about summary refs log tree commit diff
path: root/app/models
diff options
context:
space:
mode:
authorThibaut Girka <thib@sitedethib.com>2020-04-15 17:07:49 +0200
committerThibaut Girka <thib@sitedethib.com>2020-04-15 17:07:49 +0200
commit66ad30db489ddb2b3ecc98d284aabd47c9d4ae84 (patch)
treed8f035139c20e59c39bb35a74686783094c297da /app/models
parent615073df33b9a4317ac5c93fdef83c9cd34567fa (diff)
parent5524258da9bc1d62b1396d19c672d3a8335ffbc5 (diff)
Merge branch 'master' into glitch-soc/merge-upstream
Conflicts:
- `package.json`:
  No real conflict, upstream updated a dependency which is
  textually adjacent to a glitch-soc-specific dependency.
  Updated it.
- `yarn.lock`:
  No real conflict, upstream updated a dependency which is
  textually adjacent to a glitch-soc-specific dependency.
  Updated it.
Diffstat (limited to 'app/models')
-rw-r--r--app/models/account_alias.rb9
-rw-r--r--app/models/user.rb30
2 files changed, 38 insertions, 1 deletions
diff --git a/app/models/account_alias.rb b/app/models/account_alias.rb
index 66f8ce409..3d0b5d188 100644
--- a/app/models/account_alias.rb
+++ b/app/models/account_alias.rb
@@ -18,6 +18,7 @@ class AccountAlias < ApplicationRecord
   validates :acct, presence: true, domain: { acct: true }
   validates :uri, presence: true
   validates :uri, uniqueness: { scope: :account_id }
+  validate :validate_target_account
 
   before_validation :set_uri
   after_create :add_to_account
@@ -44,4 +45,12 @@ class AccountAlias < ApplicationRecord
   def remove_from_account
     account.update(also_known_as: account.also_known_as.reject { |x| x == uri })
   end
+
+  def validate_target_account
+    if uri.nil?
+      errors.add(:acct, I18n.t('migrations.errors.not_found'))
+    elsif ActivityPub::TagManager.instance.uri_for(account) == uri
+      errors.add(:acct, I18n.t('migrations.errors.move_to_self'))
+    end
+  end
 end
diff --git a/app/models/user.rb b/app/models/user.rb
index cd8a6f273..c8dbd2fd3 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -98,6 +98,7 @@ class User < ApplicationRecord
 
   before_validation :sanitize_languages
   before_create :set_approved
+  after_commit :send_pending_devise_notifications
 
   # This avoids a deprecation warning from Rails 5.1
   # It seems possible that a future release of devise-two-factor will
@@ -307,11 +308,38 @@ class User < ApplicationRecord
   protected
 
   def send_devise_notification(notification, *args)
-    devise_mailer.send(notification, self, *args).deliver_later
+    # This method can be called in `after_update` and `after_commit` hooks,
+    # but we must make sure the mailer is actually called *after* commit,
+    # otherwise it may work on stale data. To do this, figure out if we are
+    # within a transaction.
+    if ActiveRecord::Base.connection.current_transaction.try(:records)&.include?(self)
+      pending_devise_notifications << [notification, args]
+    else
+      render_and_send_devise_message(notification, *args)
+    end
   end
 
   private
 
+  def send_pending_devise_notifications
+    pending_devise_notifications.each do |notification, args|
+      render_and_send_devise_message(notification, *args)
+    end
+
+    # Empty the pending notifications array because the
+    # after_commit hook can be called multiple times which
+    # could cause multiple emails to be sent.
+    pending_devise_notifications.clear
+  end
+
+  def pending_devise_notifications
+    @pending_devise_notifications ||= []
+  end
+
+  def render_and_send_devise_message(notification, *args)
+    devise_mailer.send(notification, self, *args).deliver_later
+  end
+
   def set_approved
     self.approved = open_registrations? || valid_invitation? || external?
   end