Fix #11913master^2
@@ -0,0 +1,45 @@ | |||
# frozen_string_literal: true | |||
class Settings::Migration::RedirectsController < Settings::BaseController | |||
layout 'admin' | |||
before_action :authenticate_user! | |||
before_action :require_not_suspended! | |||
skip_before_action :require_functional! | |||
def new | |||
@redirect = Form::Redirect.new | |||
end | |||
def create | |||
@redirect = Form::Redirect.new(resource_params.merge(account: current_account)) | |||
if @redirect.valid_with_challenge?(current_user) | |||
current_account.update!(moved_to_account: @redirect.target_account) | |||
ActivityPub::UpdateDistributionWorker.perform_async(current_account.id) | |||
redirect_to settings_migration_path, notice: I18n.t('migrations.moved_msg', acct: current_account.moved_to_account.acct) | |||
else | |||
render :new | |||
end | |||
end | |||
def destroy | |||
if current_account.moved_to_account_id.present? | |||
current_account.update!(moved_to_account: nil) | |||
ActivityPub::UpdateDistributionWorker.perform_async(current_account.id) | |||
end | |||
redirect_to settings_migration_path, notice: I18n.t('migrations.cancelled_msg') | |||
end | |||
private | |||
def resource_params | |||
params.require(:form_redirect).permit(:acct, :current_password, :current_username) | |||
end | |||
def require_not_suspended! | |||
forbidden if current_account.suspended? | |||
end | |||
end |
@@ -27,15 +27,6 @@ class Settings::MigrationsController < Settings::BaseController | |||
end | |||
end | |||
def cancel | |||
if current_account.moved_to_account_id.present? | |||
current_account.update!(moved_to_account: nil) | |||
ActivityPub::UpdateDistributionWorker.perform_async(current_account.id) | |||
end | |||
redirect_to settings_migration_path, notice: I18n.t('migrations.cancelled_msg') | |||
end | |||
helper_method :on_cooldown? | |||
private | |||
@@ -47,8 +47,7 @@ class AccountMigration < ApplicationRecord | |||
end | |||
def acct=(val) | |||
val = val.to_s.strip | |||
super(val.start_with?('@') ? val[1..-1] : val) | |||
super(val.to_s.strip.gsub(/\A@/, '')) | |||
end | |||
private | |||
@@ -0,0 +1,47 @@ | |||
# frozen_string_literal: true | |||
class Form::Redirect | |||
include ActiveModel::Model | |||
attr_accessor :account, :target_account, :current_password, | |||
:current_username | |||
attr_reader :acct | |||
validates :acct, presence: true, domain: { acct: true } | |||
validate :validate_target_account | |||
def valid_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? | |||
set_target_account | |||
valid? | |||
end | |||
def acct=(val) | |||
@acct = val.to_s.strip.gsub(/\A@/, '') | |||
end | |||
private | |||
def set_target_account | |||
@target_account = ResolveAccountService.new.call(acct) | |||
rescue Goldfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error | |||
# Validation will take care of it | |||
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.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 | |||
end |
@@ -30,7 +30,18 @@ | |||
= render 'sessions' | |||
%hr.spacer/ | |||
%h3= t('auth.migrate_account') | |||
%p.muted-hint= t('auth.migrate_account_html', path: settings_migration_path) | |||
%hr.spacer/ | |||
%h3= t('migrations.incoming_migrations') | |||
%p.muted-hint= t('migrations.incoming_migrations_html', path: settings_aliases_path) | |||
- if open_deletion? && !current_account.suspended? | |||
%hr.spacer/ | |||
%h3= t('auth.delete_account') | |||
%p.muted-hint= t('auth.delete_account_html', path: settings_delete_path) |
@@ -0,0 +1,27 @@ | |||
- content_for :page_title do | |||
= t('settings.migrate') | |||
= simple_form_for @redirect, url: settings_migration_redirect_path do |f| | |||
%p.hint= t('migrations.warning.before') | |||
%ul.hint | |||
%li.warning-hint= t('migrations.warning.redirect') | |||
%li.warning-hint= t('migrations.warning.other_data') | |||
%li.warning-hint= t('migrations.warning.disabled_account') | |||
%hr.spacer/ | |||
= render 'shared/error_messages', object: @redirect | |||
.fields-row | |||
.fields-row__column.fields-group.fields-row__column-6 | |||
= f.input :acct, wrapper: :with_block_label, input_html: { autocapitalize: 'none', autocorrect: 'off' }, label: t('simple_form.labels.account_migration.acct'), hint: t('simple_form.hints.account_migration.acct') | |||
.fields-row__column.fields-group.fields-row__column-6 | |||
- if current_user.encrypted_password.present? | |||
= f.input :current_password, wrapper: :with_block_label, input_html: { :autocomplete => 'off' }, required: true | |||
- else | |||
= f.input :current_username, wrapper: :with_block_label, input_html: { :autocomplete => 'off' }, required: true | |||
.actions | |||
= f.button :button, t('migrations.set_redirect'), type: :submit, class: 'button button--destructive' |
@@ -12,28 +12,32 @@ | |||
%p.hint= t('migrations.cancel_explanation') | |||
%p.hint= link_to t('migrations.cancel'), cancel_settings_migration_path, data: { method: :post } | |||
%p.hint= link_to t('migrations.cancel'), settings_migration_redirect_path, data: { method: :delete } | |||
- else | |||
%p.hint | |||
%span.positive-hint= t('migrations.not_redirecting') | |||
%hr.spacer/ | |||
%h3= t 'migrations.proceed_with_move' | |||
%h3= t('auth.migrate_account') | |||
= simple_form_for @migration, url: settings_migration_path do |f| | |||
- if on_cooldown? | |||
%span.warning-hint= t('migrations.on_cooldown', count: ((@cooldown.cooldown_at - Time.now.utc) / 1.day.seconds).ceil) | |||
%p.hint | |||
%span.warning-hint= t('migrations.on_cooldown', count: ((@cooldown.cooldown_at - Time.now.utc) / 1.day.seconds).ceil) | |||
- else | |||
%p.hint= t('migrations.warning.before') | |||
%ul.hint | |||
%li.warning-hint= t('migrations.warning.followers') | |||
%li.warning-hint= t('migrations.warning.redirect') | |||
%li.warning-hint= t('migrations.warning.other_data') | |||
%li.warning-hint= t('migrations.warning.backreference_required') | |||
%li.warning-hint= t('migrations.warning.cooldown') | |||
%li.warning-hint= t('migrations.warning.disabled_account') | |||
%p.hint= t('migrations.warning.only_redirect_html', path: new_settings_migration_redirect_path) | |||
%hr.spacer/ | |||
= render 'shared/error_messages', object: @migration | |||
@@ -831,13 +831,16 @@ en: | |||
past_migrations: Past migrations | |||
proceed_with_move: Move followers | |||
redirecting_to: Your account is redirecting to %{acct}. | |||
set_redirect: Set redirect | |||
warning: | |||
backreference_required: The new account must first be configured to back-reference this one | |||
before: 'Before proceeding, please read these notes carefully:' | |||
cooldown: After moving there is a cooldown period during which you will not be able to move again | |||
disabled_account: Your current account will not be fully usable afterwards. However, you will have access to data export as well as re-activation. | |||
followers: This action will move all followers from the current account to the new account | |||
only_redirect_html: Alternatively, you can <a href="%{path}">only put up a redirect on your profile</a>. | |||
other_data: No other data will be moved automatically | |||
redirect: Your current account's profile will be updated with a redirect notice and be excluded from searches | |||
moderation: | |||
title: Moderation | |||
notification_mailer: | |||
@@ -134,11 +134,10 @@ Rails.application.routes.draw do | |||
end | |||
resource :delete, only: [:show, :destroy] | |||
resource :migration, only: [:show, :create] | |||
resource :migration, only: [:show, :create] do | |||
collection do | |||
post :cancel | |||
end | |||
namespace :migration do | |||
resource :redirect, only: [:new, :create, :destroy] | |||
end | |||
resources :aliases, only: [:index, :create, :destroy] | |||