Add moderator role and add pundit policies for admin actions (#5635)
* Add moderator role and add pundit policies for admin actions * Add rake task for turning user into mod and revoking it again * Fix handling of unauthorized exception * Deliver new report e-mails to staff, not just admins * Add promote/demote to admin UI, hide some actions conditionally * Fix unused i18n
This commit is contained in:
parent
2b1190065c
commit
7bb8b0b2fc
|
@ -1,23 +1,28 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Admin::AccountModerationNotesController < Admin::BaseController
|
module Admin
|
||||||
|
class AccountModerationNotesController < BaseController
|
||||||
|
before_action :set_account_moderation_note, only: [:destroy]
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
authorize AccountModerationNote, :create?
|
||||||
|
|
||||||
@account_moderation_note = current_account.account_moderation_notes.new(resource_params)
|
@account_moderation_note = current_account.account_moderation_notes.new(resource_params)
|
||||||
|
|
||||||
if @account_moderation_note.save
|
if @account_moderation_note.save
|
||||||
@target_account = @account_moderation_note.target_account
|
redirect_to admin_account_path(@account_moderation_note.target_account_id), notice: I18n.t('admin.account_moderation_notes.created_msg')
|
||||||
redirect_to admin_account_path(@target_account.id), notice: I18n.t('admin.account_moderation_notes.created_msg')
|
|
||||||
else
|
else
|
||||||
@account = @account_moderation_note.target_account
|
@account = @account_moderation_note.target_account
|
||||||
@moderation_notes = @account.targeted_moderation_notes.latest
|
@moderation_notes = @account.targeted_moderation_notes.latest
|
||||||
|
|
||||||
render template: 'admin/accounts/show'
|
render template: 'admin/accounts/show'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
@account_moderation_note = AccountModerationNote.find(params[:id])
|
authorize @account_moderation_note, :destroy?
|
||||||
@target_account = @account_moderation_note.target_account
|
|
||||||
@account_moderation_note.destroy
|
@account_moderation_note.destroy
|
||||||
redirect_to admin_account_path(@target_account.id), notice: I18n.t('admin.account_moderation_notes.destroyed_msg')
|
redirect_to admin_account_path(@account_moderation_note.target_account_id), notice: I18n.t('admin.account_moderation_notes.destroyed_msg')
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -28,4 +33,9 @@ class Admin::AccountModerationNotesController < Admin::BaseController
|
||||||
:target_account_id
|
:target_account_id
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_account_moderation_note
|
||||||
|
@account_moderation_note = AccountModerationNote.find(params[:id])
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,40 +7,49 @@ module Admin
|
||||||
before_action :require_local_account!, only: [:enable, :disable, :memorialize]
|
before_action :require_local_account!, only: [:enable, :disable, :memorialize]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
authorize :account, :index?
|
||||||
@accounts = filtered_accounts.page(params[:page])
|
@accounts = filtered_accounts.page(params[:page])
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
authorize @account, :show?
|
||||||
@account_moderation_note = current_account.account_moderation_notes.new(target_account: @account)
|
@account_moderation_note = current_account.account_moderation_notes.new(target_account: @account)
|
||||||
@moderation_notes = @account.targeted_moderation_notes.latest
|
@moderation_notes = @account.targeted_moderation_notes.latest
|
||||||
end
|
end
|
||||||
|
|
||||||
def subscribe
|
def subscribe
|
||||||
|
authorize @account, :subscribe?
|
||||||
Pubsubhubbub::SubscribeWorker.perform_async(@account.id)
|
Pubsubhubbub::SubscribeWorker.perform_async(@account.id)
|
||||||
redirect_to admin_account_path(@account.id)
|
redirect_to admin_account_path(@account.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def unsubscribe
|
def unsubscribe
|
||||||
|
authorize @account, :unsubscribe?
|
||||||
Pubsubhubbub::UnsubscribeWorker.perform_async(@account.id)
|
Pubsubhubbub::UnsubscribeWorker.perform_async(@account.id)
|
||||||
redirect_to admin_account_path(@account.id)
|
redirect_to admin_account_path(@account.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def memorialize
|
def memorialize
|
||||||
|
authorize @account, :memorialize?
|
||||||
@account.memorialize!
|
@account.memorialize!
|
||||||
redirect_to admin_account_path(@account.id)
|
redirect_to admin_account_path(@account.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def enable
|
def enable
|
||||||
|
authorize @account.user, :enable?
|
||||||
@account.user.enable!
|
@account.user.enable!
|
||||||
redirect_to admin_account_path(@account.id)
|
redirect_to admin_account_path(@account.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def disable
|
def disable
|
||||||
|
authorize @account.user, :disable?
|
||||||
@account.user.disable!
|
@account.user.disable!
|
||||||
redirect_to admin_account_path(@account.id)
|
redirect_to admin_account_path(@account.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def redownload
|
def redownload
|
||||||
|
authorize @account, :redownload?
|
||||||
|
|
||||||
@account.reset_avatar!
|
@account.reset_avatar!
|
||||||
@account.reset_header!
|
@account.reset_header!
|
||||||
@account.save!
|
@account.save!
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
module Admin
|
module Admin
|
||||||
class BaseController < ApplicationController
|
class BaseController < ApplicationController
|
||||||
before_action :require_admin!
|
include Authorization
|
||||||
|
|
||||||
|
before_action :require_staff!
|
||||||
|
|
||||||
layout 'admin'
|
layout 'admin'
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,15 +2,18 @@
|
||||||
|
|
||||||
module Admin
|
module Admin
|
||||||
class ConfirmationsController < BaseController
|
class ConfirmationsController < BaseController
|
||||||
|
before_action :set_user
|
||||||
|
|
||||||
def create
|
def create
|
||||||
account_user.confirm
|
authorize @user, :confirm?
|
||||||
|
@user.confirm!
|
||||||
redirect_to admin_accounts_path
|
redirect_to admin_accounts_path
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def account_user
|
def set_user
|
||||||
Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound)
|
@user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,14 +5,18 @@ module Admin
|
||||||
before_action :set_custom_emoji, except: [:index, :new, :create]
|
before_action :set_custom_emoji, except: [:index, :new, :create]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
authorize :custom_emoji, :index?
|
||||||
@custom_emojis = filtered_custom_emojis.eager_load(:local_counterpart).page(params[:page])
|
@custom_emojis = filtered_custom_emojis.eager_load(:local_counterpart).page(params[:page])
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
|
authorize :custom_emoji, :create?
|
||||||
@custom_emoji = CustomEmoji.new
|
@custom_emoji = CustomEmoji.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
authorize :custom_emoji, :create?
|
||||||
|
|
||||||
@custom_emoji = CustomEmoji.new(resource_params)
|
@custom_emoji = CustomEmoji.new(resource_params)
|
||||||
|
|
||||||
if @custom_emoji.save
|
if @custom_emoji.save
|
||||||
|
@ -23,6 +27,8 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
authorize @custom_emoji, :update?
|
||||||
|
|
||||||
if @custom_emoji.update(resource_params)
|
if @custom_emoji.update(resource_params)
|
||||||
redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.updated_msg')
|
redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.updated_msg')
|
||||||
else
|
else
|
||||||
|
@ -31,11 +37,14 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
authorize @custom_emoji, :destroy?
|
||||||
@custom_emoji.destroy
|
@custom_emoji.destroy
|
||||||
redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.destroyed_msg')
|
redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.destroyed_msg')
|
||||||
end
|
end
|
||||||
|
|
||||||
def copy
|
def copy
|
||||||
|
authorize @custom_emoji, :copy?
|
||||||
|
|
||||||
emoji = CustomEmoji.find_or_create_by(domain: nil, shortcode: @custom_emoji.shortcode)
|
emoji = CustomEmoji.find_or_create_by(domain: nil, shortcode: @custom_emoji.shortcode)
|
||||||
|
|
||||||
if emoji.update(image: @custom_emoji.image)
|
if emoji.update(image: @custom_emoji.image)
|
||||||
|
@ -48,11 +57,13 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def enable
|
def enable
|
||||||
|
authorize @custom_emoji, :enable?
|
||||||
@custom_emoji.update!(disabled: false)
|
@custom_emoji.update!(disabled: false)
|
||||||
redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.enabled_msg')
|
redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.enabled_msg')
|
||||||
end
|
end
|
||||||
|
|
||||||
def disable
|
def disable
|
||||||
|
authorize @custom_emoji, :disable?
|
||||||
@custom_emoji.update!(disabled: true)
|
@custom_emoji.update!(disabled: true)
|
||||||
redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.disabled_msg')
|
redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.disabled_msg')
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,14 +5,18 @@ module Admin
|
||||||
before_action :set_domain_block, only: [:show, :destroy]
|
before_action :set_domain_block, only: [:show, :destroy]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
authorize :domain_block, :index?
|
||||||
@domain_blocks = DomainBlock.page(params[:page])
|
@domain_blocks = DomainBlock.page(params[:page])
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
|
authorize :domain_block, :create?
|
||||||
@domain_block = DomainBlock.new
|
@domain_block = DomainBlock.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
authorize :domain_block, :create?
|
||||||
|
|
||||||
@domain_block = DomainBlock.new(resource_params)
|
@domain_block = DomainBlock.new(resource_params)
|
||||||
|
|
||||||
if @domain_block.save
|
if @domain_block.save
|
||||||
|
@ -23,9 +27,12 @@ module Admin
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def show; end
|
def show
|
||||||
|
authorize @domain_block, :show?
|
||||||
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
authorize @domain_block, :destroy?
|
||||||
UnblockDomainService.new.call(@domain_block, retroactive_unblock?)
|
UnblockDomainService.new.call(@domain_block, retroactive_unblock?)
|
||||||
redirect_to admin_domain_blocks_path, notice: I18n.t('admin.domain_blocks.destroyed_msg')
|
redirect_to admin_domain_blocks_path, notice: I18n.t('admin.domain_blocks.destroyed_msg')
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,14 +5,18 @@ module Admin
|
||||||
before_action :set_email_domain_block, only: [:show, :destroy]
|
before_action :set_email_domain_block, only: [:show, :destroy]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
authorize :email_domain_block, :index?
|
||||||
@email_domain_blocks = EmailDomainBlock.page(params[:page])
|
@email_domain_blocks = EmailDomainBlock.page(params[:page])
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
|
authorize :email_domain_block, :create?
|
||||||
@email_domain_block = EmailDomainBlock.new
|
@email_domain_block = EmailDomainBlock.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
authorize :email_domain_block, :create?
|
||||||
|
|
||||||
@email_domain_block = EmailDomainBlock.new(resource_params)
|
@email_domain_block = EmailDomainBlock.new(resource_params)
|
||||||
|
|
||||||
if @email_domain_block.save
|
if @email_domain_block.save
|
||||||
|
@ -23,6 +27,7 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
authorize @email_domain_block, :destroy?
|
||||||
@email_domain_block.destroy
|
@email_domain_block.destroy
|
||||||
redirect_to admin_email_domain_blocks_path, notice: I18n.t('admin.email_domain_blocks.destroyed_msg')
|
redirect_to admin_email_domain_blocks_path, notice: I18n.t('admin.email_domain_blocks.destroyed_msg')
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,10 +3,12 @@
|
||||||
module Admin
|
module Admin
|
||||||
class InstancesController < BaseController
|
class InstancesController < BaseController
|
||||||
def index
|
def index
|
||||||
|
authorize :instance, :index?
|
||||||
@instances = ordered_instances
|
@instances = ordered_instances
|
||||||
end
|
end
|
||||||
|
|
||||||
def resubscribe
|
def resubscribe
|
||||||
|
authorize :instance, :resubscribe?
|
||||||
params.require(:by_domain)
|
params.require(:by_domain)
|
||||||
Pubsubhubbub::SubscribeWorker.push_bulk(subscribeable_accounts.pluck(:id))
|
Pubsubhubbub::SubscribeWorker.push_bulk(subscribeable_accounts.pluck(:id))
|
||||||
redirect_to admin_instances_path
|
redirect_to admin_instances_path
|
||||||
|
|
|
@ -2,19 +2,20 @@
|
||||||
|
|
||||||
module Admin
|
module Admin
|
||||||
class ReportedStatusesController < BaseController
|
class ReportedStatusesController < BaseController
|
||||||
include Authorization
|
|
||||||
|
|
||||||
before_action :set_report
|
before_action :set_report
|
||||||
before_action :set_status, only: [:update, :destroy]
|
before_action :set_status, only: [:update, :destroy]
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
authorize :status, :update?
|
||||||
|
|
||||||
@form = Form::StatusBatch.new(form_status_batch_params)
|
@form = Form::StatusBatch.new(form_status_batch_params)
|
||||||
flash[:alert] = t('admin.statuses.failed_to_execute') unless @form.save
|
flash[:alert] = I18n.t('admin.statuses.failed_to_execute') unless @form.save
|
||||||
|
|
||||||
redirect_to admin_report_path(@report)
|
redirect_to admin_report_path(@report)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
authorize @status, :update?
|
||||||
@status.update(status_params)
|
@status.update(status_params)
|
||||||
redirect_to admin_report_path(@report)
|
redirect_to admin_report_path(@report)
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,14 +5,17 @@ module Admin
|
||||||
before_action :set_report, except: [:index]
|
before_action :set_report, except: [:index]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
authorize :report, :index?
|
||||||
@reports = filtered_reports.page(params[:page])
|
@reports = filtered_reports.page(params[:page])
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
authorize @report, :show?
|
||||||
@form = Form::StatusBatch.new
|
@form = Form::StatusBatch.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
authorize @report, :update?
|
||||||
process_report
|
process_report
|
||||||
redirect_to admin_report_path(@report)
|
redirect_to admin_report_path(@report)
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,17 +2,18 @@
|
||||||
|
|
||||||
module Admin
|
module Admin
|
||||||
class ResetsController < BaseController
|
class ResetsController < BaseController
|
||||||
before_action :set_account
|
before_action :set_user
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@account.user.send_reset_password_instructions
|
authorize @user, :reset_password?
|
||||||
|
@user.send_reset_password_instructions
|
||||||
redirect_to admin_accounts_path
|
redirect_to admin_accounts_path
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_account
|
def set_user
|
||||||
@account = Account.find(params[:account_id])
|
@user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
25
app/controllers/admin/roles_controller.rb
Normal file
25
app/controllers/admin/roles_controller.rb
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Admin
|
||||||
|
class RolesController < BaseController
|
||||||
|
before_action :set_user
|
||||||
|
|
||||||
|
def promote
|
||||||
|
authorize @user, :promote?
|
||||||
|
@user.promote!
|
||||||
|
redirect_to admin_account_path(@user.account_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def demote
|
||||||
|
authorize @user, :demote?
|
||||||
|
@user.demote!
|
||||||
|
redirect_to admin_account_path(@user.account_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_user
|
||||||
|
@user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -28,10 +28,13 @@ module Admin
|
||||||
).freeze
|
).freeze
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
|
authorize :settings, :show?
|
||||||
@admin_settings = Form::AdminSettings.new
|
@admin_settings = Form::AdminSettings.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
authorize :settings, :update?
|
||||||
|
|
||||||
settings_params.each do |key, value|
|
settings_params.each do |key, value|
|
||||||
if UPLOAD_SETTINGS.include?(key)
|
if UPLOAD_SETTINGS.include?(key)
|
||||||
upload = SiteUpload.where(var: key).first_or_initialize(var: key)
|
upload = SiteUpload.where(var: key).first_or_initialize(var: key)
|
||||||
|
|
|
@ -5,11 +5,13 @@ module Admin
|
||||||
before_action :set_account
|
before_action :set_account
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
authorize @account, :silence?
|
||||||
@account.update(silenced: true)
|
@account.update(silenced: true)
|
||||||
redirect_to admin_accounts_path
|
redirect_to admin_accounts_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
authorize @account, :unsilence?
|
||||||
@account.update(silenced: false)
|
@account.update(silenced: false)
|
||||||
redirect_to admin_accounts_path
|
redirect_to admin_accounts_path
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
module Admin
|
module Admin
|
||||||
class StatusesController < BaseController
|
class StatusesController < BaseController
|
||||||
include Authorization
|
|
||||||
|
|
||||||
helper_method :current_params
|
helper_method :current_params
|
||||||
|
|
||||||
before_action :set_account
|
before_action :set_account
|
||||||
|
@ -12,24 +10,30 @@ module Admin
|
||||||
PER_PAGE = 20
|
PER_PAGE = 20
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
authorize :status, :index?
|
||||||
|
|
||||||
@statuses = @account.statuses
|
@statuses = @account.statuses
|
||||||
|
|
||||||
if params[:media]
|
if params[:media]
|
||||||
account_media_status_ids = @account.media_attachments.attached.reorder(nil).select(:status_id).distinct
|
account_media_status_ids = @account.media_attachments.attached.reorder(nil).select(:status_id).distinct
|
||||||
@statuses.merge!(Status.where(id: account_media_status_ids))
|
@statuses.merge!(Status.where(id: account_media_status_ids))
|
||||||
end
|
end
|
||||||
@statuses = @statuses.preload(:media_attachments, :mentions).page(params[:page]).per(PER_PAGE)
|
|
||||||
|
|
||||||
|
@statuses = @statuses.preload(:media_attachments, :mentions).page(params[:page]).per(PER_PAGE)
|
||||||
@form = Form::StatusBatch.new
|
@form = Form::StatusBatch.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
authorize :status, :update?
|
||||||
|
|
||||||
@form = Form::StatusBatch.new(form_status_batch_params)
|
@form = Form::StatusBatch.new(form_status_batch_params)
|
||||||
flash[:alert] = t('admin.statuses.failed_to_execute') unless @form.save
|
flash[:alert] = I18n.t('admin.statuses.failed_to_execute') unless @form.save
|
||||||
|
|
||||||
redirect_to admin_account_statuses_path(@account.id, current_params)
|
redirect_to admin_account_statuses_path(@account.id, current_params)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
authorize @status, :update?
|
||||||
@status.update(status_params)
|
@status.update(status_params)
|
||||||
redirect_to admin_account_statuses_path(@account.id, current_params)
|
redirect_to admin_account_statuses_path(@account.id, current_params)
|
||||||
end
|
end
|
||||||
|
@ -60,6 +64,7 @@ module Admin
|
||||||
|
|
||||||
def current_params
|
def current_params
|
||||||
page = (params[:page] || 1).to_i
|
page = (params[:page] || 1).to_i
|
||||||
|
|
||||||
{
|
{
|
||||||
media: params[:media],
|
media: params[:media],
|
||||||
page: page > 1 && page,
|
page: page > 1 && page,
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
module Admin
|
module Admin
|
||||||
class SubscriptionsController < BaseController
|
class SubscriptionsController < BaseController
|
||||||
def index
|
def index
|
||||||
|
authorize :subscription, :index?
|
||||||
@subscriptions = ordered_subscriptions.page(requested_page)
|
@subscriptions = ordered_subscriptions.page(requested_page)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,13 @@ module Admin
|
||||||
before_action :set_account
|
before_action :set_account
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
authorize @account, :suspend?
|
||||||
Admin::SuspensionWorker.perform_async(@account.id)
|
Admin::SuspensionWorker.perform_async(@account.id)
|
||||||
redirect_to admin_accounts_path
|
redirect_to admin_accounts_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
authorize @account, :unsuspend?
|
||||||
@account.unsuspend!
|
@account.unsuspend!
|
||||||
redirect_to admin_accounts_path
|
redirect_to admin_accounts_path
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,7 @@ module Admin
|
||||||
before_action :set_user
|
before_action :set_user
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
authorize @user, :disable_2fa?
|
||||||
@user.disable_two_factor!
|
@user.disable_two_factor!
|
||||||
redirect_to admin_accounts_path
|
redirect_to admin_accounts_path
|
||||||
end
|
end
|
||||||
|
|
|
@ -19,7 +19,7 @@ class Api::V1::ReportsController < Api::BaseController
|
||||||
comment: report_params[:comment]
|
comment: report_params[:comment]
|
||||||
)
|
)
|
||||||
|
|
||||||
User.admins.includes(:account).each { |u| AdminMailer.new_report(u.account, @report).deliver_later }
|
User.staff.includes(:account).each { |u| AdminMailer.new_report(u.account, @report).deliver_later }
|
||||||
|
|
||||||
render json: @report, serializer: REST::ReportSerializer
|
render json: @report, serializer: REST::ReportSerializer
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,6 +18,7 @@ class ApplicationController < ActionController::Base
|
||||||
rescue_from ActionController::RoutingError, with: :not_found
|
rescue_from ActionController::RoutingError, with: :not_found
|
||||||
rescue_from ActiveRecord::RecordNotFound, with: :not_found
|
rescue_from ActiveRecord::RecordNotFound, with: :not_found
|
||||||
rescue_from ActionController::InvalidAuthenticityToken, with: :unprocessable_entity
|
rescue_from ActionController::InvalidAuthenticityToken, with: :unprocessable_entity
|
||||||
|
rescue_from Mastodon::NotPermittedError, with: :forbidden
|
||||||
|
|
||||||
before_action :store_current_location, except: :raise_not_found, unless: :devise_controller?
|
before_action :store_current_location, except: :raise_not_found, unless: :devise_controller?
|
||||||
before_action :check_suspension, if: :user_signed_in?
|
before_action :check_suspension, if: :user_signed_in?
|
||||||
|
@ -40,6 +41,10 @@ class ApplicationController < ActionController::Base
|
||||||
redirect_to root_path unless current_user&.admin?
|
redirect_to root_path unless current_user&.admin?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def require_staff!
|
||||||
|
redirect_to root_path unless current_user&.staff?
|
||||||
|
end
|
||||||
|
|
||||||
def check_suspension
|
def check_suspension
|
||||||
forbidden if current_user.account.suspended?
|
forbidden if current_user.account.suspended?
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
module Authorization
|
module Authorization
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
include Pundit
|
include Pundit
|
||||||
|
|
||||||
def pundit_user
|
def pundit_user
|
||||||
|
|
|
@ -35,6 +35,11 @@ module ApplicationHelper
|
||||||
Rails.env.production? ? site_title : "#{site_title} (Dev)"
|
Rails.env.production? ? site_title : "#{site_title} (Dev)"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def can?(action, record)
|
||||||
|
return false if record.nil?
|
||||||
|
policy(record).public_send("#{action}?")
|
||||||
|
end
|
||||||
|
|
||||||
def fa_icon(icon, attributes = {})
|
def fa_icon(icon, attributes = {})
|
||||||
class_names = attributes[:class]&.split(' ') || []
|
class_names = attributes[:class]&.split(' ') || []
|
||||||
class_names << 'fa'
|
class_names << 'fa'
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
# filtered_languages :string default([]), not null, is an Array
|
# filtered_languages :string default([]), not null, is an Array
|
||||||
# account_id :integer not null
|
# account_id :integer not null
|
||||||
# disabled :boolean default(FALSE), not null
|
# disabled :boolean default(FALSE), not null
|
||||||
|
# moderator :boolean default(FALSE), not null
|
||||||
#
|
#
|
||||||
|
|
||||||
class User < ApplicationRecord
|
class User < ApplicationRecord
|
||||||
|
@ -55,6 +56,8 @@ class User < ApplicationRecord
|
||||||
|
|
||||||
scope :recent, -> { order(id: :desc) }
|
scope :recent, -> { order(id: :desc) }
|
||||||
scope :admins, -> { where(admin: true) }
|
scope :admins, -> { where(admin: true) }
|
||||||
|
scope :moderators, -> { where(moderator: true) }
|
||||||
|
scope :staff, -> { admins.or(moderators) }
|
||||||
scope :confirmed, -> { where.not(confirmed_at: nil) }
|
scope :confirmed, -> { where.not(confirmed_at: nil) }
|
||||||
scope :inactive, -> { where(arel_table[:current_sign_in_at].lt(ACTIVE_DURATION.ago)) }
|
scope :inactive, -> { where(arel_table[:current_sign_in_at].lt(ACTIVE_DURATION.ago)) }
|
||||||
scope :active, -> { confirmed.where(arel_table[:current_sign_in_at].gteq(ACTIVE_DURATION.ago)).joins(:account).where(accounts: { suspended: false }) }
|
scope :active, -> { confirmed.where(arel_table[:current_sign_in_at].gteq(ACTIVE_DURATION.ago)).joins(:account).where(accounts: { suspended: false }) }
|
||||||
|
@ -74,6 +77,20 @@ class User < ApplicationRecord
|
||||||
confirmed_at.present?
|
confirmed_at.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def staff?
|
||||||
|
admin? || moderator?
|
||||||
|
end
|
||||||
|
|
||||||
|
def role
|
||||||
|
if admin?
|
||||||
|
'admin'
|
||||||
|
elsif moderator?
|
||||||
|
'moderator'
|
||||||
|
else
|
||||||
|
'user'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def disable!
|
def disable!
|
||||||
update!(disabled: true,
|
update!(disabled: true,
|
||||||
last_sign_in_at: current_sign_in_at,
|
last_sign_in_at: current_sign_in_at,
|
||||||
|
@ -84,6 +101,27 @@ class User < ApplicationRecord
|
||||||
update!(disabled: false)
|
update!(disabled: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def confirm!
|
||||||
|
skip_confirmation!
|
||||||
|
save!
|
||||||
|
end
|
||||||
|
|
||||||
|
def promote!
|
||||||
|
if moderator?
|
||||||
|
update!(moderator: false, admin: true)
|
||||||
|
elsif !admin?
|
||||||
|
update!(moderator: true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def demote!
|
||||||
|
if admin?
|
||||||
|
update!(admin: false, moderator: true)
|
||||||
|
elsif moderator?
|
||||||
|
update!(moderator: false)
|
||||||
|
end
|
||||||
|
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
|
||||||
|
|
17
app/policies/account_moderation_note_policy.rb
Normal file
17
app/policies/account_moderation_note_policy.rb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AccountModerationNotePolicy < ApplicationPolicy
|
||||||
|
def create?
|
||||||
|
staff?
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy?
|
||||||
|
admin? || owner?
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def owner?
|
||||||
|
record.account_id == current_account&.id
|
||||||
|
end
|
||||||
|
end
|
43
app/policies/account_policy.rb
Normal file
43
app/policies/account_policy.rb
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AccountPolicy < ApplicationPolicy
|
||||||
|
def index?
|
||||||
|
staff?
|
||||||
|
end
|
||||||
|
|
||||||
|
def show?
|
||||||
|
staff?
|
||||||
|
end
|
||||||
|
|
||||||
|
def suspend?
|
||||||
|
staff? && !record.user&.staff?
|
||||||
|
end
|
||||||
|
|
||||||
|
def unsuspend?
|
||||||
|
staff?
|
||||||
|
end
|
||||||
|
|
||||||
|
def silence?
|
||||||
|
staff? && !record.user&.staff?
|
||||||
|
end
|
||||||
|
|
||||||
|
def unsilence?
|
||||||
|
staff?
|
||||||
|
end
|
||||||
|
|
||||||
|
def redownload?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def subscribe?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def unsubscribe?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def memorialize?
|
||||||
|
admin? && !record.user&.admin?
|
||||||
|
end
|
||||||
|
end
|
18
app/policies/application_policy.rb
Normal file
18
app/policies/application_policy.rb
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class ApplicationPolicy
|
||||||
|
attr_reader :current_account, :record
|
||||||
|
|
||||||
|
def initialize(current_account, record)
|
||||||
|
@current_account = current_account
|
||||||
|
@record = record
|
||||||
|
end
|
||||||
|
|
||||||
|
delegate :admin?, :moderator?, :staff?, to: :current_user, allow_nil: true
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def current_user
|
||||||
|
current_account&.user
|
||||||
|
end
|
||||||
|
end
|
31
app/policies/custom_emoji_policy.rb
Normal file
31
app/policies/custom_emoji_policy.rb
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class CustomEmojiPolicy < ApplicationPolicy
|
||||||
|
def index?
|
||||||
|
staff?
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def update?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def copy?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def enable?
|
||||||
|
staff?
|
||||||
|
end
|
||||||
|
|
||||||
|
def disable?
|
||||||
|
staff?
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
end
|
19
app/policies/domain_block_policy.rb
Normal file
19
app/policies/domain_block_policy.rb
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class DomainBlockPolicy < ApplicationPolicy
|
||||||
|
def index?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def show?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
end
|
15
app/policies/email_domain_block_policy.rb
Normal file
15
app/policies/email_domain_block_policy.rb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class EmailDomainBlockPolicy < ApplicationPolicy
|
||||||
|
def index?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
end
|
11
app/policies/instance_policy.rb
Normal file
11
app/policies/instance_policy.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class InstancePolicy < ApplicationPolicy
|
||||||
|
def index?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def resubscribe?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
end
|
15
app/policies/report_policy.rb
Normal file
15
app/policies/report_policy.rb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class ReportPolicy < ApplicationPolicy
|
||||||
|
def update?
|
||||||
|
staff?
|
||||||
|
end
|
||||||
|
|
||||||
|
def index?
|
||||||
|
staff?
|
||||||
|
end
|
||||||
|
|
||||||
|
def show?
|
||||||
|
staff?
|
||||||
|
end
|
||||||
|
end
|
11
app/policies/settings_policy.rb
Normal file
11
app/policies/settings_policy.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class SettingsPolicy < ApplicationPolicy
|
||||||
|
def update?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def show?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,20 +1,17 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class StatusPolicy
|
class StatusPolicy < ApplicationPolicy
|
||||||
attr_reader :account, :status
|
def index?
|
||||||
|
staff?
|
||||||
def initialize(account, status)
|
|
||||||
@account = account
|
|
||||||
@status = status
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def show?
|
def show?
|
||||||
if direct?
|
if direct?
|
||||||
owned? || status.mentions.where(account: account).exists?
|
owned? || record.mentions.where(account: current_account).exists?
|
||||||
elsif private?
|
elsif private?
|
||||||
owned? || account&.following?(status.account) || status.mentions.where(account: account).exists?
|
owned? || current_account&.following?(author) || record.mentions.where(account: current_account).exists?
|
||||||
else
|
else
|
||||||
account.nil? || !status.account.blocking?(account)
|
current_account.nil? || !author.blocking?(current_account)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -23,26 +20,30 @@ class StatusPolicy
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
admin? || owned?
|
staff? || owned?
|
||||||
end
|
end
|
||||||
|
|
||||||
alias unreblog? destroy?
|
alias unreblog? destroy?
|
||||||
|
|
||||||
private
|
def update?
|
||||||
|
staff?
|
||||||
def admin?
|
|
||||||
account&.user&.admin?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
def direct?
|
def direct?
|
||||||
status.direct_visibility?
|
record.direct_visibility?
|
||||||
end
|
end
|
||||||
|
|
||||||
def owned?
|
def owned?
|
||||||
status.account.id == account&.id
|
author.id == current_account&.id
|
||||||
end
|
end
|
||||||
|
|
||||||
def private?
|
def private?
|
||||||
status.private_visibility?
|
record.private_visibility?
|
||||||
|
end
|
||||||
|
|
||||||
|
def author
|
||||||
|
record.account
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
7
app/policies/subscription_policy.rb
Normal file
7
app/policies/subscription_policy.rb
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class SubscriptionPolicy < ApplicationPolicy
|
||||||
|
def index?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
end
|
41
app/policies/user_policy.rb
Normal file
41
app/policies/user_policy.rb
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class UserPolicy < ApplicationPolicy
|
||||||
|
def reset_password?
|
||||||
|
staff? && !record.staff?
|
||||||
|
end
|
||||||
|
|
||||||
|
def disable_2fa?
|
||||||
|
admin? && !record.staff?
|
||||||
|
end
|
||||||
|
|
||||||
|
def confirm?
|
||||||
|
staff? && !record.confirmed?
|
||||||
|
end
|
||||||
|
|
||||||
|
def enable?
|
||||||
|
admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def disable?
|
||||||
|
admin? && !record.admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def promote?
|
||||||
|
admin? && promoteable?
|
||||||
|
end
|
||||||
|
|
||||||
|
def demote?
|
||||||
|
admin? && !record.admin? && demoteable?
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def promoteable?
|
||||||
|
!record.staff? || !record.admin?
|
||||||
|
end
|
||||||
|
|
||||||
|
def demoteable?
|
||||||
|
record.staff?
|
||||||
|
end
|
||||||
|
end
|
|
@ -7,4 +7,4 @@
|
||||||
%time.formatted{ datetime: account_moderation_note.created_at.iso8601, title: l(account_moderation_note.created_at) }
|
%time.formatted{ datetime: account_moderation_note.created_at.iso8601, title: l(account_moderation_note.created_at) }
|
||||||
= l account_moderation_note.created_at
|
= l account_moderation_note.created_at
|
||||||
%td
|
%td
|
||||||
= link_to t('admin.account_moderation_notes.delete'), admin_account_moderation_note_path(account_moderation_note), method: :delete
|
= link_to t('admin.account_moderation_notes.delete'), admin_account_moderation_note_path(account_moderation_note), method: :delete if can?(:destroy, account_moderation_note)
|
||||||
|
|
|
@ -17,16 +17,20 @@
|
||||||
- if @account.local?
|
- if @account.local?
|
||||||
%tr
|
%tr
|
||||||
%th= t('admin.accounts.email')
|
%th= t('admin.accounts.email')
|
||||||
%td= @account.user_email
|
%td
|
||||||
|
= @account.user_email
|
||||||
|
|
||||||
|
- if @account.user_confirmed?
|
||||||
|
= fa_icon('check')
|
||||||
%tr
|
%tr
|
||||||
%th= t('admin.accounts.login_status')
|
%th= t('admin.accounts.login_status')
|
||||||
%td
|
%td
|
||||||
- if @account.user&.disabled?
|
- if @account.user&.disabled?
|
||||||
= t('admin.accounts.disabled')
|
= t('admin.accounts.disabled')
|
||||||
= table_link_to 'unlock', t('admin.accounts.enable'), enable_admin_account_path(@account.id), method: :post
|
= table_link_to 'unlock', t('admin.accounts.enable'), enable_admin_account_path(@account.id), method: :post if can?(:enable, @account.user)
|
||||||
- else
|
- else
|
||||||
= t('admin.accounts.enabled')
|
= t('admin.accounts.enabled')
|
||||||
= table_link_to 'lock', t('admin.accounts.disable'), disable_admin_account_path(@account.id), method: :post
|
= table_link_to 'lock', t('admin.accounts.disable'), disable_admin_account_path(@account.id), method: :post if can?(:disable, @account.user)
|
||||||
%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
|
||||||
|
@ -71,28 +75,28 @@
|
||||||
%div{ style: 'overflow: hidden' }
|
%div{ style: 'overflow: hidden' }
|
||||||
%div{ style: 'float: right' }
|
%div{ style: 'float: right' }
|
||||||
- if @account.local?
|
- if @account.local?
|
||||||
= 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 can?(:reset_password, @account.user)
|
||||||
- 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' if can?(:disable_2fa, @account.user)
|
||||||
- unless @account.memorial?
|
- 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'
|
= link_to t('admin.accounts.memorialize'), memorialize_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button' if can?(:memorialize, @account)
|
||||||
- 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' if can?(:redownload, @account)
|
||||||
|
|
||||||
%div{ style: 'float: left' }
|
%div{ style: 'float: left' }
|
||||||
- if @account.silenced?
|
- if @account.silenced?
|
||||||
= link_to t('admin.accounts.undo_silenced'), admin_account_silence_path(@account.id), method: :delete, class: 'button'
|
= link_to t('admin.accounts.undo_silenced'), admin_account_silence_path(@account.id), method: :delete, class: 'button' if can?(:unsilence, @account)
|
||||||
- else
|
- else
|
||||||
= link_to t('admin.accounts.silence'), admin_account_silence_path(@account.id), method: :post, class: 'button'
|
= link_to t('admin.accounts.silence'), admin_account_silence_path(@account.id), method: :post, class: 'button' if can?(:silence, @account)
|
||||||
|
|
||||||
- if @account.local?
|
- if @account.local?
|
||||||
- unless @account.user_confirmed?
|
- unless @account.user_confirmed?
|
||||||
= link_to t('admin.accounts.confirm'), admin_account_confirmation_path(@account.id), method: :post, class: 'button'
|
= link_to t('admin.accounts.confirm'), admin_account_confirmation_path(@account.id), method: :post, class: 'button' if can?(:confirm, @account.user)
|
||||||
|
|
||||||
- if @account.suspended?
|
- if @account.suspended?
|
||||||
= link_to t('admin.accounts.undo_suspension'), admin_account_suspension_path(@account.id), method: :delete, class: 'button'
|
= link_to t('admin.accounts.undo_suspension'), admin_account_suspension_path(@account.id), method: :delete, class: 'button' if can?(:unsuspend, @account)
|
||||||
- else
|
- else
|
||||||
= link_to t('admin.accounts.perform_full_suspension'), admin_account_suspension_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button'
|
= link_to t('admin.accounts.perform_full_suspension'), admin_account_suspension_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button' if can?(:suspend, @account)
|
||||||
|
|
||||||
- unless @account.local?
|
- unless @account.local?
|
||||||
%hr
|
%hr
|
||||||
|
@ -118,9 +122,9 @@
|
||||||
|
|
||||||
%div{ style: 'overflow: hidden' }
|
%div{ style: 'overflow: hidden' }
|
||||||
%div{ style: 'float: right' }
|
%div{ style: 'float: right' }
|
||||||
= link_to @account.subscribed? ? t('admin.accounts.resubscribe') : t('admin.accounts.subscribe'), subscribe_admin_account_path(@account.id), method: :post, class: 'button'
|
= link_to @account.subscribed? ? t('admin.accounts.resubscribe') : t('admin.accounts.subscribe'), subscribe_admin_account_path(@account.id), method: :post, class: 'button' if can?(:subscribe, @account)
|
||||||
- if @account.subscribed?
|
- if @account.subscribed?
|
||||||
= link_to t('admin.accounts.unsubscribe'), unsubscribe_admin_account_path(@account.id), method: :post, class: 'button negative'
|
= link_to t('admin.accounts.unsubscribe'), unsubscribe_admin_account_path(@account.id), method: :post, class: 'button negative' if can?(:unsubscribe, @account)
|
||||||
|
|
||||||
%hr
|
%hr
|
||||||
%h3 ActivityPub
|
%h3 ActivityPub
|
||||||
|
@ -141,6 +145,20 @@
|
||||||
%th= t('admin.accounts.followers_url')
|
%th= t('admin.accounts.followers_url')
|
||||||
%td= link_to @account.followers_url, @account.followers_url
|
%td= link_to @account.followers_url, @account.followers_url
|
||||||
|
|
||||||
|
- else
|
||||||
|
%hr
|
||||||
|
|
||||||
|
.table-wrapper
|
||||||
|
%table.table
|
||||||
|
%tbody
|
||||||
|
%tr
|
||||||
|
%th= t('admin.accounts.role')
|
||||||
|
%td
|
||||||
|
= t("admin.accounts.roles.#{@account.user&.role}")
|
||||||
|
%td<
|
||||||
|
= table_link_to 'angle-double-up', t('admin.accounts.promote'), promote_admin_account_role_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:promote, @account.user)
|
||||||
|
= table_link_to 'angle-double-down', t('admin.accounts.demote'), demote_admin_account_role_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:demote, @account.user)
|
||||||
|
|
||||||
%hr
|
%hr
|
||||||
%h3= t('admin.accounts.moderation_notes')
|
%h3= t('admin.accounts.moderation_notes')
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ ignore_missing:
|
||||||
- 'terms.body_html'
|
- 'terms.body_html'
|
||||||
- 'application_mailer.salutation'
|
- 'application_mailer.salutation'
|
||||||
- 'errors.500'
|
- 'errors.500'
|
||||||
|
|
||||||
ignore_unused:
|
ignore_unused:
|
||||||
- 'activemodel.errors.*'
|
- 'activemodel.errors.*'
|
||||||
- 'activerecord.attributes.*'
|
- 'activerecord.attributes.*'
|
||||||
|
@ -58,3 +59,4 @@ ignore_unused:
|
||||||
- 'errors.messages.*'
|
- 'errors.messages.*'
|
||||||
- 'activerecord.errors.models.doorkeeper/*'
|
- 'activerecord.errors.models.doorkeeper/*'
|
||||||
- 'errors.429'
|
- 'errors.429'
|
||||||
|
- 'admin.accounts.roles.*'
|
||||||
|
|
|
@ -62,6 +62,7 @@ en:
|
||||||
by_domain: Domain
|
by_domain: Domain
|
||||||
confirm: Confirm
|
confirm: Confirm
|
||||||
confirmed: Confirmed
|
confirmed: Confirmed
|
||||||
|
demote: Demote
|
||||||
disable: Disable
|
disable: Disable
|
||||||
disable_two_factor_authentication: Disable 2FA
|
disable_two_factor_authentication: Disable 2FA
|
||||||
disabled: Disabled
|
disabled: Disabled
|
||||||
|
@ -101,6 +102,7 @@ en:
|
||||||
outbox_url: Outbox URL
|
outbox_url: Outbox URL
|
||||||
perform_full_suspension: Perform full suspension
|
perform_full_suspension: Perform full suspension
|
||||||
profile_url: Profile URL
|
profile_url: Profile URL
|
||||||
|
promote: Promote
|
||||||
protocol: Protocol
|
protocol: Protocol
|
||||||
public: Public
|
public: Public
|
||||||
push_subscription_expires: PuSH subscription expires
|
push_subscription_expires: PuSH subscription expires
|
||||||
|
@ -108,6 +110,11 @@ en:
|
||||||
reset: Reset
|
reset: Reset
|
||||||
reset_password: Reset password
|
reset_password: Reset password
|
||||||
resubscribe: Resubscribe
|
resubscribe: Resubscribe
|
||||||
|
role: Permissions
|
||||||
|
roles:
|
||||||
|
admin: Administrator
|
||||||
|
moderator: Moderator
|
||||||
|
user: User
|
||||||
salmon_url: Salmon URL
|
salmon_url: Salmon URL
|
||||||
search: Search
|
search: Search
|
||||||
shared_inbox_url: Shared Inbox URL
|
shared_inbox_url: Shared Inbox URL
|
||||||
|
|
|
@ -20,16 +20,16 @@ SimpleNavigation::Configuration.run do |navigation|
|
||||||
development.item :your_apps, safe_join([fa_icon('list fw'), t('settings.your_apps')]), settings_applications_url, highlights_on: %r{/settings/applications}
|
development.item :your_apps, safe_join([fa_icon('list fw'), t('settings.your_apps')]), settings_applications_url, highlights_on: %r{/settings/applications}
|
||||||
end
|
end
|
||||||
|
|
||||||
primary.item :admin, safe_join([fa_icon('cogs fw'), t('admin.title')]), admin_reports_url, if: proc { current_user.admin? } do |admin|
|
primary.item :admin, safe_join([fa_icon('cogs fw'), t('admin.title')]), admin_reports_url, if: proc { current_user.staff? } do |admin|
|
||||||
admin.item :reports, safe_join([fa_icon('flag fw'), t('admin.reports.title')]), admin_reports_url, highlights_on: %r{/admin/reports}
|
admin.item :reports, safe_join([fa_icon('flag fw'), t('admin.reports.title')]), admin_reports_url, highlights_on: %r{/admin/reports}
|
||||||
admin.item :accounts, safe_join([fa_icon('users fw'), t('admin.accounts.title')]), admin_accounts_url, highlights_on: %r{/admin/accounts}
|
admin.item :accounts, safe_join([fa_icon('users fw'), t('admin.accounts.title')]), admin_accounts_url, highlights_on: %r{/admin/accounts}
|
||||||
admin.item :instances, safe_join([fa_icon('cloud fw'), t('admin.instances.title')]), admin_instances_url, highlights_on: %r{/admin/instances}
|
admin.item :instances, safe_join([fa_icon('cloud fw'), t('admin.instances.title')]), admin_instances_url, highlights_on: %r{/admin/instances}, if: -> { current_user.admin? }
|
||||||
admin.item :subscriptions, safe_join([fa_icon('paper-plane-o fw'), t('admin.subscriptions.title')]), admin_subscriptions_url
|
admin.item :subscriptions, safe_join([fa_icon('paper-plane-o fw'), t('admin.subscriptions.title')]), admin_subscriptions_url, if: -> { current_user.admin? }
|
||||||
admin.item :domain_blocks, safe_join([fa_icon('lock fw'), t('admin.domain_blocks.title')]), admin_domain_blocks_url, highlights_on: %r{/admin/domain_blocks}
|
admin.item :domain_blocks, safe_join([fa_icon('lock fw'), t('admin.domain_blocks.title')]), admin_domain_blocks_url, highlights_on: %r{/admin/domain_blocks}, if: -> { current_user.admin? }
|
||||||
admin.item :email_domain_blocks, safe_join([fa_icon('envelope fw'), t('admin.email_domain_blocks.title')]), admin_email_domain_blocks_url, highlights_on: %r{/admin/email_domain_blocks}
|
admin.item :email_domain_blocks, safe_join([fa_icon('envelope fw'), t('admin.email_domain_blocks.title')]), admin_email_domain_blocks_url, highlights_on: %r{/admin/email_domain_blocks}, if: -> { current_user.admin? }
|
||||||
admin.item :sidekiq, safe_join([fa_icon('diamond fw'), 'Sidekiq']), sidekiq_url, link_html: { target: 'sidekiq' }
|
admin.item :sidekiq, safe_join([fa_icon('diamond fw'), 'Sidekiq']), sidekiq_url, link_html: { target: 'sidekiq' }, if: -> { current_user.admin? }
|
||||||
admin.item :pghero, safe_join([fa_icon('database fw'), 'PgHero']), pghero_url, link_html: { target: 'pghero' }
|
admin.item :pghero, safe_join([fa_icon('database fw'), 'PgHero']), pghero_url, link_html: { target: 'pghero' }, if: -> { current_user.admin? }
|
||||||
admin.item :settings, safe_join([fa_icon('cogs fw'), t('admin.settings.title')]), edit_admin_settings_url
|
admin.item :settings, safe_join([fa_icon('cogs fw'), t('admin.settings.title')]), edit_admin_settings_url, if: -> { current_user.admin? }
|
||||||
admin.item :custom_emojis, safe_join([fa_icon('smile-o fw'), t('admin.custom_emojis.title')]), admin_custom_emojis_url, highlights_on: %r{/admin/custom_emojis}
|
admin.item :custom_emojis, safe_join([fa_icon('smile-o fw'), t('admin.custom_emojis.title')]), admin_custom_emojis_url, highlights_on: %r{/admin/custom_emojis}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -137,6 +137,13 @@ Rails.application.routes.draw do
|
||||||
resource :suspension, only: [:create, :destroy]
|
resource :suspension, only: [:create, :destroy]
|
||||||
resource :confirmation, only: [:create]
|
resource :confirmation, only: [:create]
|
||||||
resources :statuses, only: [:index, :create, :update, :destroy]
|
resources :statuses, only: [:index, :create, :update, :destroy]
|
||||||
|
|
||||||
|
resource :role do
|
||||||
|
member do
|
||||||
|
post :promote
|
||||||
|
post :demote
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :users, only: [] do
|
resources :users, only: [] do
|
||||||
|
|
15
db/migrate/20171109012327_add_moderator_to_accounts.rb
Normal file
15
db/migrate/20171109012327_add_moderator_to_accounts.rb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
require Rails.root.join('lib', 'mastodon', 'migration_helpers')
|
||||||
|
|
||||||
|
class AddModeratorToAccounts < ActiveRecord::Migration[5.1]
|
||||||
|
include Mastodon::MigrationHelpers
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def up
|
||||||
|
safety_assured { add_column_with_default :users, :moderator, :bool, default: false }
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_column :users, :moderator
|
||||||
|
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: 20171107143624) do
|
ActiveRecord::Schema.define(version: 20171109012327) 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"
|
||||||
|
@ -437,6 +437,7 @@ ActiveRecord::Schema.define(version: 20171107143624) do
|
||||||
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.boolean "disabled", default: false, null: false
|
||||||
|
t.boolean "moderator", 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
|
||||||
|
|
|
@ -10,6 +10,7 @@ namespace :mastodon do
|
||||||
desc 'Turn a user into an admin, identified by the USERNAME environment variable'
|
desc 'Turn a user into an admin, identified by the USERNAME environment variable'
|
||||||
task make_admin: :environment do
|
task make_admin: :environment do
|
||||||
include RoutingHelper
|
include RoutingHelper
|
||||||
|
|
||||||
account_username = ENV.fetch('USERNAME')
|
account_username = ENV.fetch('USERNAME')
|
||||||
user = User.joins(:account).where(accounts: { username: account_username })
|
user = User.joins(:account).where(accounts: { username: account_username })
|
||||||
|
|
||||||
|
@ -17,7 +18,33 @@ namespace :mastodon do
|
||||||
user.update(admin: true)
|
user.update(admin: true)
|
||||||
puts "Congrats! #{account_username} is now an admin. \\o/\nNavigate to #{edit_admin_settings_url} to get started"
|
puts "Congrats! #{account_username} is now an admin. \\o/\nNavigate to #{edit_admin_settings_url} to get started"
|
||||||
else
|
else
|
||||||
puts "User could not be found; please make sure an Account with the `#{account_username}` username exists."
|
puts "User could not be found; please make sure an account with the `#{account_username}` username exists."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
desc 'Turn a user into a moderator, identified by the USERNAME environment variable'
|
||||||
|
task make_mod: :environment do
|
||||||
|
account_username = ENV.fetch('USERNAME')
|
||||||
|
user = User.joins(:account).where(accounts: { username: account_username })
|
||||||
|
|
||||||
|
if user.present?
|
||||||
|
user.update(moderator: true)
|
||||||
|
puts "Congrats! #{account_username} is now a moderator \\o/"
|
||||||
|
else
|
||||||
|
puts "User could not be found; please make sure an account with the `#{account_username}` username exists."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
desc 'Remove admin and moderator privileges from user identified by the USERNAME environment variable'
|
||||||
|
task revoke_staff: :environment do
|
||||||
|
account_username = ENV.fetch('USERNAME')
|
||||||
|
user = User.joins(:account).where(accounts: { username: account_username })
|
||||||
|
|
||||||
|
if user.present?
|
||||||
|
user.update(moderator: false, admin: false)
|
||||||
|
puts "#{account_username} is no longer admin or moderator."
|
||||||
|
else
|
||||||
|
puts "User could not be found; please make sure an account with the `#{account_username}` username exists."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue