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:
		| @@ -1,31 +1,41 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class Admin::AccountModerationNotesController < Admin::BaseController | ||||
|   def create | ||||
|     @account_moderation_note = current_account.account_moderation_notes.new(resource_params) | ||||
|     if @account_moderation_note.save | ||||
|       @target_account = @account_moderation_note.target_account | ||||
|       redirect_to admin_account_path(@target_account.id), notice: I18n.t('admin.account_moderation_notes.created_msg') | ||||
|     else | ||||
|       @account = @account_moderation_note.target_account | ||||
|       @moderation_notes = @account.targeted_moderation_notes.latest | ||||
|       render template: 'admin/accounts/show' | ||||
| module Admin | ||||
|   class AccountModerationNotesController < BaseController | ||||
|     before_action :set_account_moderation_note, only: [:destroy] | ||||
|  | ||||
|     def create | ||||
|       authorize AccountModerationNote, :create? | ||||
|  | ||||
|       @account_moderation_note = current_account.account_moderation_notes.new(resource_params) | ||||
|  | ||||
|       if @account_moderation_note.save | ||||
|         redirect_to admin_account_path(@account_moderation_note.target_account_id), notice: I18n.t('admin.account_moderation_notes.created_msg') | ||||
|       else | ||||
|         @account          = @account_moderation_note.target_account | ||||
|         @moderation_notes = @account.targeted_moderation_notes.latest | ||||
|  | ||||
|         render template: 'admin/accounts/show' | ||||
|       end | ||||
|     end | ||||
|  | ||||
|     def destroy | ||||
|       authorize @account_moderation_note, :destroy? | ||||
|       @account_moderation_note.destroy | ||||
|       redirect_to admin_account_path(@account_moderation_note.target_account_id), notice: I18n.t('admin.account_moderation_notes.destroyed_msg') | ||||
|     end | ||||
|  | ||||
|     private | ||||
|  | ||||
|     def resource_params | ||||
|       params.require(:account_moderation_note).permit( | ||||
|         :content, | ||||
|         :target_account_id | ||||
|       ) | ||||
|     end | ||||
|  | ||||
|     def set_account_moderation_note | ||||
|       @account_moderation_note = AccountModerationNote.find(params[:id]) | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def destroy | ||||
|     @account_moderation_note = AccountModerationNote.find(params[:id]) | ||||
|     @target_account = @account_moderation_note.target_account | ||||
|     @account_moderation_note.destroy | ||||
|     redirect_to admin_account_path(@target_account.id), notice: I18n.t('admin.account_moderation_notes.destroyed_msg') | ||||
|   end | ||||
|  | ||||
|   private | ||||
|  | ||||
|   def resource_params | ||||
|     params.require(:account_moderation_note).permit( | ||||
|       :content, | ||||
|       :target_account_id | ||||
|     ) | ||||
|   end | ||||
| end | ||||
|   | ||||
| @@ -7,40 +7,49 @@ module Admin | ||||
|     before_action :require_local_account!, only: [:enable, :disable, :memorialize] | ||||
|  | ||||
|     def index | ||||
|       authorize :account, :index? | ||||
|       @accounts = filtered_accounts.page(params[:page]) | ||||
|     end | ||||
|  | ||||
|     def show | ||||
|       authorize @account, :show? | ||||
|       @account_moderation_note = current_account.account_moderation_notes.new(target_account: @account) | ||||
|       @moderation_notes = @account.targeted_moderation_notes.latest | ||||
|     end | ||||
|  | ||||
|     def subscribe | ||||
|       authorize @account, :subscribe? | ||||
|       Pubsubhubbub::SubscribeWorker.perform_async(@account.id) | ||||
|       redirect_to admin_account_path(@account.id) | ||||
|     end | ||||
|  | ||||
|     def unsubscribe | ||||
|       authorize @account, :unsubscribe? | ||||
|       Pubsubhubbub::UnsubscribeWorker.perform_async(@account.id) | ||||
|       redirect_to admin_account_path(@account.id) | ||||
|     end | ||||
|  | ||||
|     def memorialize | ||||
|       authorize @account, :memorialize? | ||||
|       @account.memorialize! | ||||
|       redirect_to admin_account_path(@account.id) | ||||
|     end | ||||
|  | ||||
|     def enable | ||||
|       authorize @account.user, :enable? | ||||
|       @account.user.enable! | ||||
|       redirect_to admin_account_path(@account.id) | ||||
|     end | ||||
|  | ||||
|     def disable | ||||
|       authorize @account.user, :disable? | ||||
|       @account.user.disable! | ||||
|       redirect_to admin_account_path(@account.id) | ||||
|     end | ||||
|  | ||||
|     def redownload | ||||
|       authorize @account, :redownload? | ||||
|  | ||||
|       @account.reset_avatar! | ||||
|       @account.reset_header! | ||||
|       @account.save! | ||||
|   | ||||
| @@ -2,7 +2,9 @@ | ||||
|  | ||||
| module Admin | ||||
|   class BaseController < ApplicationController | ||||
|     before_action :require_admin! | ||||
|     include Authorization | ||||
|  | ||||
|     before_action :require_staff! | ||||
|  | ||||
|     layout 'admin' | ||||
|   end | ||||
|   | ||||
| @@ -2,15 +2,18 @@ | ||||
|  | ||||
| module Admin | ||||
|   class ConfirmationsController < BaseController | ||||
|     before_action :set_user | ||||
|  | ||||
|     def create | ||||
|       account_user.confirm | ||||
|       authorize @user, :confirm? | ||||
|       @user.confirm! | ||||
|       redirect_to admin_accounts_path | ||||
|     end | ||||
|  | ||||
|     private | ||||
|  | ||||
|     def account_user | ||||
|       Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound) | ||||
|     def set_user | ||||
|       @user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound) | ||||
|     end | ||||
|   end | ||||
| end | ||||
|   | ||||
| @@ -5,14 +5,18 @@ module Admin | ||||
|     before_action :set_custom_emoji, except: [:index, :new, :create] | ||||
|  | ||||
|     def index | ||||
|       authorize :custom_emoji, :index? | ||||
|       @custom_emojis = filtered_custom_emojis.eager_load(:local_counterpart).page(params[:page]) | ||||
|     end | ||||
|  | ||||
|     def new | ||||
|       authorize :custom_emoji, :create? | ||||
|       @custom_emoji = CustomEmoji.new | ||||
|     end | ||||
|  | ||||
|     def create | ||||
|       authorize :custom_emoji, :create? | ||||
|  | ||||
|       @custom_emoji = CustomEmoji.new(resource_params) | ||||
|  | ||||
|       if @custom_emoji.save | ||||
| @@ -23,6 +27,8 @@ module Admin | ||||
|     end | ||||
|  | ||||
|     def update | ||||
|       authorize @custom_emoji, :update? | ||||
|  | ||||
|       if @custom_emoji.update(resource_params) | ||||
|         redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.updated_msg') | ||||
|       else | ||||
| @@ -31,11 +37,14 @@ module Admin | ||||
|     end | ||||
|  | ||||
|     def destroy | ||||
|       authorize @custom_emoji, :destroy? | ||||
|       @custom_emoji.destroy | ||||
|       redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.destroyed_msg') | ||||
|     end | ||||
|  | ||||
|     def copy | ||||
|       authorize @custom_emoji, :copy? | ||||
|  | ||||
|       emoji = CustomEmoji.find_or_create_by(domain: nil, shortcode: @custom_emoji.shortcode) | ||||
|  | ||||
|       if emoji.update(image: @custom_emoji.image) | ||||
| @@ -48,11 +57,13 @@ module Admin | ||||
|     end | ||||
|  | ||||
|     def enable | ||||
|       authorize @custom_emoji, :enable? | ||||
|       @custom_emoji.update!(disabled: false) | ||||
|       redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.enabled_msg') | ||||
|     end | ||||
|  | ||||
|     def disable | ||||
|       authorize @custom_emoji, :disable? | ||||
|       @custom_emoji.update!(disabled: true) | ||||
|       redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.disabled_msg') | ||||
|     end | ||||
|   | ||||
| @@ -5,14 +5,18 @@ module Admin | ||||
|     before_action :set_domain_block, only: [:show, :destroy] | ||||
|  | ||||
|     def index | ||||
|       authorize :domain_block, :index? | ||||
|       @domain_blocks = DomainBlock.page(params[:page]) | ||||
|     end | ||||
|  | ||||
|     def new | ||||
|       authorize :domain_block, :create? | ||||
|       @domain_block = DomainBlock.new | ||||
|     end | ||||
|  | ||||
|     def create | ||||
|       authorize :domain_block, :create? | ||||
|  | ||||
|       @domain_block = DomainBlock.new(resource_params) | ||||
|  | ||||
|       if @domain_block.save | ||||
| @@ -23,9 +27,12 @@ module Admin | ||||
|       end | ||||
|     end | ||||
|  | ||||
|     def show; end | ||||
|     def show | ||||
|       authorize @domain_block, :show? | ||||
|     end | ||||
|  | ||||
|     def destroy | ||||
|       authorize @domain_block, :destroy? | ||||
|       UnblockDomainService.new.call(@domain_block, retroactive_unblock?) | ||||
|       redirect_to admin_domain_blocks_path, notice: I18n.t('admin.domain_blocks.destroyed_msg') | ||||
|     end | ||||
|   | ||||
| @@ -5,14 +5,18 @@ module Admin | ||||
|     before_action :set_email_domain_block, only: [:show, :destroy] | ||||
|  | ||||
|     def index | ||||
|       authorize :email_domain_block, :index? | ||||
|       @email_domain_blocks = EmailDomainBlock.page(params[:page]) | ||||
|     end | ||||
|  | ||||
|     def new | ||||
|       authorize :email_domain_block, :create? | ||||
|       @email_domain_block = EmailDomainBlock.new | ||||
|     end | ||||
|  | ||||
|     def create | ||||
|       authorize :email_domain_block, :create? | ||||
|  | ||||
|       @email_domain_block = EmailDomainBlock.new(resource_params) | ||||
|  | ||||
|       if @email_domain_block.save | ||||
| @@ -23,6 +27,7 @@ module Admin | ||||
|     end | ||||
|  | ||||
|     def destroy | ||||
|       authorize @email_domain_block, :destroy? | ||||
|       @email_domain_block.destroy | ||||
|       redirect_to admin_email_domain_blocks_path, notice: I18n.t('admin.email_domain_blocks.destroyed_msg') | ||||
|     end | ||||
|   | ||||
| @@ -3,10 +3,12 @@ | ||||
| module Admin | ||||
|   class InstancesController < BaseController | ||||
|     def index | ||||
|       authorize :instance, :index? | ||||
|       @instances = ordered_instances | ||||
|     end | ||||
|  | ||||
|     def resubscribe | ||||
|       authorize :instance, :resubscribe? | ||||
|       params.require(:by_domain) | ||||
|       Pubsubhubbub::SubscribeWorker.push_bulk(subscribeable_accounts.pluck(:id)) | ||||
|       redirect_to admin_instances_path | ||||
|   | ||||
| @@ -2,19 +2,20 @@ | ||||
|  | ||||
| module Admin | ||||
|   class ReportedStatusesController < BaseController | ||||
|     include Authorization | ||||
|  | ||||
|     before_action :set_report | ||||
|     before_action :set_status, only: [:update, :destroy] | ||||
|  | ||||
|     def create | ||||
|       @form = Form::StatusBatch.new(form_status_batch_params) | ||||
|       flash[:alert] = t('admin.statuses.failed_to_execute') unless @form.save | ||||
|       authorize :status, :update? | ||||
|  | ||||
|       @form         = Form::StatusBatch.new(form_status_batch_params) | ||||
|       flash[:alert] = I18n.t('admin.statuses.failed_to_execute') unless @form.save | ||||
|  | ||||
|       redirect_to admin_report_path(@report) | ||||
|     end | ||||
|  | ||||
|     def update | ||||
|       authorize @status, :update? | ||||
|       @status.update(status_params) | ||||
|       redirect_to admin_report_path(@report) | ||||
|     end | ||||
|   | ||||
| @@ -5,14 +5,17 @@ module Admin | ||||
|     before_action :set_report, except: [:index] | ||||
|  | ||||
|     def index | ||||
|       authorize :report, :index? | ||||
|       @reports = filtered_reports.page(params[:page]) | ||||
|     end | ||||
|  | ||||
|     def show | ||||
|       authorize @report, :show? | ||||
|       @form = Form::StatusBatch.new | ||||
|     end | ||||
|  | ||||
|     def update | ||||
|       authorize @report, :update? | ||||
|       process_report | ||||
|       redirect_to admin_report_path(@report) | ||||
|     end | ||||
|   | ||||
| @@ -2,17 +2,18 @@ | ||||
|  | ||||
| module Admin | ||||
|   class ResetsController < BaseController | ||||
|     before_action :set_account | ||||
|     before_action :set_user | ||||
|  | ||||
|     def create | ||||
|       @account.user.send_reset_password_instructions | ||||
|       authorize @user, :reset_password? | ||||
|       @user.send_reset_password_instructions | ||||
|       redirect_to admin_accounts_path | ||||
|     end | ||||
|  | ||||
|     private | ||||
|  | ||||
|     def set_account | ||||
|       @account = Account.find(params[:account_id]) | ||||
|     def set_user | ||||
|       @user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound) | ||||
|     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 | ||||
|  | ||||
|     def edit | ||||
|       authorize :settings, :show? | ||||
|       @admin_settings = Form::AdminSettings.new | ||||
|     end | ||||
|  | ||||
|     def update | ||||
|       authorize :settings, :update? | ||||
|  | ||||
|       settings_params.each do |key, value| | ||||
|         if UPLOAD_SETTINGS.include?(key) | ||||
|           upload = SiteUpload.where(var: key).first_or_initialize(var: key) | ||||
|   | ||||
| @@ -5,11 +5,13 @@ module Admin | ||||
|     before_action :set_account | ||||
|  | ||||
|     def create | ||||
|       authorize @account, :silence? | ||||
|       @account.update(silenced: true) | ||||
|       redirect_to admin_accounts_path | ||||
|     end | ||||
|  | ||||
|     def destroy | ||||
|       authorize @account, :unsilence? | ||||
|       @account.update(silenced: false) | ||||
|       redirect_to admin_accounts_path | ||||
|     end | ||||
|   | ||||
| @@ -2,8 +2,6 @@ | ||||
|  | ||||
| module Admin | ||||
|   class StatusesController < BaseController | ||||
|     include Authorization | ||||
|  | ||||
|     helper_method :current_params | ||||
|  | ||||
|     before_action :set_account | ||||
| @@ -12,24 +10,30 @@ module Admin | ||||
|     PER_PAGE = 20 | ||||
|  | ||||
|     def index | ||||
|       authorize :status, :index? | ||||
|  | ||||
|       @statuses = @account.statuses | ||||
|  | ||||
|       if params[:media] | ||||
|         account_media_status_ids = @account.media_attachments.attached.reorder(nil).select(:status_id).distinct | ||||
|         @statuses.merge!(Status.where(id: account_media_status_ids)) | ||||
|       end | ||||
|       @statuses = @statuses.preload(:media_attachments, :mentions).page(params[:page]).per(PER_PAGE) | ||||
|  | ||||
|       @form = Form::StatusBatch.new | ||||
|       @statuses = @statuses.preload(:media_attachments, :mentions).page(params[:page]).per(PER_PAGE) | ||||
|       @form     = Form::StatusBatch.new | ||||
|     end | ||||
|  | ||||
|     def create | ||||
|       @form = Form::StatusBatch.new(form_status_batch_params) | ||||
|       flash[:alert] = t('admin.statuses.failed_to_execute') unless @form.save | ||||
|       authorize :status, :update? | ||||
|  | ||||
|       @form         = Form::StatusBatch.new(form_status_batch_params) | ||||
|       flash[:alert] = I18n.t('admin.statuses.failed_to_execute') unless @form.save | ||||
|  | ||||
|       redirect_to admin_account_statuses_path(@account.id, current_params) | ||||
|     end | ||||
|  | ||||
|     def update | ||||
|       authorize @status, :update? | ||||
|       @status.update(status_params) | ||||
|       redirect_to admin_account_statuses_path(@account.id, current_params) | ||||
|     end | ||||
| @@ -60,6 +64,7 @@ module Admin | ||||
|  | ||||
|     def current_params | ||||
|       page = (params[:page] || 1).to_i | ||||
|  | ||||
|       { | ||||
|         media: params[:media], | ||||
|         page: page > 1 && page, | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| module Admin | ||||
|   class SubscriptionsController < BaseController | ||||
|     def index | ||||
|       authorize :subscription, :index? | ||||
|       @subscriptions = ordered_subscriptions.page(requested_page) | ||||
|     end | ||||
|  | ||||
|   | ||||
| @@ -5,11 +5,13 @@ module Admin | ||||
|     before_action :set_account | ||||
|  | ||||
|     def create | ||||
|       authorize @account, :suspend? | ||||
|       Admin::SuspensionWorker.perform_async(@account.id) | ||||
|       redirect_to admin_accounts_path | ||||
|     end | ||||
|  | ||||
|     def destroy | ||||
|       authorize @account, :unsuspend? | ||||
|       @account.unsuspend! | ||||
|       redirect_to admin_accounts_path | ||||
|     end | ||||
|   | ||||
| @@ -5,6 +5,7 @@ module Admin | ||||
|     before_action :set_user | ||||
|  | ||||
|     def destroy | ||||
|       authorize @user, :disable_2fa? | ||||
|       @user.disable_two_factor! | ||||
|       redirect_to admin_accounts_path | ||||
|     end | ||||
|   | ||||
| @@ -19,7 +19,7 @@ class Api::V1::ReportsController < Api::BaseController | ||||
|       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 | ||||
|   end | ||||
|   | ||||
| @@ -18,6 +18,7 @@ class ApplicationController < ActionController::Base | ||||
|   rescue_from ActionController::RoutingError, with: :not_found | ||||
|   rescue_from ActiveRecord::RecordNotFound, with: :not_found | ||||
|   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 :check_suspension, if: :user_signed_in? | ||||
| @@ -40,6 +41,10 @@ class ApplicationController < ActionController::Base | ||||
|     redirect_to root_path unless current_user&.admin? | ||||
|   end | ||||
|  | ||||
|   def require_staff! | ||||
|     redirect_to root_path unless current_user&.staff? | ||||
|   end | ||||
|  | ||||
|   def check_suspension | ||||
|     forbidden if current_user.account.suspended? | ||||
|   end | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
|  | ||||
| module Authorization | ||||
|   extend ActiveSupport::Concern | ||||
|  | ||||
|   include Pundit | ||||
|  | ||||
|   def pundit_user | ||||
|   | ||||
| @@ -35,6 +35,11 @@ module ApplicationHelper | ||||
|     Rails.env.production? ? site_title : "#{site_title} (Dev)" | ||||
|   end | ||||
|  | ||||
|   def can?(action, record) | ||||
|     return false if record.nil? | ||||
|     policy(record).public_send("#{action}?") | ||||
|   end | ||||
|  | ||||
|   def fa_icon(icon, attributes = {}) | ||||
|     class_names = attributes[:class]&.split(' ') || [] | ||||
|     class_names << 'fa' | ||||
|   | ||||
| @@ -32,6 +32,7 @@ | ||||
| #  filtered_languages        :string           default([]), not null, is an Array | ||||
| #  account_id                :integer          not null | ||||
| #  disabled                  :boolean          default(FALSE), not null | ||||
| #  moderator                 :boolean          default(FALSE), not null | ||||
| # | ||||
|  | ||||
| class User < ApplicationRecord | ||||
| @@ -53,8 +54,10 @@ class User < ApplicationRecord | ||||
|   validates :locale, inclusion: I18n.available_locales.map(&:to_s), if: :locale? | ||||
|   validates_with BlacklistedEmailValidator, if: :email_changed? | ||||
|  | ||||
|   scope :recent,    -> { order(id: :desc) } | ||||
|   scope :admins,    -> { where(admin: true) } | ||||
|   scope :recent, -> { order(id: :desc) } | ||||
|   scope :admins, -> { where(admin: true) } | ||||
|   scope :moderators, -> { where(moderator: true) } | ||||
|   scope :staff, -> { admins.or(moderators) } | ||||
|   scope :confirmed, -> { where.not(confirmed_at: nil) } | ||||
|   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 }) } | ||||
| @@ -74,6 +77,20 @@ class User < ApplicationRecord | ||||
|     confirmed_at.present? | ||||
|   end | ||||
|  | ||||
|   def staff? | ||||
|     admin? || moderator? | ||||
|   end | ||||
|  | ||||
|   def role | ||||
|     if admin? | ||||
|       'admin' | ||||
|     elsif moderator? | ||||
|       'moderator' | ||||
|     else | ||||
|       'user' | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def disable! | ||||
|     update!(disabled: true, | ||||
|             last_sign_in_at: current_sign_in_at, | ||||
| @@ -84,6 +101,27 @@ class User < ApplicationRecord | ||||
|     update!(disabled: false) | ||||
|   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! | ||||
|     self.otp_required_for_login = false | ||||
|     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 | ||||
|  | ||||
| class StatusPolicy | ||||
|   attr_reader :account, :status | ||||
|  | ||||
|   def initialize(account, status) | ||||
|     @account = account | ||||
|     @status = status | ||||
| class StatusPolicy < ApplicationPolicy | ||||
|   def index? | ||||
|     staff? | ||||
|   end | ||||
|  | ||||
|   def show? | ||||
|     if direct? | ||||
|       owned? || status.mentions.where(account: account).exists? | ||||
|       owned? || record.mentions.where(account: current_account).exists? | ||||
|     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 | ||||
|       account.nil? || !status.account.blocking?(account) | ||||
|       current_account.nil? || !author.blocking?(current_account) | ||||
|     end | ||||
|   end | ||||
|  | ||||
| @@ -23,26 +20,30 @@ class StatusPolicy | ||||
|   end | ||||
|  | ||||
|   def destroy? | ||||
|     admin? || owned? | ||||
|     staff? || owned? | ||||
|   end | ||||
|  | ||||
|   alias unreblog? destroy? | ||||
|  | ||||
|   private | ||||
|  | ||||
|   def admin? | ||||
|     account&.user&.admin? | ||||
|   def update? | ||||
|     staff? | ||||
|   end | ||||
|  | ||||
|   private | ||||
|  | ||||
|   def direct? | ||||
|     status.direct_visibility? | ||||
|     record.direct_visibility? | ||||
|   end | ||||
|  | ||||
|   def owned? | ||||
|     status.account.id == account&.id | ||||
|     author.id == current_account&.id | ||||
|   end | ||||
|  | ||||
|   def private? | ||||
|     status.private_visibility? | ||||
|     record.private_visibility? | ||||
|   end | ||||
|  | ||||
|   def author | ||||
|     record.account | ||||
|   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) } | ||||
|       = l account_moderation_note.created_at | ||||
|   %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? | ||||
|         %tr | ||||
|           %th= t('admin.accounts.email') | ||||
|           %td= @account.user_email | ||||
|           %td | ||||
|             = @account.user_email | ||||
|  | ||||
|             - if @account.user_confirmed? | ||||
|               = fa_icon('check') | ||||
|         %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 | ||||
|               = table_link_to 'unlock', t('admin.accounts.enable'), enable_admin_account_path(@account.id), method: :post if can?(:enable, @account.user) | ||||
|             - else | ||||
|               = 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 | ||||
|           %th= t('admin.accounts.most_recent_ip') | ||||
|           %td= @account.user_current_sign_in_ip | ||||
| @@ -71,28 +75,28 @@ | ||||
| %div{ style: 'overflow: hidden' } | ||||
|   %div{ style: 'float: right' } | ||||
|     - 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? | ||||
|         = 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? | ||||
|         = 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 | ||||
|       = 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' } | ||||
|     - 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 | ||||
|       = 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? | ||||
|       - 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? | ||||
|       = 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 | ||||
|       = 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? | ||||
|   %hr | ||||
| @@ -118,9 +122,9 @@ | ||||
|  | ||||
|   %div{ style: 'overflow: hidden' } | ||||
|     %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? | ||||
|         = 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 | ||||
|   %h3 ActivityPub | ||||
| @@ -141,6 +145,20 @@ | ||||
|           %th= t('admin.accounts.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 | ||||
| %h3= t('admin.accounts.moderation_notes') | ||||
|  | ||||
|   | ||||
| @@ -46,6 +46,7 @@ ignore_missing: | ||||
|   - 'terms.body_html' | ||||
|   - 'application_mailer.salutation' | ||||
|   - 'errors.500' | ||||
|  | ||||
| ignore_unused: | ||||
|   - 'activemodel.errors.*' | ||||
|   - 'activerecord.attributes.*' | ||||
| @@ -58,3 +59,4 @@ ignore_unused: | ||||
|   - 'errors.messages.*' | ||||
|   - 'activerecord.errors.models.doorkeeper/*' | ||||
|   - 'errors.429' | ||||
|   - 'admin.accounts.roles.*' | ||||
|   | ||||
| @@ -62,6 +62,7 @@ en: | ||||
|       by_domain: Domain | ||||
|       confirm: Confirm | ||||
|       confirmed: Confirmed | ||||
|       demote: Demote | ||||
|       disable: Disable | ||||
|       disable_two_factor_authentication: Disable 2FA | ||||
|       disabled: Disabled | ||||
| @@ -101,6 +102,7 @@ en: | ||||
|       outbox_url: Outbox URL | ||||
|       perform_full_suspension: Perform full suspension | ||||
|       profile_url: Profile URL | ||||
|       promote: Promote | ||||
|       protocol: Protocol | ||||
|       public: Public | ||||
|       push_subscription_expires: PuSH subscription expires | ||||
| @@ -108,6 +110,11 @@ en: | ||||
|       reset: Reset | ||||
|       reset_password: Reset password | ||||
|       resubscribe: Resubscribe | ||||
|       role: Permissions | ||||
|       roles: | ||||
|         admin: Administrator | ||||
|         moderator: Moderator | ||||
|         user: User | ||||
|       salmon_url: Salmon URL | ||||
|       search: Search | ||||
|       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} | ||||
|     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 :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 :subscriptions, safe_join([fa_icon('paper-plane-o fw'), t('admin.subscriptions.title')]), admin_subscriptions_url | ||||
|       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 :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 :sidekiq, safe_join([fa_icon('diamond fw'), 'Sidekiq']), sidekiq_url, link_html: { target: 'sidekiq' } | ||||
|       admin.item :pghero, safe_join([fa_icon('database fw'), 'PgHero']), pghero_url, link_html: { target: 'pghero' } | ||||
|       admin.item :settings, safe_join([fa_icon('cogs fw'), t('admin.settings.title')]), edit_admin_settings_url | ||||
|       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, 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}, 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}, if: -> { current_user.admin? } | ||||
|       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' }, if: -> { current_user.admin? } | ||||
|       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} | ||||
|     end | ||||
|  | ||||
|   | ||||
| @@ -137,6 +137,13 @@ Rails.application.routes.draw do | ||||
|       resource :suspension, only: [:create, :destroy] | ||||
|       resource :confirmation, only: [:create] | ||||
|       resources :statuses, only: [:index, :create, :update, :destroy] | ||||
|  | ||||
|       resource :role do | ||||
|         member do | ||||
|           post :promote | ||||
|           post :demote | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|  | ||||
|     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. | ||||
|  | ||||
| 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 | ||||
|   enable_extension "plpgsql" | ||||
| @@ -437,6 +437,7 @@ ActiveRecord::Schema.define(version: 20171107143624) do | ||||
|     t.string "filtered_languages", default: [], null: false, array: true | ||||
|     t.bigint "account_id", 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 ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true | ||||
|     t.index ["email"], name: "index_users_on_email", unique: true | ||||
|   | ||||
| @@ -10,14 +10,41 @@ namespace :mastodon do | ||||
|   desc 'Turn a user into an admin, identified by the USERNAME environment variable' | ||||
|   task make_admin: :environment do | ||||
|     include RoutingHelper | ||||
|  | ||||
|     account_username = ENV.fetch('USERNAME') | ||||
|     user = User.joins(:account).where(accounts: { username: account_username }) | ||||
|     user             = User.joins(:account).where(accounts: { username: account_username }) | ||||
|  | ||||
|     if user.present? | ||||
|       user.update(admin: true) | ||||
|       puts "Congrats! #{account_username} is now an admin. \\o/\nNavigate to #{edit_admin_settings_url} to get started" | ||||
|     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 | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user