]> git.openstreetmap.org Git - rails.git/blobdiff - app/models/user.rb
Merge remote-tracking branch 'upstream/pull/3345'
[rails.git] / app / models / user.rb
index 023604801cbf49183279acd55449a587e54c1e50..7a0d069927fa5da20e6aeecee4a52a841d76b1e2 100644 (file)
@@ -45,7 +45,7 @@
 
 class User < ApplicationRecord
   require "digest"
-  require "xml/libxml"
+  include AASM
 
   has_many :traces, -> { where(:visible => true) }
   has_many :diary_entries, -> { order(:created_at => :desc) }
@@ -114,7 +114,8 @@ class User < ApplicationRecord
   validates_email_format_of :email, :if => proc { |u| u.email_changed? }
   validates_email_format_of :new_email, :allow_blank => true, :if => proc { |u| u.new_email_changed? }
 
-  after_initialize :set_defaults
+  alias_attribute :created_at, :creation_time
+
   before_save :encrypt_password
   before_save :update_tile
   after_save :spam_check
@@ -158,6 +159,64 @@ class User < ApplicationRecord
     user
   end
 
+  aasm :column => :status, :no_direct_assignment => true do
+    state :pending, :initial => true
+    state :active
+    state :confirmed
+    state :suspended
+    state :deleted
+
+    # A normal account is active
+    event :activate do
+      transitions :from => :pending, :to => :active
+    end
+
+    # Used in test suite, not something that we would normally need to do.
+    if Rails.env.test?
+      event :deactivate do
+        transitions :from => :active, :to => :pending
+      end
+    end
+
+    # To confirm an account is used to override the spam scoring
+    event :confirm do
+      transitions :from => [:pending, :active, :suspended], :to => :confirmed
+    end
+
+    # To unconfirm an account is to make it subject to future spam scoring again
+    event :unconfirm do
+      transitions :from => :confirmed, :to => :active
+    end
+
+    # Accounts can be automatically suspended by spam_check
+    event :suspend do
+      transitions :from => [:pending, :active], :to => :suspended
+    end
+
+    # Unsuspending an account moves it back to active without overriding the spam scoring
+    event :unsuspend do
+      transitions :from => :suspended, :to => :active
+    end
+
+    # Mark the account as deleted but keep all data intact
+    event :hide do
+      transitions :from => [:pending, :active, :confirmed, :suspended], :to => :deleted
+    end
+
+    event :unhide do
+      transitions :from => [:deleted], :to => :active
+    end
+
+    # Mark the account as deleted and remove personal data
+    event :soft_destroy do
+      before do
+        remove_personal_data
+      end
+
+      transitions :from => [:pending, :active, :confirmed, :suspended], :to => :deleted
+    end
+  end
+
   def description
     RichText.new(self[:description_format], self[:description])
   end
@@ -241,8 +300,8 @@ class User < ApplicationRecord
   end
 
   ##
-  # delete a user - leave the account but purge most personal data
-  def delete
+  # remove personal data - leave the account but purge most personal data
+  def remove_personal_data
     avatar.purge_later
 
     self.display_name = "user_#{id}"
@@ -253,7 +312,6 @@ class User < ApplicationRecord
     self.new_email = nil
     self.auth_provider = nil
     self.auth_uid = nil
-    self.status = "deleted"
 
     save
   end
@@ -279,7 +337,7 @@ class User < ApplicationRecord
   ##
   # perform a spam check on a user
   def spam_check
-    update(:status => "suspended") if status == "active" && spam_score > Settings.spam_threshold
+    suspend! if may_suspend? && spam_score > Settings.spam_threshold
   end
 
   ##
@@ -308,7 +366,7 @@ class User < ApplicationRecord
   end
 
   def max_messages_per_hour
-    account_age_in_seconds = Time.now.utc - creation_time
+    account_age_in_seconds = Time.now.utc - created_at
     account_age_in_hours = account_age_in_seconds / 3600
     recent_messages = messages.where("sent_on >= ?", Time.now.utc - 3600).count
     active_reports = issues.with_status(:open).sum(:reports_count)
@@ -317,7 +375,7 @@ class User < ApplicationRecord
   end
 
   def max_friends_per_hour
-    account_age_in_seconds = Time.now.utc - creation_time
+    account_age_in_seconds = Time.now.utc - created_at
     account_age_in_hours = account_age_in_seconds / 3600
     recent_friends = Friendship.where(:befriendee => self).where("created_at >= ?", Time.now.utc - 3600).count
     active_reports = issues.with_status(:open).sum(:reports_count)
@@ -327,10 +385,6 @@ class User < ApplicationRecord
 
   private
 
-  def set_defaults
-    self.creation_time = Time.now.getutc unless attribute_present?(:creation_time)
-  end
-
   def encrypt_password
     if pass_crypt_confirmation
       self.pass_crypt, self.pass_salt = PasswordHash.create(pass_crypt)