0
0
Fork 0

Add account migration UI (#11846)

Fix #10736

- Change data export to be available for non-functional accounts
- Change non-functional accounts to include redirecting accounts
This commit is contained in:
Eugen Rochko 2019-09-19 20:58:19 +02:00 committed by GitHub
parent b6df9c1067
commit 3ed94dcc1a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 542 additions and 73 deletions

View file

@ -0,0 +1,41 @@
# frozen_string_literal: true
# == Schema Information
#
# Table name: account_aliases
#
# id :bigint(8) not null, primary key
# account_id :bigint(8)
# acct :string default(""), not null
# uri :string default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
#
class AccountAlias < ApplicationRecord
belongs_to :account
validates :acct, presence: true, domain: { acct: true }
validates :uri, presence: true
before_validation :set_uri
after_create :add_to_account
after_destroy :remove_from_account
private
def set_uri
target_account = ResolveAccountService.new.call(acct)
self.uri = ActivityPub::TagManager.instance.uri_for(target_account) unless target_account.nil?
rescue Goldfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error
# Validation will take care of it
end
def add_to_account
account.update(also_known_as: account.also_known_as + [uri])
end
def remove_from_account
account.update(also_known_as: account.also_known_as.reject { |x| x == uri })
end
end

View file

@ -0,0 +1,74 @@
# frozen_string_literal: true
# == Schema Information
#
# Table name: account_migrations
#
# id :bigint(8) not null, primary key
# account_id :bigint(8)
# acct :string default(""), not null
# followers_count :bigint(8) default(0), not null
# target_account_id :bigint(8)
# created_at :datetime not null
# updated_at :datetime not null
#
class AccountMigration < ApplicationRecord
COOLDOWN_PERIOD = 30.days.freeze
belongs_to :account
belongs_to :target_account, class_name: 'Account'
before_validation :set_target_account
before_validation :set_followers_count
validates :acct, presence: true, domain: { acct: true }
validate :validate_migration_cooldown
validate :validate_target_account
scope :within_cooldown, ->(now = Time.now.utc) { where(arel_table[:created_at].gteq(now - COOLDOWN_PERIOD)) }
attr_accessor :current_password, :current_username
def save_with_challenge(current_user)
if current_user.encrypted_password.present?
errors.add(:current_password, :invalid) unless current_user.valid_password?(current_password)
else
errors.add(:current_username, :invalid) unless account.username == current_username
end
return false unless errors.empty?
save
end
def cooldown_at
created_at + COOLDOWN_PERIOD
end
private
def set_target_account
self.target_account = ResolveAccountService.new.call(acct)
rescue Goldfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error
# Validation will take care of it
end
def set_followers_count
self.followers_count = account.followers_count
end
def validate_target_account
if target_account.nil?
errors.add(:acct, I18n.t('migrations.errors.not_found'))
else
errors.add(:acct, I18n.t('migrations.errors.missing_also_known_as')) unless target_account.also_known_as.include?(ActivityPub::TagManager.instance.uri_for(account))
errors.add(:acct, I18n.t('migrations.errors.already_moved')) if account.moved_to_account_id.present? && account.moved_to_account_id == target_account.id
errors.add(:acct, I18n.t('migrations.errors.move_to_self')) if account.id == target_account.id
end
end
def validate_migration_cooldown
errors.add(:base, I18n.t('migrations.errors.on_cooldown')) if account.migrations.within_cooldown.exists?
end
end

View file

@ -52,6 +52,8 @@ module AccountAssociations
# Account migrations
belongs_to :moved_to_account, class_name: 'Account', optional: true
has_many :migrations, class_name: 'AccountMigration', dependent: :destroy, inverse_of: :account
has_many :aliases, class_name: 'AccountAlias', dependent: :destroy, inverse_of: :account
# Hashtags
has_and_belongs_to_many :tags

View file

@ -1,25 +0,0 @@
# frozen_string_literal: true
class Form::Migration
include ActiveModel::Validations
attr_accessor :acct, :account
def initialize(attrs = {})
@account = attrs[:account]
@acct = attrs[:account].acct unless @account.nil?
@acct = attrs[:acct].gsub(/\A@/, '').strip unless attrs[:acct].nil?
end
def valid?
return false unless super
set_account
errors.empty?
end
private
def set_account
self.account = (ResolveAccountService.new.call(acct) if account.nil? && acct.present?)
end
end

View file

@ -49,7 +49,7 @@ class RemoteFollow
end
def fetch_template!
return missing_resource if acct.blank?
return missing_resource_error if acct.blank?
_, domain = acct.split('@')

View file

@ -168,7 +168,7 @@ class User < ApplicationRecord
end
def functional?
confirmed? && approved? && !disabled? && !account.suspended?
confirmed? && approved? && !disabled? && !account.suspended? && account.moved_to_account_id.nil?
end
def unconfirmed_or_pending?