Add ability to disable login and mark accounts as memorial (#5615)
Fix #5597
This commit is contained in:
		
							parent
							
								
									7a5fb781ce
								
							
						
					
					
						commit
						7f1a0241c1
					
				
					 17 changed files with 168 additions and 39 deletions
				
			
		| 
						 | 
					@ -2,8 +2,9 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module Admin
 | 
					module Admin
 | 
				
			||||||
  class AccountsController < BaseController
 | 
					  class AccountsController < BaseController
 | 
				
			||||||
    before_action :set_account, only: [:show, :subscribe, :unsubscribe, :redownload]
 | 
					    before_action :set_account, only: [:show, :subscribe, :unsubscribe, :redownload, :enable, :disable, :memorialize]
 | 
				
			||||||
    before_action :require_remote_account!, only: [:subscribe, :unsubscribe, :redownload]
 | 
					    before_action :require_remote_account!, only: [:subscribe, :unsubscribe, :redownload]
 | 
				
			||||||
 | 
					    before_action :require_local_account!, only: [:enable, :disable, :memorialize]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def index
 | 
					    def index
 | 
				
			||||||
      @accounts = filtered_accounts.page(params[:page])
 | 
					      @accounts = filtered_accounts.page(params[:page])
 | 
				
			||||||
| 
						 | 
					@ -24,6 +25,21 @@ module Admin
 | 
				
			||||||
      redirect_to admin_account_path(@account.id)
 | 
					      redirect_to admin_account_path(@account.id)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def memorialize
 | 
				
			||||||
 | 
					      @account.memorialize!
 | 
				
			||||||
 | 
					      redirect_to admin_account_path(@account.id)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def enable
 | 
				
			||||||
 | 
					      @account.user.enable!
 | 
				
			||||||
 | 
					      redirect_to admin_account_path(@account.id)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def disable
 | 
				
			||||||
 | 
					      @account.user.disable!
 | 
				
			||||||
 | 
					      redirect_to admin_account_path(@account.id)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def redownload
 | 
					    def redownload
 | 
				
			||||||
      @account.reset_avatar!
 | 
					      @account.reset_avatar!
 | 
				
			||||||
      @account.reset_header!
 | 
					      @account.reset_header!
 | 
				
			||||||
| 
						 | 
					@ -42,6 +58,10 @@ module Admin
 | 
				
			||||||
      redirect_to admin_account_path(@account.id) if @account.local?
 | 
					      redirect_to admin_account_path(@account.id) if @account.local?
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def require_local_account!
 | 
				
			||||||
 | 
					      redirect_to admin_account_path(@account.id) unless @account.local? && @account.user.present?
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def filtered_accounts
 | 
					    def filtered_accounts
 | 
				
			||||||
      AccountFilter.new(filter_params).results
 | 
					      AccountFilter.new(filter_params).results
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,7 @@ module Admin
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def destroy
 | 
					    def destroy
 | 
				
			||||||
      @account.update(suspended: false)
 | 
					      @account.unsuspend!
 | 
				
			||||||
      redirect_to admin_accounts_path
 | 
					      redirect_to admin_accounts_path
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,5 @@
 | 
				
			||||||
.landing-strip {
 | 
					.landing-strip,
 | 
				
			||||||
 | 
					.memoriam-strip {
 | 
				
			||||||
  background: rgba(darken($ui-base-color, 7%), 0.8);
 | 
					  background: rgba(darken($ui-base-color, 7%), 0.8);
 | 
				
			||||||
  color: $ui-primary-color;
 | 
					  color: $ui-primary-color;
 | 
				
			||||||
  font-weight: 400;
 | 
					  font-weight: 400;
 | 
				
			||||||
| 
						 | 
					@ -29,3 +30,7 @@
 | 
				
			||||||
    margin-bottom: 0;
 | 
					    margin-bottom: 0;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.memoriam-strip {
 | 
				
			||||||
 | 
					  background: rgba($base-shadow-color, 0.7);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,8 @@ class NotificationMailer < ApplicationMailer
 | 
				
			||||||
    @me     = recipient
 | 
					    @me     = recipient
 | 
				
			||||||
    @status = notification.target_status
 | 
					    @status = notification.target_status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return if @me.user.disabled?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    locale_for_account(@me) do
 | 
					    locale_for_account(@me) do
 | 
				
			||||||
      thread_by_conversation(@status.conversation)
 | 
					      thread_by_conversation(@status.conversation)
 | 
				
			||||||
      mail to: @me.user.email, subject: I18n.t('notification_mailer.mention.subject', name: @status.account.acct)
 | 
					      mail to: @me.user.email, subject: I18n.t('notification_mailer.mention.subject', name: @status.account.acct)
 | 
				
			||||||
| 
						 | 
					@ -17,6 +19,8 @@ class NotificationMailer < ApplicationMailer
 | 
				
			||||||
    @me      = recipient
 | 
					    @me      = recipient
 | 
				
			||||||
    @account = notification.from_account
 | 
					    @account = notification.from_account
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return if @me.user.disabled?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    locale_for_account(@me) do
 | 
					    locale_for_account(@me) do
 | 
				
			||||||
      mail to: @me.user.email, subject: I18n.t('notification_mailer.follow.subject', name: @account.acct)
 | 
					      mail to: @me.user.email, subject: I18n.t('notification_mailer.follow.subject', name: @account.acct)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
| 
						 | 
					@ -27,6 +31,8 @@ class NotificationMailer < ApplicationMailer
 | 
				
			||||||
    @account = notification.from_account
 | 
					    @account = notification.from_account
 | 
				
			||||||
    @status  = notification.target_status
 | 
					    @status  = notification.target_status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return if @me.user.disabled?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    locale_for_account(@me) do
 | 
					    locale_for_account(@me) do
 | 
				
			||||||
      thread_by_conversation(@status.conversation)
 | 
					      thread_by_conversation(@status.conversation)
 | 
				
			||||||
      mail to: @me.user.email, subject: I18n.t('notification_mailer.favourite.subject', name: @account.acct)
 | 
					      mail to: @me.user.email, subject: I18n.t('notification_mailer.favourite.subject', name: @account.acct)
 | 
				
			||||||
| 
						 | 
					@ -38,6 +44,8 @@ class NotificationMailer < ApplicationMailer
 | 
				
			||||||
    @account = notification.from_account
 | 
					    @account = notification.from_account
 | 
				
			||||||
    @status  = notification.target_status
 | 
					    @status  = notification.target_status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return if @me.user.disabled?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    locale_for_account(@me) do
 | 
					    locale_for_account(@me) do
 | 
				
			||||||
      thread_by_conversation(@status.conversation)
 | 
					      thread_by_conversation(@status.conversation)
 | 
				
			||||||
      mail to: @me.user.email, subject: I18n.t('notification_mailer.reblog.subject', name: @account.acct)
 | 
					      mail to: @me.user.email, subject: I18n.t('notification_mailer.reblog.subject', name: @account.acct)
 | 
				
			||||||
| 
						 | 
					@ -48,6 +56,8 @@ class NotificationMailer < ApplicationMailer
 | 
				
			||||||
    @me      = recipient
 | 
					    @me      = recipient
 | 
				
			||||||
    @account = notification.from_account
 | 
					    @account = notification.from_account
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return if @me.user.disabled?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    locale_for_account(@me) do
 | 
					    locale_for_account(@me) do
 | 
				
			||||||
      mail to: @me.user.email, subject: I18n.t('notification_mailer.follow_request.subject', name: @account.acct)
 | 
					      mail to: @me.user.email, subject: I18n.t('notification_mailer.follow_request.subject', name: @account.acct)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
| 
						 | 
					@ -59,15 +69,11 @@ class NotificationMailer < ApplicationMailer
 | 
				
			||||||
    @notifications = Notification.where(account: @me, activity_type: 'Mention').where('created_at > ?', @since)
 | 
					    @notifications = Notification.where(account: @me, activity_type: 'Mention').where('created_at > ?', @since)
 | 
				
			||||||
    @follows_since = Notification.where(account: @me, activity_type: 'Follow').where('created_at > ?', @since).count
 | 
					    @follows_since = Notification.where(account: @me, activity_type: 'Follow').where('created_at > ?', @since).count
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return if @notifications.empty?
 | 
					    return if @me.user.disabled? || @notifications.empty?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    locale_for_account(@me) do
 | 
					    locale_for_account(@me) do
 | 
				
			||||||
      mail to: @me.user.email,
 | 
					      mail to: @me.user.email,
 | 
				
			||||||
           subject: I18n.t(
 | 
					           subject: I18n.t(:subject, scope: [:notification_mailer, :digest], count: @notifications.size)
 | 
				
			||||||
             :subject,
 | 
					 | 
				
			||||||
             scope: [:notification_mailer, :digest],
 | 
					 | 
				
			||||||
             count: @notifications.size
 | 
					 | 
				
			||||||
           )
 | 
					 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,6 +10,8 @@ class UserMailer < Devise::Mailer
 | 
				
			||||||
    @token    = token
 | 
					    @token    = token
 | 
				
			||||||
    @instance = Rails.configuration.x.local_domain
 | 
					    @instance = Rails.configuration.x.local_domain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return if @resource.disabled?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    I18n.with_locale(@resource.locale || I18n.default_locale) do
 | 
					    I18n.with_locale(@resource.locale || I18n.default_locale) do
 | 
				
			||||||
      mail to: @resource.unconfirmed_email.blank? ? @resource.email : @resource.unconfirmed_email, subject: I18n.t('devise.mailer.confirmation_instructions.subject', instance: @instance)
 | 
					      mail to: @resource.unconfirmed_email.blank? ? @resource.email : @resource.unconfirmed_email, subject: I18n.t('devise.mailer.confirmation_instructions.subject', instance: @instance)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
| 
						 | 
					@ -20,6 +22,8 @@ class UserMailer < Devise::Mailer
 | 
				
			||||||
    @token    = token
 | 
					    @token    = token
 | 
				
			||||||
    @instance = Rails.configuration.x.local_domain
 | 
					    @instance = Rails.configuration.x.local_domain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return if @resource.disabled?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    I18n.with_locale(@resource.locale || I18n.default_locale) do
 | 
					    I18n.with_locale(@resource.locale || I18n.default_locale) do
 | 
				
			||||||
      mail to: @resource.email, subject: I18n.t('devise.mailer.reset_password_instructions.subject')
 | 
					      mail to: @resource.email, subject: I18n.t('devise.mailer.reset_password_instructions.subject')
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
| 
						 | 
					@ -29,6 +33,8 @@ class UserMailer < Devise::Mailer
 | 
				
			||||||
    @resource = user
 | 
					    @resource = user
 | 
				
			||||||
    @instance = Rails.configuration.x.local_domain
 | 
					    @instance = Rails.configuration.x.local_domain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return if @resource.disabled?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    I18n.with_locale(@resource.locale || I18n.default_locale) do
 | 
					    I18n.with_locale(@resource.locale || I18n.default_locale) do
 | 
				
			||||||
      mail to: @resource.email, subject: I18n.t('devise.mailer.password_change.subject')
 | 
					      mail to: @resource.email, subject: I18n.t('devise.mailer.password_change.subject')
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,6 +41,7 @@
 | 
				
			||||||
#  shared_inbox_url        :string           default(""), not null
 | 
					#  shared_inbox_url        :string           default(""), not null
 | 
				
			||||||
#  followers_url           :string           default(""), not null
 | 
					#  followers_url           :string           default(""), not null
 | 
				
			||||||
#  protocol                :integer          default("ostatus"), not null
 | 
					#  protocol                :integer          default("ostatus"), not null
 | 
				
			||||||
 | 
					#  memorial                :boolean          default(FALSE), not null
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Account < ApplicationRecord
 | 
					class Account < ApplicationRecord
 | 
				
			||||||
| 
						 | 
					@ -150,6 +151,20 @@ class Account < ApplicationRecord
 | 
				
			||||||
    ResolveRemoteAccountService.new.call(acct)
 | 
					    ResolveRemoteAccountService.new.call(acct)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def unsuspend!
 | 
				
			||||||
 | 
					    transaction do
 | 
				
			||||||
 | 
					      user&.enable! if local?
 | 
				
			||||||
 | 
					      update!(suspended: false)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def memorialize!
 | 
				
			||||||
 | 
					    transaction do
 | 
				
			||||||
 | 
					      user&.disable! if local?
 | 
				
			||||||
 | 
					      update!(memorial: true)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def keypair
 | 
					  def keypair
 | 
				
			||||||
    @keypair ||= OpenSSL::PKey::RSA.new(private_key || public_key)
 | 
					    @keypair ||= OpenSSL::PKey::RSA.new(private_key || public_key)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,6 @@
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
#  id                        :integer          not null, primary key
 | 
					#  id                        :integer          not null, primary key
 | 
				
			||||||
#  email                     :string           default(""), not null
 | 
					#  email                     :string           default(""), not null
 | 
				
			||||||
#  account_id                :integer          not null
 | 
					 | 
				
			||||||
#  created_at                :datetime         not null
 | 
					#  created_at                :datetime         not null
 | 
				
			||||||
#  updated_at                :datetime         not null
 | 
					#  updated_at                :datetime         not null
 | 
				
			||||||
#  encrypted_password        :string           default(""), not null
 | 
					#  encrypted_password        :string           default(""), not null
 | 
				
			||||||
| 
						 | 
					@ -31,10 +30,13 @@
 | 
				
			||||||
#  last_emailed_at           :datetime
 | 
					#  last_emailed_at           :datetime
 | 
				
			||||||
#  otp_backup_codes          :string           is an Array
 | 
					#  otp_backup_codes          :string           is an Array
 | 
				
			||||||
#  filtered_languages        :string           default([]), not null, is an Array
 | 
					#  filtered_languages        :string           default([]), not null, is an Array
 | 
				
			||||||
 | 
					#  account_id                :integer          not null
 | 
				
			||||||
 | 
					#  disabled                  :boolean          default(FALSE), not null
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class User < ApplicationRecord
 | 
					class User < ApplicationRecord
 | 
				
			||||||
  include Settings::Extend
 | 
					  include Settings::Extend
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ACTIVE_DURATION = 14.days
 | 
					  ACTIVE_DURATION = 14.days
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  devise :registerable, :recoverable,
 | 
					  devise :registerable, :recoverable,
 | 
				
			||||||
| 
						 | 
					@ -72,12 +74,26 @@ class User < ApplicationRecord
 | 
				
			||||||
    confirmed_at.present?
 | 
					    confirmed_at.present?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def disable!
 | 
				
			||||||
 | 
					    update!(disabled: true,
 | 
				
			||||||
 | 
					            last_sign_in_at: current_sign_in_at,
 | 
				
			||||||
 | 
					            current_sign_in_at: nil)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def enable!
 | 
				
			||||||
 | 
					    update!(disabled: false)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def disable_two_factor!
 | 
					  def disable_two_factor!
 | 
				
			||||||
    self.otp_required_for_login = false
 | 
					    self.otp_required_for_login = false
 | 
				
			||||||
    otp_backup_codes&.clear
 | 
					    otp_backup_codes&.clear
 | 
				
			||||||
    save!
 | 
					    save!
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def active_for_authentication?
 | 
				
			||||||
 | 
					    super && !disabled?
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def setting_default_privacy
 | 
					  def setting_default_privacy
 | 
				
			||||||
    settings.default_privacy || (account.locked? ? 'private' : 'public')
 | 
					    settings.default_privacy || (account.locked? ? 'private' : 'public')
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,22 +1,27 @@
 | 
				
			||||||
# frozen_string_literal: true
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SuspendAccountService < BaseService
 | 
					class SuspendAccountService < BaseService
 | 
				
			||||||
  def call(account, remove_user = false)
 | 
					  def call(account, options = {})
 | 
				
			||||||
    @account = account
 | 
					    @account = account
 | 
				
			||||||
 | 
					    @options = options
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    purge_user if remove_user
 | 
					    purge_user!
 | 
				
			||||||
    purge_profile
 | 
					    purge_profile!
 | 
				
			||||||
    purge_content
 | 
					    purge_content!
 | 
				
			||||||
    unsubscribe_push_subscribers
 | 
					    unsubscribe_push_subscribers!
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def purge_user
 | 
					  def purge_user!
 | 
				
			||||||
    @account.user.destroy
 | 
					    if @options[:remove_user]
 | 
				
			||||||
 | 
					      @account.user&.destroy
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      @account.user&.disable!
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def purge_content
 | 
					  def purge_content!
 | 
				
			||||||
    @account.statuses.reorder(nil).find_in_batches do |statuses|
 | 
					    @account.statuses.reorder(nil).find_in_batches do |statuses|
 | 
				
			||||||
      BatchedRemoveStatusService.new.call(statuses)
 | 
					      BatchedRemoveStatusService.new.call(statuses)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
| 
						 | 
					@ -33,7 +38,7 @@ class SuspendAccountService < BaseService
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def purge_profile
 | 
					  def purge_profile!
 | 
				
			||||||
    @account.suspended    = true
 | 
					    @account.suspended    = true
 | 
				
			||||||
    @account.display_name = ''
 | 
					    @account.display_name = ''
 | 
				
			||||||
    @account.note         = ''
 | 
					    @account.note         = ''
 | 
				
			||||||
| 
						 | 
					@ -42,7 +47,7 @@ class SuspendAccountService < BaseService
 | 
				
			||||||
    @account.save!
 | 
					    @account.save!
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def unsubscribe_push_subscribers
 | 
					  def unsubscribe_push_subscribers!
 | 
				
			||||||
    destroy_all(@account.subscriptions)
 | 
					    destroy_all(@account.subscriptions)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
.card.h-card.p-author{ style: "background-image: url(#{account.header.url(:original)})" }
 | 
					.card.h-card.p-author{ style: "background-image: url(#{account.header.url(:original)})" }
 | 
				
			||||||
  .card__illustration
 | 
					  .card__illustration
 | 
				
			||||||
 | 
					    - unless account.memorial?
 | 
				
			||||||
      - if user_signed_in? && current_account.id != account.id && !current_account.requested?(account)
 | 
					      - if user_signed_in? && current_account.id != account.id && !current_account.requested?(account)
 | 
				
			||||||
        .controls
 | 
					        .controls
 | 
				
			||||||
          - if current_account.following?(account)
 | 
					          - if current_account.following?(account)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,9 @@
 | 
				
			||||||
  = opengraph 'og:type', 'profile'
 | 
					  = opengraph 'og:type', 'profile'
 | 
				
			||||||
  = render 'og', account: @account, url: short_account_url(@account, only_path: false)
 | 
					  = render 'og', account: @account, url: short_account_url(@account, only_path: false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- if show_landing_strip?
 | 
					- if @account.memorial?
 | 
				
			||||||
 | 
					  .memoriam-strip= t('in_memoriam_html')
 | 
				
			||||||
 | 
					- elsif show_landing_strip?
 | 
				
			||||||
  = render partial: 'shared/landing_strip', locals: { account: @account }
 | 
					  = render partial: 'shared/landing_strip', locals: { account: @account }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.h-feed
 | 
					.h-feed
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,15 @@
 | 
				
			||||||
        %tr
 | 
					        %tr
 | 
				
			||||||
          %th= t('admin.accounts.email')
 | 
					          %th= t('admin.accounts.email')
 | 
				
			||||||
          %td= @account.user_email
 | 
					          %td= @account.user_email
 | 
				
			||||||
 | 
					        %tr
 | 
				
			||||||
 | 
					          %th= t('admin.accounts.login_status')
 | 
				
			||||||
 | 
					          %td
 | 
				
			||||||
 | 
					            - if @account.user&.disabled?
 | 
				
			||||||
 | 
					              = t('admin.accounts.disabled')
 | 
				
			||||||
 | 
					              = table_link_to 'unlock', t('admin.accounts.enable'), enable_admin_account_path(@account.id), method: :post
 | 
				
			||||||
 | 
					            - else
 | 
				
			||||||
 | 
					              = t('admin.accounts.enabled')
 | 
				
			||||||
 | 
					              = table_link_to 'lock', t('admin.accounts.disable'), disable_admin_account_path(@account.id), method: :post
 | 
				
			||||||
        %tr
 | 
					        %tr
 | 
				
			||||||
          %th= t('admin.accounts.most_recent_ip')
 | 
					          %th= t('admin.accounts.most_recent_ip')
 | 
				
			||||||
          %td= @account.user_current_sign_in_ip
 | 
					          %td= @account.user_current_sign_in_ip
 | 
				
			||||||
| 
						 | 
					@ -65,6 +74,8 @@
 | 
				
			||||||
      = link_to t('admin.accounts.reset_password'), admin_account_reset_path(@account.id), method: :create, class: 'button'
 | 
					      = link_to t('admin.accounts.reset_password'), admin_account_reset_path(@account.id), method: :create, class: 'button'
 | 
				
			||||||
      - if @account.user&.otp_required_for_login?
 | 
					      - if @account.user&.otp_required_for_login?
 | 
				
			||||||
        = link_to t('admin.accounts.disable_two_factor_authentication'), admin_user_two_factor_authentication_path(@account.user.id), method: :delete, class: 'button'
 | 
					        = link_to t('admin.accounts.disable_two_factor_authentication'), admin_user_two_factor_authentication_path(@account.user.id), method: :delete, class: 'button'
 | 
				
			||||||
 | 
					      - unless @account.memorial?
 | 
				
			||||||
 | 
					        = link_to t('admin.accounts.memorialize'), memorialize_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button'
 | 
				
			||||||
    - else
 | 
					    - else
 | 
				
			||||||
      = link_to t('admin.accounts.redownload'), redownload_admin_account_path(@account.id), method: :post, class: 'button'
 | 
					      = link_to t('admin.accounts.redownload'), redownload_admin_account_path(@account.id), method: :post, class: 'button'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,6 @@ class Admin::SuspensionWorker
 | 
				
			||||||
  sidekiq_options queue: 'pull'
 | 
					  sidekiq_options queue: 'pull'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def perform(account_id, remove_user = false)
 | 
					  def perform(account_id, remove_user = false)
 | 
				
			||||||
    SuspendAccountService.new.call(Account.find(account_id), remove_user)
 | 
					    SuspendAccountService.new.call(Account.find(account_id), remove_user: remove_user)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,11 +62,15 @@ en:
 | 
				
			||||||
      by_domain: Domain
 | 
					      by_domain: Domain
 | 
				
			||||||
      confirm: Confirm
 | 
					      confirm: Confirm
 | 
				
			||||||
      confirmed: Confirmed
 | 
					      confirmed: Confirmed
 | 
				
			||||||
 | 
					      disable: Disable
 | 
				
			||||||
      disable_two_factor_authentication: Disable 2FA
 | 
					      disable_two_factor_authentication: Disable 2FA
 | 
				
			||||||
 | 
					      disabled: Disabled
 | 
				
			||||||
      display_name: Display name
 | 
					      display_name: Display name
 | 
				
			||||||
      domain: Domain
 | 
					      domain: Domain
 | 
				
			||||||
      edit: Edit
 | 
					      edit: Edit
 | 
				
			||||||
      email: E-mail
 | 
					      email: E-mail
 | 
				
			||||||
 | 
					      enable: Enable
 | 
				
			||||||
 | 
					      enabled: Enabled
 | 
				
			||||||
      feed_url: Feed URL
 | 
					      feed_url: Feed URL
 | 
				
			||||||
      followers: Followers
 | 
					      followers: Followers
 | 
				
			||||||
      followers_url: Followers URL
 | 
					      followers_url: Followers URL
 | 
				
			||||||
| 
						 | 
					@ -78,7 +82,9 @@ en:
 | 
				
			||||||
        local: Local
 | 
					        local: Local
 | 
				
			||||||
        remote: Remote
 | 
					        remote: Remote
 | 
				
			||||||
        title: Location
 | 
					        title: Location
 | 
				
			||||||
 | 
					      login_status: Login status
 | 
				
			||||||
      media_attachments: Media attachments
 | 
					      media_attachments: Media attachments
 | 
				
			||||||
 | 
					      memorialize: Turn into memoriam
 | 
				
			||||||
      moderation:
 | 
					      moderation:
 | 
				
			||||||
        all: All
 | 
					        all: All
 | 
				
			||||||
        silenced: Silenced
 | 
					        silenced: Silenced
 | 
				
			||||||
| 
						 | 
					@ -379,6 +385,7 @@ en:
 | 
				
			||||||
      following: Following list
 | 
					      following: Following list
 | 
				
			||||||
      muting: Muting list
 | 
					      muting: Muting list
 | 
				
			||||||
    upload: Upload
 | 
					    upload: Upload
 | 
				
			||||||
 | 
					  in_memoriam_html: In Memoriam.
 | 
				
			||||||
  landing_strip_html: "<strong>%{name}</strong> is a user on %{link_to_root_path}. You can follow them or interact with them if you have an account anywhere in the fediverse."
 | 
					  landing_strip_html: "<strong>%{name}</strong> is a user on %{link_to_root_path}. You can follow them or interact with them if you have an account anywhere in the fediverse."
 | 
				
			||||||
  landing_strip_signup_html: If you don't, you can <a href="%{sign_up_path}">sign up here</a>.
 | 
					  landing_strip_signup_html: If you don't, you can <a href="%{sign_up_path}">sign up here</a>.
 | 
				
			||||||
  media_attachments:
 | 
					  media_attachments:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -126,7 +126,10 @@ Rails.application.routes.draw do
 | 
				
			||||||
      member do
 | 
					      member do
 | 
				
			||||||
        post :subscribe
 | 
					        post :subscribe
 | 
				
			||||||
        post :unsubscribe
 | 
					        post :unsubscribe
 | 
				
			||||||
 | 
					        post :enable
 | 
				
			||||||
 | 
					        post :disable
 | 
				
			||||||
        post :redownload
 | 
					        post :redownload
 | 
				
			||||||
 | 
					        post :memorialize
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      resource :reset, only: [:create]
 | 
					      resource :reset, only: [:create]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										15
									
								
								db/migrate/20171107143332_add_memorial_to_accounts.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								db/migrate/20171107143332_add_memorial_to_accounts.rb
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,15 @@
 | 
				
			||||||
 | 
					require Rails.root.join('lib', 'mastodon', 'migration_helpers')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AddMemorialToAccounts < ActiveRecord::Migration[5.1]
 | 
				
			||||||
 | 
					  include Mastodon::MigrationHelpers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  disable_ddl_transaction!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def up
 | 
				
			||||||
 | 
					    safety_assured { add_column_with_default :accounts, :memorial, :bool, default: false }
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def down
 | 
				
			||||||
 | 
					    remove_column :accounts, :memorial
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										15
									
								
								db/migrate/20171107143624_add_disabled_to_users.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								db/migrate/20171107143624_add_disabled_to_users.rb
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,15 @@
 | 
				
			||||||
 | 
					require Rails.root.join('lib', 'mastodon', 'migration_helpers')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AddDisabledToUsers < ActiveRecord::Migration[5.1]
 | 
				
			||||||
 | 
					  include Mastodon::MigrationHelpers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  disable_ddl_transaction!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def up
 | 
				
			||||||
 | 
					    safety_assured { add_column_with_default :users, :disabled, :bool, default: false }
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def down
 | 
				
			||||||
 | 
					    remove_column :users, :disabled
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,7 @@
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# It's strongly recommended that you check this file into your version control system.
 | 
					# It's strongly recommended that you check this file into your version control system.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ActiveRecord::Schema.define(version: 20171020084748) do
 | 
					ActiveRecord::Schema.define(version: 20171107143624) do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # These are extensions that must be enabled in order to support this database
 | 
					  # These are extensions that must be enabled in order to support this database
 | 
				
			||||||
  enable_extension "plpgsql"
 | 
					  enable_extension "plpgsql"
 | 
				
			||||||
| 
						 | 
					@ -71,6 +71,7 @@ ActiveRecord::Schema.define(version: 20171020084748) do
 | 
				
			||||||
    t.string "shared_inbox_url", default: "", null: false
 | 
					    t.string "shared_inbox_url", default: "", null: false
 | 
				
			||||||
    t.string "followers_url", default: "", null: false
 | 
					    t.string "followers_url", default: "", null: false
 | 
				
			||||||
    t.integer "protocol", default: 0, null: false
 | 
					    t.integer "protocol", default: 0, null: false
 | 
				
			||||||
 | 
					    t.boolean "memorial", default: false, null: false
 | 
				
			||||||
    t.index "(((setweight(to_tsvector('simple'::regconfig, (display_name)::text), 'A'::\"char\") || setweight(to_tsvector('simple'::regconfig, (username)::text), 'B'::\"char\")) || setweight(to_tsvector('simple'::regconfig, (COALESCE(domain, ''::character varying))::text), 'C'::\"char\")))", name: "search_index", using: :gin
 | 
					    t.index "(((setweight(to_tsvector('simple'::regconfig, (display_name)::text), 'A'::\"char\") || setweight(to_tsvector('simple'::regconfig, (username)::text), 'B'::\"char\")) || setweight(to_tsvector('simple'::regconfig, (COALESCE(domain, ''::character varying))::text), 'C'::\"char\")))", name: "search_index", using: :gin
 | 
				
			||||||
    t.index "lower((username)::text), lower((domain)::text)", name: "index_accounts_on_username_and_domain_lower"
 | 
					    t.index "lower((username)::text), lower((domain)::text)", name: "index_accounts_on_username_and_domain_lower"
 | 
				
			||||||
    t.index ["uri"], name: "index_accounts_on_uri"
 | 
					    t.index ["uri"], name: "index_accounts_on_uri"
 | 
				
			||||||
| 
						 | 
					@ -435,6 +436,7 @@ ActiveRecord::Schema.define(version: 20171020084748) do
 | 
				
			||||||
    t.string "otp_backup_codes", array: true
 | 
					    t.string "otp_backup_codes", array: true
 | 
				
			||||||
    t.string "filtered_languages", default: [], null: false, array: true
 | 
					    t.string "filtered_languages", default: [], null: false, array: true
 | 
				
			||||||
    t.bigint "account_id", null: false
 | 
					    t.bigint "account_id", null: false
 | 
				
			||||||
 | 
					    t.boolean "disabled", default: false, null: false
 | 
				
			||||||
    t.index ["account_id"], name: "index_users_on_account_id"
 | 
					    t.index ["account_id"], name: "index_users_on_account_id"
 | 
				
			||||||
    t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
 | 
					    t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
 | 
				
			||||||
    t.index ["email"], name: "index_users_on_email", unique: true
 | 
					    t.index ["email"], name: "index_users_on_email", unique: true
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue