Add customizable user roles (#18641)
* Add customizable user roles * Various fixes and improvements * Add migration for old settings and fix tootctl role management
This commit is contained in:
parent
1b4054256f
commit
44b2ee3485
|
@ -67,7 +67,7 @@ Lint/UselessAccessModifier:
|
||||||
- class_methods
|
- class_methods
|
||||||
|
|
||||||
Metrics/AbcSize:
|
Metrics/AbcSize:
|
||||||
Max: 100
|
Max: 115
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'lib/mastodon/*_cli.rb'
|
- 'lib/mastodon/*_cli.rb'
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ Metrics/BlockNesting:
|
||||||
|
|
||||||
Metrics/ClassLength:
|
Metrics/ClassLength:
|
||||||
CountComments: false
|
CountComments: false
|
||||||
Max: 400
|
Max: 500
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'lib/mastodon/*_cli.rb'
|
- 'lib/mastodon/*_cli.rb'
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,15 @@ module Admin
|
||||||
before_action :set_account
|
before_action :set_account
|
||||||
|
|
||||||
def new
|
def new
|
||||||
|
authorize @account, :show?
|
||||||
|
|
||||||
@account_action = Admin::AccountAction.new(type: params[:type], report_id: params[:report_id], send_email_notification: true, include_statuses: true)
|
@account_action = Admin::AccountAction.new(type: params[:type], report_id: params[:report_id], send_email_notification: true, include_statuses: true)
|
||||||
@warning_presets = AccountWarningPreset.all
|
@warning_presets = AccountWarningPreset.all
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
authorize @account, :show?
|
||||||
|
|
||||||
account_action = Admin::AccountAction.new(resource_params)
|
account_action = Admin::AccountAction.new(resource_params)
|
||||||
account_action.target_account = @account
|
account_action.target_account = @account
|
||||||
account_action.current_account = current_account
|
account_action.current_account = current_account
|
||||||
|
|
|
@ -14,6 +14,8 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def batch
|
def batch
|
||||||
|
authorize :account, :index?
|
||||||
|
|
||||||
@form = Form::AccountBatch.new(form_account_batch_params.merge(current_account: current_account, action: action_from_button))
|
@form = Form::AccountBatch.new(form_account_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||||
@form.save
|
@form.save
|
||||||
rescue ActionController::ParameterMissing
|
rescue ActionController::ParameterMissing
|
||||||
|
|
|
@ -4,7 +4,10 @@ module Admin
|
||||||
class ActionLogsController < BaseController
|
class ActionLogsController < BaseController
|
||||||
before_action :set_action_logs
|
before_action :set_action_logs
|
||||||
|
|
||||||
def index; end
|
def index
|
||||||
|
authorize :audit_log, :index?
|
||||||
|
@auditable_accounts = Account.where(id: Admin::ActionLog.reorder(nil).select('distinct account_id')).select(:id, :username)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@ module Admin
|
||||||
|
|
||||||
layout 'admin'
|
layout 'admin'
|
||||||
|
|
||||||
before_action :require_staff!
|
|
||||||
before_action :set_body_classes
|
before_action :set_body_classes
|
||||||
|
after_action :verify_authorized
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,8 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def batch
|
def batch
|
||||||
|
authorize :custom_emoji, :index?
|
||||||
|
|
||||||
@form = Form::CustomEmojiBatch.new(form_custom_emoji_batch_params.merge(current_account: current_account, action: action_from_button))
|
@form = Form::CustomEmojiBatch.new(form_custom_emoji_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||||
@form.save
|
@form.save
|
||||||
rescue ActionController::ParameterMissing
|
rescue ActionController::ParameterMissing
|
||||||
|
|
|
@ -5,7 +5,9 @@ module Admin
|
||||||
include Redisable
|
include Redisable
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@system_checks = Admin::SystemCheck.perform
|
authorize :dashboard, :index?
|
||||||
|
|
||||||
|
@system_checks = Admin::SystemCheck.perform(current_user)
|
||||||
@time_period = (29.days.ago.to_date...Time.now.utc.to_date)
|
@time_period = (29.days.ago.to_date...Time.now.utc.to_date)
|
||||||
@pending_users_count = User.pending.count
|
@pending_users_count = User.pending.count
|
||||||
@pending_reports_count = Report.unresolved.count
|
@pending_reports_count = Report.unresolved.count
|
||||||
|
|
|
@ -12,6 +12,8 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def batch
|
def batch
|
||||||
|
authorize :email_domain_block, :index?
|
||||||
|
|
||||||
@form = Form::EmailDomainBlockBatch.new(form_email_domain_block_batch_params.merge(current_account: current_account, action: action_from_button))
|
@form = Form::EmailDomainBlockBatch.new(form_email_domain_block_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||||
@form.save
|
@form.save
|
||||||
rescue ActionController::ParameterMissing
|
rescue ActionController::ParameterMissing
|
||||||
|
|
|
@ -12,6 +12,8 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
authorize :follow_recommendation, :show?
|
||||||
|
|
||||||
@form = Form::AccountBatch.new(form_account_batch_params.merge(current_account: current_account, action: action_from_button))
|
@form = Form::AccountBatch.new(form_account_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||||
@form.save
|
@form.save
|
||||||
rescue ActionController::ParameterMissing
|
rescue ActionController::ParameterMissing
|
||||||
|
|
|
@ -29,6 +29,8 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def batch
|
def batch
|
||||||
|
authorize :ip_block, :index?
|
||||||
|
|
||||||
@form = Form::IpBlockBatch.new(form_ip_block_batch_params.merge(current_account: current_account, action: action_from_button))
|
@form = Form::IpBlockBatch.new(form_ip_block_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||||
@form.save
|
@form.save
|
||||||
rescue ActionController::ParameterMissing
|
rescue ActionController::ParameterMissing
|
||||||
|
|
|
@ -7,7 +7,7 @@ module Admin
|
||||||
PER_PAGE = 40
|
PER_PAGE = 40
|
||||||
|
|
||||||
def index
|
def index
|
||||||
authorize :account, :index?
|
authorize @account, :show?
|
||||||
|
|
||||||
@accounts = RelationshipFilter.new(@account, filter_params).results.includes(:account_stat, user: [:ips, :invite_request]).page(params[:page]).per(PER_PAGE)
|
@accounts = RelationshipFilter.new(@account, filter_params).results.includes(:account_stat, user: [:ips, :invite_request]).page(params[:page]).per(PER_PAGE)
|
||||||
@form = Form::AccountBatch.new
|
@form = Form::AccountBatch.new
|
||||||
|
|
|
@ -2,20 +2,63 @@
|
||||||
|
|
||||||
module Admin
|
module Admin
|
||||||
class RolesController < BaseController
|
class RolesController < BaseController
|
||||||
before_action :set_user
|
before_action :set_role, except: [:index, :new, :create]
|
||||||
|
|
||||||
def promote
|
def index
|
||||||
authorize @user, :promote?
|
authorize :user_role, :index?
|
||||||
@user.promote!
|
|
||||||
log_action :promote, @user
|
@roles = UserRole.order(position: :desc).page(params[:page])
|
||||||
redirect_to admin_account_path(@user.account_id)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def demote
|
def new
|
||||||
authorize @user, :demote?
|
authorize :user_role, :create?
|
||||||
@user.demote!
|
|
||||||
log_action :demote, @user
|
@role = UserRole.new
|
||||||
redirect_to admin_account_path(@user.account_id)
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
authorize :user_role, :create?
|
||||||
|
|
||||||
|
@role = UserRole.new(resource_params)
|
||||||
|
@role.current_account = current_account
|
||||||
|
|
||||||
|
if @role.save
|
||||||
|
redirect_to admin_roles_path
|
||||||
|
else
|
||||||
|
render :new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
authorize @role, :update?
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
authorize @role, :update?
|
||||||
|
|
||||||
|
@role.current_account = current_account
|
||||||
|
|
||||||
|
if @role.update(resource_params)
|
||||||
|
redirect_to admin_roles_path
|
||||||
|
else
|
||||||
|
render :edit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
authorize @role, :destroy?
|
||||||
|
@role.destroy!
|
||||||
|
redirect_to admin_roles_path
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_role
|
||||||
|
@role = UserRole.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def resource_params
|
||||||
|
params.require(:user_role).permit(:name, :color, :highlighted, :position, permissions_as_keys: [])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,6 +14,8 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def batch
|
def batch
|
||||||
|
authorize :status, :index?
|
||||||
|
|
||||||
@status_batch_action = Admin::StatusBatchAction.new(admin_status_batch_action_params.merge(current_account: current_account, report_id: params[:report_id], type: action_from_button))
|
@status_batch_action = Admin::StatusBatchAction.new(admin_status_batch_action_params.merge(current_account: current_account, report_id: params[:report_id], type: action_from_button))
|
||||||
@status_batch_action.save!
|
@status_batch_action.save!
|
||||||
rescue ActionController::ParameterMissing
|
rescue ActionController::ParameterMissing
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Admin
|
|
||||||
class SubscriptionsController < BaseController
|
|
||||||
def index
|
|
||||||
authorize :subscription, :index?
|
|
||||||
@subscriptions = ordered_subscriptions.page(requested_page)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def ordered_subscriptions
|
|
||||||
Subscription.order(id: :desc).includes(:account)
|
|
||||||
end
|
|
||||||
|
|
||||||
def requested_page
|
|
||||||
params[:page].to_i
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -2,13 +2,15 @@
|
||||||
|
|
||||||
class Admin::Trends::Links::PreviewCardProvidersController < Admin::BaseController
|
class Admin::Trends::Links::PreviewCardProvidersController < Admin::BaseController
|
||||||
def index
|
def index
|
||||||
authorize :preview_card_provider, :index?
|
authorize :preview_card_provider, :review?
|
||||||
|
|
||||||
@preview_card_providers = filtered_preview_card_providers.page(params[:page])
|
@preview_card_providers = filtered_preview_card_providers.page(params[:page])
|
||||||
@form = Trends::PreviewCardProviderBatch.new
|
@form = Trends::PreviewCardProviderBatch.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def batch
|
def batch
|
||||||
|
authorize :preview_card_provider, :review?
|
||||||
|
|
||||||
@form = Trends::PreviewCardProviderBatch.new(trends_preview_card_provider_batch_params.merge(current_account: current_account, action: action_from_button))
|
@form = Trends::PreviewCardProviderBatch.new(trends_preview_card_provider_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||||
@form.save
|
@form.save
|
||||||
rescue ActionController::ParameterMissing
|
rescue ActionController::ParameterMissing
|
||||||
|
|
|
@ -2,13 +2,15 @@
|
||||||
|
|
||||||
class Admin::Trends::LinksController < Admin::BaseController
|
class Admin::Trends::LinksController < Admin::BaseController
|
||||||
def index
|
def index
|
||||||
authorize :preview_card, :index?
|
authorize :preview_card, :review?
|
||||||
|
|
||||||
@preview_cards = filtered_preview_cards.page(params[:page])
|
@preview_cards = filtered_preview_cards.page(params[:page])
|
||||||
@form = Trends::PreviewCardBatch.new
|
@form = Trends::PreviewCardBatch.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def batch
|
def batch
|
||||||
|
authorize :preview_card, :review?
|
||||||
|
|
||||||
@form = Trends::PreviewCardBatch.new(trends_preview_card_batch_params.merge(current_account: current_account, action: action_from_button))
|
@form = Trends::PreviewCardBatch.new(trends_preview_card_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||||
@form.save
|
@form.save
|
||||||
rescue ActionController::ParameterMissing
|
rescue ActionController::ParameterMissing
|
||||||
|
|
|
@ -2,13 +2,15 @@
|
||||||
|
|
||||||
class Admin::Trends::StatusesController < Admin::BaseController
|
class Admin::Trends::StatusesController < Admin::BaseController
|
||||||
def index
|
def index
|
||||||
authorize :status, :index?
|
authorize :status, :review?
|
||||||
|
|
||||||
@statuses = filtered_statuses.page(params[:page])
|
@statuses = filtered_statuses.page(params[:page])
|
||||||
@form = Trends::StatusBatch.new
|
@form = Trends::StatusBatch.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def batch
|
def batch
|
||||||
|
authorize :status, :review?
|
||||||
|
|
||||||
@form = Trends::StatusBatch.new(trends_status_batch_params.merge(current_account: current_account, action: action_from_button))
|
@form = Trends::StatusBatch.new(trends_status_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||||
@form.save
|
@form.save
|
||||||
rescue ActionController::ParameterMissing
|
rescue ActionController::ParameterMissing
|
||||||
|
|
|
@ -2,13 +2,15 @@
|
||||||
|
|
||||||
class Admin::Trends::TagsController < Admin::BaseController
|
class Admin::Trends::TagsController < Admin::BaseController
|
||||||
def index
|
def index
|
||||||
authorize :tag, :index?
|
authorize :tag, :review?
|
||||||
|
|
||||||
@tags = filtered_tags.page(params[:page])
|
@tags = filtered_tags.page(params[:page])
|
||||||
@form = Trends::TagBatch.new
|
@form = Trends::TagBatch.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def batch
|
def batch
|
||||||
|
authorize :tag, :review?
|
||||||
|
|
||||||
@form = Trends::TagBatch.new(trends_tag_batch_params.merge(current_account: current_account, action: action_from_button))
|
@form = Trends::TagBatch.new(trends_tag_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||||
@form.save
|
@form.save
|
||||||
rescue ActionController::ParameterMissing
|
rescue ActionController::ParameterMissing
|
||||||
|
|
33
app/controllers/admin/users/roles_controller.rb
Normal file
33
app/controllers/admin/users/roles_controller.rb
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Admin
|
||||||
|
class Users::RolesController < BaseController
|
||||||
|
before_action :set_user
|
||||||
|
|
||||||
|
def show
|
||||||
|
authorize @user, :change_role?
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
authorize @user, :change_role?
|
||||||
|
|
||||||
|
@user.current_account = current_account
|
||||||
|
|
||||||
|
if @user.update(resource_params)
|
||||||
|
redirect_to admin_account_path(@user.account_id), notice: I18n.t('admin.accounts.change_role.changed_msg')
|
||||||
|
else
|
||||||
|
render :show
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_user
|
||||||
|
@user = User.find(params[:user_id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def resource_params
|
||||||
|
params.require(:user).permit(:role_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Admin
|
module Admin
|
||||||
class TwoFactorAuthenticationsController < BaseController
|
class Users::TwoFactorAuthenticationsController < BaseController
|
||||||
before_action :set_target_user
|
before_action :set_target_user
|
||||||
|
|
||||||
def destroy
|
def destroy
|
|
@ -1,11 +1,16 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::Admin::AccountActionsController < Api::BaseController
|
class Api::V1::Admin::AccountActionsController < Api::BaseController
|
||||||
|
include Authorization
|
||||||
|
|
||||||
before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:accounts' }
|
before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:accounts' }
|
||||||
before_action :require_staff!
|
|
||||||
before_action :set_account
|
before_action :set_account
|
||||||
|
|
||||||
|
after_action :verify_authorized
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
authorize @account, :show?
|
||||||
|
|
||||||
account_action = Admin::AccountAction.new(resource_params)
|
account_action = Admin::AccountAction.new(resource_params)
|
||||||
account_action.target_account = @account
|
account_action.target_account = @account
|
||||||
account_action.current_account = current_account
|
account_action.current_account = current_account
|
||||||
|
|
|
@ -8,11 +8,11 @@ class Api::V1::Admin::AccountsController < Api::BaseController
|
||||||
|
|
||||||
before_action -> { authorize_if_got_token! :'admin:read', :'admin:read:accounts' }, only: [:index, :show]
|
before_action -> { authorize_if_got_token! :'admin:read', :'admin:read:accounts' }, only: [:index, :show]
|
||||||
before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:accounts' }, except: [:index, :show]
|
before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:accounts' }, except: [:index, :show]
|
||||||
before_action :require_staff!
|
|
||||||
before_action :set_accounts, only: :index
|
before_action :set_accounts, only: :index
|
||||||
before_action :set_account, except: :index
|
before_action :set_account, except: :index
|
||||||
before_action :require_local_account!, only: [:enable, :approve, :reject]
|
before_action :require_local_account!, only: [:enable, :approve, :reject]
|
||||||
|
|
||||||
|
after_action :verify_authorized
|
||||||
after_action :insert_pagination_headers, only: :index
|
after_action :insert_pagination_headers, only: :index
|
||||||
|
|
||||||
FILTER_PARAMS = %i(
|
FILTER_PARAMS = %i(
|
||||||
|
@ -119,7 +119,9 @@ class Api::V1::Admin::AccountsController < Api::BaseController
|
||||||
translated_params[:status] = status.to_s if params[status].present?
|
translated_params[:status] = status.to_s if params[status].present?
|
||||||
end
|
end
|
||||||
|
|
||||||
translated_params[:permissions] = 'staff' if params[:staff].present?
|
if params[:staff].present?
|
||||||
|
translated_params[:role_ids] = UserRole.that_can(:manage_reports).map(&:id)
|
||||||
|
end
|
||||||
|
|
||||||
translated_params
|
translated_params
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::Admin::DimensionsController < Api::BaseController
|
class Api::V1::Admin::DimensionsController < Api::BaseController
|
||||||
|
include Authorization
|
||||||
|
|
||||||
before_action -> { authorize_if_got_token! :'admin:read' }
|
before_action -> { authorize_if_got_token! :'admin:read' }
|
||||||
before_action :require_staff!
|
|
||||||
before_action :set_dimensions
|
before_action :set_dimensions
|
||||||
|
|
||||||
|
after_action :verify_authorized
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
authorize :dashboard, :index?
|
||||||
render json: @dimensions, each_serializer: REST::Admin::DimensionSerializer
|
render json: @dimensions, each_serializer: REST::Admin::DimensionSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,10 @@ class Api::V1::Admin::DomainAllowsController < Api::BaseController
|
||||||
|
|
||||||
before_action -> { authorize_if_got_token! :'admin:read', :'admin:read:domain_allows' }, only: [:index, :show]
|
before_action -> { authorize_if_got_token! :'admin:read', :'admin:read:domain_allows' }, only: [:index, :show]
|
||||||
before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:domain_allows' }, except: [:index, :show]
|
before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:domain_allows' }, except: [:index, :show]
|
||||||
before_action :require_staff!
|
|
||||||
before_action :set_domain_allows, only: :index
|
before_action :set_domain_allows, only: :index
|
||||||
before_action :set_domain_allow, only: [:show, :destroy]
|
before_action :set_domain_allow, only: [:show, :destroy]
|
||||||
|
|
||||||
|
after_action :verify_authorized
|
||||||
after_action :insert_pagination_headers, only: :index
|
after_action :insert_pagination_headers, only: :index
|
||||||
|
|
||||||
PAGINATION_PARAMS = %i(limit).freeze
|
PAGINATION_PARAMS = %i(limit).freeze
|
||||||
|
|
|
@ -8,10 +8,10 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController
|
||||||
|
|
||||||
before_action -> { authorize_if_got_token! :'admin:read', :'admin:read:domain_blocks' }, only: [:index, :show]
|
before_action -> { authorize_if_got_token! :'admin:read', :'admin:read:domain_blocks' }, only: [:index, :show]
|
||||||
before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:domain_blocks' }, except: [:index, :show]
|
before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:domain_blocks' }, except: [:index, :show]
|
||||||
before_action :require_staff!
|
|
||||||
before_action :set_domain_blocks, only: :index
|
before_action :set_domain_blocks, only: :index
|
||||||
before_action :set_domain_block, only: [:show, :update, :destroy]
|
before_action :set_domain_block, only: [:show, :update, :destroy]
|
||||||
|
|
||||||
|
after_action :verify_authorized
|
||||||
after_action :insert_pagination_headers, only: :index
|
after_action :insert_pagination_headers, only: :index
|
||||||
|
|
||||||
PAGINATION_PARAMS = %i(limit).freeze
|
PAGINATION_PARAMS = %i(limit).freeze
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::Admin::MeasuresController < Api::BaseController
|
class Api::V1::Admin::MeasuresController < Api::BaseController
|
||||||
|
include Authorization
|
||||||
|
|
||||||
before_action -> { authorize_if_got_token! :'admin:read' }
|
before_action -> { authorize_if_got_token! :'admin:read' }
|
||||||
before_action :require_staff!
|
|
||||||
before_action :set_measures
|
before_action :set_measures
|
||||||
|
|
||||||
|
after_action :verify_authorized
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
authorize :dashboard, :index?
|
||||||
render json: @measures, each_serializer: REST::Admin::MeasureSerializer
|
render json: @measures, each_serializer: REST::Admin::MeasureSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,10 @@ class Api::V1::Admin::ReportsController < Api::BaseController
|
||||||
|
|
||||||
before_action -> { authorize_if_got_token! :'admin:read', :'admin:read:reports' }, only: [:index, :show]
|
before_action -> { authorize_if_got_token! :'admin:read', :'admin:read:reports' }, only: [:index, :show]
|
||||||
before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:reports' }, except: [:index, :show]
|
before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:reports' }, except: [:index, :show]
|
||||||
before_action :require_staff!
|
|
||||||
before_action :set_reports, only: :index
|
before_action :set_reports, only: :index
|
||||||
before_action :set_report, except: :index
|
before_action :set_report, except: :index
|
||||||
|
|
||||||
|
after_action :verify_authorized
|
||||||
after_action :insert_pagination_headers, only: :index
|
after_action :insert_pagination_headers, only: :index
|
||||||
|
|
||||||
FILTER_PARAMS = %i(
|
FILTER_PARAMS = %i(
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::Admin::RetentionController < Api::BaseController
|
class Api::V1::Admin::RetentionController < Api::BaseController
|
||||||
|
include Authorization
|
||||||
|
|
||||||
before_action -> { authorize_if_got_token! :'admin:read' }
|
before_action -> { authorize_if_got_token! :'admin:read' }
|
||||||
before_action :require_staff!
|
|
||||||
before_action :set_cohorts
|
before_action :set_cohorts
|
||||||
|
|
||||||
|
after_action :verify_authorized
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
authorize :dashboard, :index?
|
||||||
render json: @cohorts, each_serializer: REST::Admin::CohortSerializer
|
render json: @cohorts, each_serializer: REST::Admin::CohortSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::Admin::Trends::LinksController < Api::BaseController
|
class Api::V1::Admin::Trends::LinksController < Api::V1::Trends::LinksController
|
||||||
before_action -> { authorize_if_got_token! :'admin:read' }
|
before_action -> { authorize_if_got_token! :'admin:read' }
|
||||||
before_action :require_staff!
|
|
||||||
before_action :set_links
|
|
||||||
|
|
||||||
def index
|
|
||||||
render json: @links, each_serializer: REST::Trends::LinkSerializer
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_links
|
def enabled?
|
||||||
@links = Trends.links.query.limit(limit_param(10))
|
super || current_user&.can?(:manage_taxonomies)
|
||||||
|
end
|
||||||
|
|
||||||
|
def links_from_trends
|
||||||
|
if current_user&.can?(:manage_taxonomies)
|
||||||
|
Trends.links.query
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::Admin::Trends::StatusesController < Api::BaseController
|
class Api::V1::Admin::Trends::StatusesController < Api::V1::Trends::StatusesController
|
||||||
before_action -> { authorize_if_got_token! :'admin:read' }
|
before_action -> { authorize_if_got_token! :'admin:read' }
|
||||||
before_action :require_staff!
|
|
||||||
before_action :set_statuses
|
|
||||||
|
|
||||||
def index
|
|
||||||
render json: @statuses, each_serializer: REST::StatusSerializer
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_statuses
|
def enabled?
|
||||||
@statuses = cache_collection(Trends.statuses.query.limit(limit_param(DEFAULT_STATUSES_LIMIT)), Status)
|
super || current_user&.can?(:manage_taxonomies)
|
||||||
|
end
|
||||||
|
|
||||||
|
def statuses_from_trends
|
||||||
|
if current_user&.can?(:manage_taxonomies)
|
||||||
|
Trends.statuses.query
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::Admin::Trends::TagsController < Api::BaseController
|
class Api::V1::Admin::Trends::TagsController < Api::V1::Trends::TagsController
|
||||||
before_action -> { authorize_if_got_token! :'admin:read' }
|
before_action -> { authorize_if_got_token! :'admin:read' }
|
||||||
before_action :require_staff!
|
|
||||||
before_action :set_tags
|
|
||||||
|
|
||||||
def index
|
|
||||||
render json: @tags, each_serializer: REST::Admin::TagSerializer
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_tags
|
def enabled?
|
||||||
@tags = Trends.tags.query.limit(limit_param(10))
|
super || current_user&.can?(:manage_taxonomies)
|
||||||
|
end
|
||||||
|
|
||||||
|
def tags_from_trends
|
||||||
|
if current_user&.can?(:manage_taxonomies)
|
||||||
|
Trends.tags.query
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,10 +13,14 @@ class Api::V1::Trends::LinksController < Api::BaseController
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def enabled?
|
||||||
|
Setting.trends
|
||||||
|
end
|
||||||
|
|
||||||
def set_links
|
def set_links
|
||||||
@links = begin
|
@links = begin
|
||||||
if Setting.trends
|
if enabled?
|
||||||
links_from_trends
|
links_from_trends.offset(offset_param).limit(limit_param(DEFAULT_LINKS_LIMIT))
|
||||||
else
|
else
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
|
@ -24,7 +28,7 @@ class Api::V1::Trends::LinksController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def links_from_trends
|
def links_from_trends
|
||||||
Trends.links.query.allowed.in_locale(content_locale).offset(offset_param).limit(limit_param(DEFAULT_LINKS_LIMIT))
|
Trends.links.query.allowed.in_locale(content_locale)
|
||||||
end
|
end
|
||||||
|
|
||||||
def insert_pagination_headers
|
def insert_pagination_headers
|
||||||
|
|
|
@ -11,10 +11,14 @@ class Api::V1::Trends::StatusesController < Api::BaseController
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def enabled?
|
||||||
|
Setting.trends
|
||||||
|
end
|
||||||
|
|
||||||
def set_statuses
|
def set_statuses
|
||||||
@statuses = begin
|
@statuses = begin
|
||||||
if Setting.trends
|
if enabled?
|
||||||
cache_collection(statuses_from_trends, Status)
|
cache_collection(statuses_from_trends.offset(offset_param).limit(limit_param(DEFAULT_STATUSES_LIMIT)), Status)
|
||||||
else
|
else
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
|
@ -24,7 +28,7 @@ class Api::V1::Trends::StatusesController < Api::BaseController
|
||||||
def statuses_from_trends
|
def statuses_from_trends
|
||||||
scope = Trends.statuses.query.allowed.in_locale(content_locale)
|
scope = Trends.statuses.query.allowed.in_locale(content_locale)
|
||||||
scope = scope.filtered_for(current_account) if user_signed_in?
|
scope = scope.filtered_for(current_account) if user_signed_in?
|
||||||
scope.offset(offset_param).limit(limit_param(DEFAULT_STATUSES_LIMIT))
|
scope
|
||||||
end
|
end
|
||||||
|
|
||||||
def insert_pagination_headers
|
def insert_pagination_headers
|
||||||
|
|
|
@ -13,16 +13,24 @@ class Api::V1::Trends::TagsController < Api::BaseController
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def enabled?
|
||||||
|
Setting.trends
|
||||||
|
end
|
||||||
|
|
||||||
def set_tags
|
def set_tags
|
||||||
@tags = begin
|
@tags = begin
|
||||||
if Setting.trends
|
if enabled?
|
||||||
Trends.tags.query.allowed.offset(offset_param).limit(limit_param(DEFAULT_TAGS_LIMIT))
|
tags_from_trends.offset(offset_param).limit(limit_param(DEFAULT_TAGS_LIMIT))
|
||||||
else
|
else
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def tags_from_trends
|
||||||
|
Trends.tags.query.allowed
|
||||||
|
end
|
||||||
|
|
||||||
def insert_pagination_headers
|
def insert_pagination_headers
|
||||||
set_pagination_headers(next_path, prev_path)
|
set_pagination_headers(next_path, prev_path)
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,6 +11,7 @@ class Api::V2::Admin::AccountsController < Api::V1::Admin::AccountsController
|
||||||
email
|
email
|
||||||
ip
|
ip
|
||||||
invited_by
|
invited_by
|
||||||
|
role_ids
|
||||||
).freeze
|
).freeze
|
||||||
|
|
||||||
PAGINATION_PARAMS = (%i(limit) + FILTER_PARAMS).freeze
|
PAGINATION_PARAMS = (%i(limit) + FILTER_PARAMS).freeze
|
||||||
|
@ -18,7 +19,17 @@ class Api::V2::Admin::AccountsController < Api::V1::Admin::AccountsController
|
||||||
private
|
private
|
||||||
|
|
||||||
def filtered_accounts
|
def filtered_accounts
|
||||||
AccountFilter.new(filter_params).results
|
AccountFilter.new(translated_filter_params).results
|
||||||
|
end
|
||||||
|
|
||||||
|
def translated_filter_params
|
||||||
|
translated_params = filter_params.slice(*AccountFilter::KEYS)
|
||||||
|
|
||||||
|
if params[:permissions] == 'staff'
|
||||||
|
translated_params[:role_ids] = UserRole.that_can(:manage_reports).map(&:id)
|
||||||
|
end
|
||||||
|
|
||||||
|
translated_params
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter_params
|
def filter_params
|
||||||
|
|
|
@ -56,14 +56,6 @@ class ApplicationController < ActionController::Base
|
||||||
store_location_for(:user, request.url) unless [:json, :rss].include?(request.format&.to_sym)
|
store_location_for(:user, request.url) unless [:json, :rss].include?(request.format&.to_sym)
|
||||||
end
|
end
|
||||||
|
|
||||||
def require_admin!
|
|
||||||
forbidden unless current_user&.admin?
|
|
||||||
end
|
|
||||||
|
|
||||||
def require_staff!
|
|
||||||
forbidden unless current_user&.staff?
|
|
||||||
end
|
|
||||||
|
|
||||||
def require_functional!
|
def require_functional!
|
||||||
redirect_to edit_user_registration_path unless current_user.functional?
|
redirect_to edit_user_registration_path unless current_user.functional?
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,6 +13,6 @@ class CustomCssController < ApplicationController
|
||||||
def show
|
def show
|
||||||
expires_in 3.minutes, public: true
|
expires_in 3.minutes, public: true
|
||||||
request.session_options[:skip] = true
|
request.session_options[:skip] = true
|
||||||
render plain: Setting.custom_css || '', content_type: 'text/css'
|
render content_type: 'text/css'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -61,21 +61,13 @@ module AccountsHelper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def account_badge(account, all: false)
|
def account_badge(account)
|
||||||
if account.bot?
|
if account.bot?
|
||||||
content_tag(:div, content_tag(:div, t('accounts.roles.bot'), class: 'account-role bot'), class: 'roles')
|
content_tag(:div, content_tag(:div, t('accounts.roles.bot'), class: 'account-role bot'), class: 'roles')
|
||||||
elsif account.group?
|
elsif account.group?
|
||||||
content_tag(:div, content_tag(:div, t('accounts.roles.group'), class: 'account-role group'), class: 'roles')
|
content_tag(:div, content_tag(:div, t('accounts.roles.group'), class: 'account-role group'), class: 'roles')
|
||||||
elsif (Setting.show_staff_badge && account.user_staff?) || all
|
elsif account.user_role&.highlighted?
|
||||||
content_tag(:div, class: 'roles') do
|
content_tag(:div, content_tag(:div, account.user_role.name, class: "account-role user-role-#{account.user_role.id}"), class: 'roles')
|
||||||
if all && !account.user_staff?
|
|
||||||
content_tag(:div, t('admin.accounts.roles.user'), class: 'account-role')
|
|
||||||
elsif account.user_admin?
|
|
||||||
content_tag(:div, t('accounts.roles.admin'), class: 'account-role admin')
|
|
||||||
elsif account.user_moderator?
|
|
||||||
content_tag(:div, t('accounts.roles.moderator'), class: 'account-role moderator')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,9 @@ import IconButton from './icon_button';
|
||||||
import DropdownMenuContainer from '../containers/dropdown_menu_container';
|
import DropdownMenuContainer from '../containers/dropdown_menu_container';
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { me, isStaff } from '../initial_state';
|
import { me } from '../initial_state';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { PERMISSION_MANAGE_USERS } from 'mastodon/permissions';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
delete: { id: 'status.delete', defaultMessage: 'Delete' },
|
delete: { id: 'status.delete', defaultMessage: 'Delete' },
|
||||||
|
@ -55,6 +56,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object,
|
router: PropTypes.object,
|
||||||
|
identity: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -306,7 +308,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isStaff) {
|
if ((this.context.identity.permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS) {
|
||||||
menu.push(null);
|
menu.push(null);
|
||||||
menu.push({ text: intl.formatMessage(messages.admin_account, { name: account.get('username') }), href: `/admin/accounts/${status.getIn(['account', 'id'])}` });
|
menu.push({ text: intl.formatMessage(messages.admin_account, { name: account.get('username') }), href: `/admin/accounts/${status.getIn(['account', 'id'])}` });
|
||||||
menu.push({ text: intl.formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses?id=${status.get('id')}` });
|
menu.push({ text: intl.formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses?id=${status.get('id')}` });
|
||||||
|
|
|
@ -26,6 +26,7 @@ const createIdentityContext = state => ({
|
||||||
signedIn: !!state.meta.me,
|
signedIn: !!state.meta.me,
|
||||||
accountId: state.meta.me,
|
accountId: state.meta.me,
|
||||||
accessToken: state.meta.access_token,
|
accessToken: state.meta.access_token,
|
||||||
|
permissions: state.role.permissions,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default class Mastodon extends React.PureComponent {
|
export default class Mastodon extends React.PureComponent {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import Button from 'mastodon/components/button';
|
import Button from 'mastodon/components/button';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { autoPlayGif, me, isStaff } from 'mastodon/initial_state';
|
import { autoPlayGif, me } from 'mastodon/initial_state';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import Icon from 'mastodon/components/icon';
|
import Icon from 'mastodon/components/icon';
|
||||||
import IconButton from 'mastodon/components/icon_button';
|
import IconButton from 'mastodon/components/icon_button';
|
||||||
|
@ -14,6 +14,7 @@ import ShortNumber from 'mastodon/components/short_number';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container';
|
import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container';
|
||||||
import AccountNoteContainer from '../containers/account_note_container';
|
import AccountNoteContainer from '../containers/account_note_container';
|
||||||
|
import { PERMISSION_MANAGE_USERS } from 'mastodon/permissions';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
||||||
|
@ -64,6 +65,10 @@ const dateFormatOptions = {
|
||||||
export default @injectIntl
|
export default @injectIntl
|
||||||
class Header extends ImmutablePureComponent {
|
class Header extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static contextTypes = {
|
||||||
|
identity: PropTypes.object,
|
||||||
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
account: ImmutablePropTypes.map,
|
account: ImmutablePropTypes.map,
|
||||||
identity_props: ImmutablePropTypes.list,
|
identity_props: ImmutablePropTypes.list,
|
||||||
|
@ -241,7 +246,7 @@ class Header extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (account.get('id') !== me && isStaff) {
|
if (account.get('id') !== me && (this.context.identity.permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS) {
|
||||||
menu.push(null);
|
menu.push(null);
|
||||||
menu.push({ text: intl.formatMessage(messages.admin_account, { name: account.get('username') }), href: `/admin/accounts/${account.get('id')}` });
|
menu.push({ text: intl.formatMessage(messages.admin_account, { name: account.get('username') }), href: `/admin/accounts/${account.get('id')}` });
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,14 @@ import { FormattedMessage } from 'react-intl';
|
||||||
import ClearColumnButton from './clear_column_button';
|
import ClearColumnButton from './clear_column_button';
|
||||||
import GrantPermissionButton from './grant_permission_button';
|
import GrantPermissionButton from './grant_permission_button';
|
||||||
import SettingToggle from './setting_toggle';
|
import SettingToggle from './setting_toggle';
|
||||||
import { isStaff } from 'mastodon/initial_state';
|
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_REPORTS } from 'mastodon/permissions';
|
||||||
|
|
||||||
export default class ColumnSettings extends React.PureComponent {
|
export default class ColumnSettings extends React.PureComponent {
|
||||||
|
|
||||||
|
static contextTypes = {
|
||||||
|
identity: PropTypes.object,
|
||||||
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
settings: ImmutablePropTypes.map.isRequired,
|
settings: ImmutablePropTypes.map.isRequired,
|
||||||
pushSettings: ImmutablePropTypes.map.isRequired,
|
pushSettings: ImmutablePropTypes.map.isRequired,
|
||||||
|
@ -166,7 +170,7 @@ export default class ColumnSettings extends React.PureComponent {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isStaff && (
|
{(this.context.identity.permissions & PERMISSION_MANAGE_USERS === PERMISSION_MANAGE_USERS) && (
|
||||||
<div role='group' aria-labelledby='notifications-admin-sign-up'>
|
<div role='group' aria-labelledby='notifications-admin-sign-up'>
|
||||||
<span id='notifications-status' className='column-settings__section'><FormattedMessage id='notifications.column_settings.admin.sign_up' defaultMessage='New sign-ups:' /></span>
|
<span id='notifications-status' className='column-settings__section'><FormattedMessage id='notifications.column_settings.admin.sign_up' defaultMessage='New sign-ups:' /></span>
|
||||||
|
|
||||||
|
@ -179,7 +183,7 @@ export default class ColumnSettings extends React.PureComponent {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isStaff && (
|
{(this.context.identity.permissions & PERMISSION_MANAGE_REPORTS === PERMISSION_MANAGE_REPORTS) && (
|
||||||
<div role='group' aria-labelledby='notifications-admin-report'>
|
<div role='group' aria-labelledby='notifications-admin-report'>
|
||||||
<span id='notifications-status' className='column-settings__section'><FormattedMessage id='notifications.column_settings.admin.report' defaultMessage='New reports:' /></span>
|
<span id='notifications-status' className='column-settings__section'><FormattedMessage id='notifications.column_settings.admin.report' defaultMessage='New reports:' /></span>
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,9 @@ import IconButton from '../../../components/icon_button';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import DropdownMenuContainer from '../../../containers/dropdown_menu_container';
|
import DropdownMenuContainer from '../../../containers/dropdown_menu_container';
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import { me, isStaff } from '../../../initial_state';
|
import { me } from '../../../initial_state';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { PERMISSION_MANAGE_USERS } from 'mastodon/permissions';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
delete: { id: 'status.delete', defaultMessage: 'Delete' },
|
delete: { id: 'status.delete', defaultMessage: 'Delete' },
|
||||||
|
@ -50,6 +51,7 @@ class ActionBar extends React.PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object,
|
router: PropTypes.object,
|
||||||
|
identity: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -248,7 +250,7 @@ class ActionBar extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isStaff) {
|
if ((this.context.identity.permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS) {
|
||||||
menu.push(null);
|
menu.push(null);
|
||||||
menu.push({ text: intl.formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), href: `/admin/accounts/${status.getIn(['account', 'id'])}` });
|
menu.push({ text: intl.formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), href: `/admin/accounts/${status.getIn(['account', 'id'])}` });
|
||||||
menu.push({ text: intl.formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses?id=${status.get('id')}` });
|
menu.push({ text: intl.formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses?id=${status.get('id')}` });
|
||||||
|
|
|
@ -3,9 +3,10 @@ import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { invitesEnabled, limitedFederationMode, version, repository, source_url, profile_directory as profileDirectory } from 'mastodon/initial_state';
|
import { limitedFederationMode, version, repository, source_url, profile_directory as profileDirectory } from 'mastodon/initial_state';
|
||||||
import { logOut } from 'mastodon/utils/log_out';
|
import { logOut } from 'mastodon/utils/log_out';
|
||||||
import { openModal } from 'mastodon/actions/modal';
|
import { openModal } from 'mastodon/actions/modal';
|
||||||
|
import { PERMISSION_INVITE_USERS } from 'mastodon/permissions';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
logoutMessage: { id: 'confirmations.logout.message', defaultMessage: 'Are you sure you want to log out?' },
|
logoutMessage: { id: 'confirmations.logout.message', defaultMessage: 'Are you sure you want to log out?' },
|
||||||
|
@ -27,6 +28,10 @@ export default @injectIntl
|
||||||
@connect(null, mapDispatchToProps)
|
@connect(null, mapDispatchToProps)
|
||||||
class LinkFooter extends React.PureComponent {
|
class LinkFooter extends React.PureComponent {
|
||||||
|
|
||||||
|
static contextTypes = {
|
||||||
|
identity: PropTypes.object,
|
||||||
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
withHotkeys: PropTypes.bool,
|
withHotkeys: PropTypes.bool,
|
||||||
onLogout: PropTypes.func.isRequired,
|
onLogout: PropTypes.func.isRequired,
|
||||||
|
@ -48,7 +53,7 @@ class LinkFooter extends React.PureComponent {
|
||||||
return (
|
return (
|
||||||
<div className='getting-started__footer'>
|
<div className='getting-started__footer'>
|
||||||
<ul>
|
<ul>
|
||||||
{invitesEnabled && <li><a href='/invites' target='_blank'><FormattedMessage id='getting_started.invite' defaultMessage='Invite people' /></a> · </li>}
|
{((this.context.identity.permissions & PERMISSION_INVITE_USERS) === PERMISSION_INVITE_USERS) && <li><a href='/invites' target='_blank'><FormattedMessage id='getting_started.invite' defaultMessage='Invite people' /></a> · </li>}
|
||||||
{withHotkeys && <li><Link to='/keyboard-shortcuts'><FormattedMessage id='navigation_bar.keyboard_shortcuts' defaultMessage='Hotkeys' /></Link> · </li>}
|
{withHotkeys && <li><Link to='/keyboard-shortcuts'><FormattedMessage id='navigation_bar.keyboard_shortcuts' defaultMessage='Hotkeys' /></Link> · </li>}
|
||||||
<li><a href='/auth/edit'><FormattedMessage id='getting_started.security' defaultMessage='Security' /></a> · </li>
|
<li><a href='/auth/edit'><FormattedMessage id='getting_started.security' defaultMessage='Security' /></a> · </li>
|
||||||
{!limitedFederationMode && <li><a href='/about/more' target='_blank'><FormattedMessage id='navigation_bar.info' defaultMessage='About this server' /></a> · </li>}
|
{!limitedFederationMode && <li><a href='/about/more' target='_blank'><FormattedMessage id='navigation_bar.info' defaultMessage='About this server' /></a> · </li>}
|
||||||
|
|
|
@ -12,14 +12,12 @@ export const boostModal = getMeta('boost_modal');
|
||||||
export const deleteModal = getMeta('delete_modal');
|
export const deleteModal = getMeta('delete_modal');
|
||||||
export const me = getMeta('me');
|
export const me = getMeta('me');
|
||||||
export const searchEnabled = getMeta('search_enabled');
|
export const searchEnabled = getMeta('search_enabled');
|
||||||
export const invitesEnabled = getMeta('invites_enabled');
|
|
||||||
export const limitedFederationMode = getMeta('limited_federation_mode');
|
export const limitedFederationMode = getMeta('limited_federation_mode');
|
||||||
export const repository = getMeta('repository');
|
export const repository = getMeta('repository');
|
||||||
export const source_url = getMeta('source_url');
|
export const source_url = getMeta('source_url');
|
||||||
export const version = getMeta('version');
|
export const version = getMeta('version');
|
||||||
export const mascot = getMeta('mascot');
|
export const mascot = getMeta('mascot');
|
||||||
export const profile_directory = getMeta('profile_directory');
|
export const profile_directory = getMeta('profile_directory');
|
||||||
export const isStaff = getMeta('is_staff');
|
|
||||||
export const forceSingleColumn = !getMeta('advanced_layout');
|
export const forceSingleColumn = !getMeta('advanced_layout');
|
||||||
export const useBlurhash = getMeta('use_blurhash');
|
export const useBlurhash = getMeta('use_blurhash');
|
||||||
export const usePendingItems = getMeta('use_pending_items');
|
export const usePendingItems = getMeta('use_pending_items');
|
||||||
|
|
3
app/javascript/mastodon/permissions.js
Normal file
3
app/javascript/mastodon/permissions.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export const PERMISSION_INVITE_USERS = 0x0000000000010000;
|
||||||
|
export const PERMISSION_MANAGE_USERS = 0x0000000000000400;
|
||||||
|
export const PERMISSION_MANAGE_REPORTS = 0x0000000000000010;
|
|
@ -7,12 +7,13 @@ const initialState = ImmutableMap({
|
||||||
streaming_api_base_url: null,
|
streaming_api_base_url: null,
|
||||||
access_token: null,
|
access_token: null,
|
||||||
layout: layoutFromWindow(),
|
layout: layoutFromWindow(),
|
||||||
|
permissions: '0',
|
||||||
});
|
});
|
||||||
|
|
||||||
export default function meta(state = initialState, action) {
|
export default function meta(state = initialState, action) {
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
case STORE_HYDRATE:
|
case STORE_HYDRATE:
|
||||||
return state.merge(action.state.get('meta'));
|
return state.merge(action.state.get('meta')).set('permissions', action.state.getIn(['role', 'permissions']));
|
||||||
case APP_LAYOUT_CHANGE:
|
case APP_LAYOUT_CHANGE:
|
||||||
return state.set('layout', action.layout);
|
return state.set('layout', action.layout);
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -924,6 +924,10 @@ a.name-tag,
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.user-role {
|
||||||
|
color: var(--user-role-accent);
|
||||||
|
}
|
||||||
|
|
||||||
.announcements-list,
|
.announcements-list,
|
||||||
.filters-list {
|
.filters-list {
|
||||||
border: 1px solid lighten($ui-base-color, 4%);
|
border: 1px solid lighten($ui-base-color, 4%);
|
||||||
|
@ -960,6 +964,17 @@ a.name-tag,
|
||||||
&__meta {
|
&__meta {
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
color: $dark-text-color;
|
color: $dark-text-color;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: underline;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus,
|
||||||
|
&:active {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__action-bar {
|
&__action-bar {
|
||||||
|
|
|
@ -256,6 +256,10 @@ code {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.input.with_block_label.user_role_permissions_as_keys ul {
|
||||||
|
columns: unset;
|
||||||
|
}
|
||||||
|
|
||||||
.input.datetime .label_input select {
|
.input.datetime .label_input select {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
|
|
@ -8,11 +8,11 @@ class Admin::SystemCheck
|
||||||
Admin::SystemCheck::ElasticsearchCheck,
|
Admin::SystemCheck::ElasticsearchCheck,
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
def self.perform
|
def self.perform(current_user)
|
||||||
ACTIVE_CHECKS.each_with_object([]) do |klass, arr|
|
ACTIVE_CHECKS.each_with_object([]) do |klass, arr|
|
||||||
check = klass.new
|
check = klass.new(current_user)
|
||||||
|
|
||||||
if check.pass?
|
if check.skip? || check.pass?
|
||||||
arr
|
arr
|
||||||
else
|
else
|
||||||
arr << check.message
|
arr << check.message
|
||||||
|
|
|
@ -1,6 +1,16 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Admin::SystemCheck::BaseCheck
|
class Admin::SystemCheck::BaseCheck
|
||||||
|
attr_reader :current_user
|
||||||
|
|
||||||
|
def initialize(current_user)
|
||||||
|
@current_user = current_user
|
||||||
|
end
|
||||||
|
|
||||||
|
def skip?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
def pass?
|
def pass?
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Admin::SystemCheck::DatabaseSchemaCheck < Admin::SystemCheck::BaseCheck
|
class Admin::SystemCheck::DatabaseSchemaCheck < Admin::SystemCheck::BaseCheck
|
||||||
|
def skip?
|
||||||
|
!current_user.can?(:view_devops)
|
||||||
|
end
|
||||||
|
|
||||||
def pass?
|
def pass?
|
||||||
!ActiveRecord::Base.connection.migration_context.needs_migration?
|
!ActiveRecord::Base.connection.migration_context.needs_migration?
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck
|
class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck
|
||||||
|
def skip?
|
||||||
|
!current_user.can?(:view_devops)
|
||||||
|
end
|
||||||
|
|
||||||
def pass?
|
def pass?
|
||||||
return true unless Chewy.enabled?
|
return true unless Chewy.enabled?
|
||||||
|
|
||||||
|
@ -32,8 +36,4 @@ class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck
|
||||||
def compatible_version?
|
def compatible_version?
|
||||||
Gem::Version.new(running_version) >= Gem::Version.new(required_version)
|
Gem::Version.new(running_version) >= Gem::Version.new(required_version)
|
||||||
end
|
end
|
||||||
|
|
||||||
def missing_queues
|
|
||||||
@missing_queues ||= Sidekiq::ProcessSet.new.reduce(SIDEKIQ_QUEUES) { |queues, process| queues - process['queues'] }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
class Admin::SystemCheck::RulesCheck < Admin::SystemCheck::BaseCheck
|
class Admin::SystemCheck::RulesCheck < Admin::SystemCheck::BaseCheck
|
||||||
include RoutingHelper
|
include RoutingHelper
|
||||||
|
|
||||||
|
def skip?
|
||||||
|
!current_user.can?(:manage_rules)
|
||||||
|
end
|
||||||
|
|
||||||
def pass?
|
def pass?
|
||||||
Rule.kept.exists?
|
Rule.kept.exists?
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,6 +9,10 @@ class Admin::SystemCheck::SidekiqProcessCheck < Admin::SystemCheck::BaseCheck
|
||||||
scheduler
|
scheduler
|
||||||
).freeze
|
).freeze
|
||||||
|
|
||||||
|
def skip?
|
||||||
|
!current_user.can?(:view_devops)
|
||||||
|
end
|
||||||
|
|
||||||
def pass?
|
def pass?
|
||||||
missing_queues.empty?
|
missing_queues.empty?
|
||||||
end
|
end
|
||||||
|
|
|
@ -116,7 +116,7 @@ class Account < ApplicationRecord
|
||||||
scope :by_recent_status, -> { order(Arel.sql('(case when account_stats.last_status_at is null then 1 else 0 end) asc, account_stats.last_status_at desc, accounts.id desc')) }
|
scope :by_recent_status, -> { order(Arel.sql('(case when account_stats.last_status_at is null then 1 else 0 end) asc, account_stats.last_status_at desc, accounts.id desc')) }
|
||||||
scope :by_recent_sign_in, -> { order(Arel.sql('(case when users.current_sign_in_at is null then 1 else 0 end) asc, users.current_sign_in_at desc, accounts.id desc')) }
|
scope :by_recent_sign_in, -> { order(Arel.sql('(case when users.current_sign_in_at is null then 1 else 0 end) asc, users.current_sign_in_at desc, accounts.id desc')) }
|
||||||
scope :popular, -> { order('account_stats.followers_count desc') }
|
scope :popular, -> { order('account_stats.followers_count desc') }
|
||||||
scope :by_domain_and_subdomains, ->(domain) { where(domain: domain).or(where(arel_table[:domain].matches('%.' + domain))) }
|
scope :by_domain_and_subdomains, ->(domain) { where(domain: domain).or(where(arel_table[:domain].matches("%.#{domain}"))) }
|
||||||
scope :not_excluded_by_account, ->(account) { where.not(id: account.excluded_from_timeline_account_ids) }
|
scope :not_excluded_by_account, ->(account) { where.not(id: account.excluded_from_timeline_account_ids) }
|
||||||
scope :not_domain_blocked_by_account, ->(account) { where(arel_table[:domain].eq(nil).or(arel_table[:domain].not_in(account.excluded_from_timeline_domains))) }
|
scope :not_domain_blocked_by_account, ->(account) { where(arel_table[:domain].eq(nil).or(arel_table[:domain].not_in(account.excluded_from_timeline_domains))) }
|
||||||
|
|
||||||
|
@ -132,9 +132,6 @@ class Account < ApplicationRecord
|
||||||
:unconfirmed?,
|
:unconfirmed?,
|
||||||
:unconfirmed_or_pending?,
|
:unconfirmed_or_pending?,
|
||||||
:role,
|
:role,
|
||||||
:admin?,
|
|
||||||
:moderator?,
|
|
||||||
:staff?,
|
|
||||||
:locale,
|
:locale,
|
||||||
:shows_application?,
|
:shows_application?,
|
||||||
to: :user,
|
to: :user,
|
||||||
|
@ -454,7 +451,7 @@ class Account < ApplicationRecord
|
||||||
DeliveryFailureTracker.without_unavailable(urls)
|
DeliveryFailureTracker.without_unavailable(urls)
|
||||||
end
|
end
|
||||||
|
|
||||||
def search_for(terms, limit = 10, offset = 0)
|
def search_for(terms, limit: 10, offset: 0)
|
||||||
tsquery = generate_query_for_search(terms)
|
tsquery = generate_query_for_search(terms)
|
||||||
|
|
||||||
sql = <<-SQL.squish
|
sql = <<-SQL.squish
|
||||||
|
@ -476,7 +473,7 @@ class Account < ApplicationRecord
|
||||||
records
|
records
|
||||||
end
|
end
|
||||||
|
|
||||||
def advanced_search_for(terms, account, limit = 10, following = false, offset = 0)
|
def advanced_search_for(terms, account, limit: 10, following: false, offset: 0)
|
||||||
tsquery = generate_query_for_search(terms)
|
tsquery = generate_query_for_search(terms)
|
||||||
sql = advanced_search_for_sql_template(following)
|
sql = advanced_search_for_sql_template(following)
|
||||||
records = find_by_sql([sql, id: account.id, limit: limit, offset: offset, tsquery: tsquery])
|
records = find_by_sql([sql, id: account.id, limit: limit, offset: offset, tsquery: tsquery])
|
||||||
|
|
|
@ -4,7 +4,7 @@ class AccountFilter
|
||||||
KEYS = %i(
|
KEYS = %i(
|
||||||
origin
|
origin
|
||||||
status
|
status
|
||||||
permissions
|
role_ids
|
||||||
username
|
username
|
||||||
by_domain
|
by_domain
|
||||||
display_name
|
display_name
|
||||||
|
@ -26,7 +26,7 @@ class AccountFilter
|
||||||
params.each do |key, value|
|
params.each do |key, value|
|
||||||
next if key.to_s == 'page'
|
next if key.to_s == 'page'
|
||||||
|
|
||||||
scope.merge!(scope_for(key, value.to_s.strip)) if value.present?
|
scope.merge!(scope_for(key, value)) if value.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
scope
|
scope
|
||||||
|
@ -38,18 +38,18 @@ class AccountFilter
|
||||||
case key.to_s
|
case key.to_s
|
||||||
when 'origin'
|
when 'origin'
|
||||||
origin_scope(value)
|
origin_scope(value)
|
||||||
when 'permissions'
|
when 'role_ids'
|
||||||
permissions_scope(value)
|
role_scope(value)
|
||||||
when 'status'
|
when 'status'
|
||||||
status_scope(value)
|
status_scope(value)
|
||||||
when 'by_domain'
|
when 'by_domain'
|
||||||
Account.where(domain: value)
|
Account.where(domain: value.to_s)
|
||||||
when 'username'
|
when 'username'
|
||||||
Account.matches_username(value)
|
Account.matches_username(value.to_s)
|
||||||
when 'display_name'
|
when 'display_name'
|
||||||
Account.matches_display_name(value)
|
Account.matches_display_name(value.to_s)
|
||||||
when 'email'
|
when 'email'
|
||||||
accounts_with_users.merge(User.matches_email(value))
|
accounts_with_users.merge(User.matches_email(value.to_s))
|
||||||
when 'ip'
|
when 'ip'
|
||||||
valid_ip?(value) ? accounts_with_users.merge(User.matches_ip(value).group('users.id, accounts.id')) : Account.none
|
valid_ip?(value) ? accounts_with_users.merge(User.matches_ip(value).group('users.id, accounts.id')) : Account.none
|
||||||
when 'invited_by'
|
when 'invited_by'
|
||||||
|
@ -104,13 +104,8 @@ class AccountFilter
|
||||||
Account.left_joins(user: :invite).merge(Invite.where(user_id: value.to_s))
|
Account.left_joins(user: :invite).merge(Invite.where(user_id: value.to_s))
|
||||||
end
|
end
|
||||||
|
|
||||||
def permissions_scope(value)
|
def role_scope(value)
|
||||||
case value.to_s
|
accounts_with_users.merge(User.where(role_id: Array(value).map(&:to_s)))
|
||||||
when 'staff'
|
|
||||||
accounts_with_users.merge(User.staff)
|
|
||||||
else
|
|
||||||
raise "Unknown permissions: #{value}"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def accounts_with_users
|
def accounts_with_users
|
||||||
|
@ -118,7 +113,7 @@ class AccountFilter
|
||||||
end
|
end
|
||||||
|
|
||||||
def valid_ip?(value)
|
def valid_ip?(value)
|
||||||
IPAddr.new(value) && true
|
IPAddr.new(value.to_s) && true
|
||||||
rescue IPAddr::InvalidAddressError
|
rescue IPAddr::InvalidAddressError
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module UserRoles
|
|
||||||
extend ActiveSupport::Concern
|
|
||||||
|
|
||||||
included do
|
|
||||||
scope :admins, -> { where(admin: true) }
|
|
||||||
scope :moderators, -> { where(moderator: true) }
|
|
||||||
scope :staff, -> { admins.or(moderators) }
|
|
||||||
end
|
|
||||||
|
|
||||||
def staff?
|
|
||||||
admin? || moderator?
|
|
||||||
end
|
|
||||||
|
|
||||||
def role=(value)
|
|
||||||
case value
|
|
||||||
when 'admin'
|
|
||||||
self.admin = true
|
|
||||||
self.moderator = false
|
|
||||||
when 'moderator'
|
|
||||||
self.admin = false
|
|
||||||
self.moderator = true
|
|
||||||
else
|
|
||||||
self.admin = false
|
|
||||||
self.moderator = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def role
|
|
||||||
if admin?
|
|
||||||
'admin'
|
|
||||||
elsif moderator?
|
|
||||||
'moderator'
|
|
||||||
else
|
|
||||||
'user'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def role?(role)
|
|
||||||
case role
|
|
||||||
when 'user'
|
|
||||||
true
|
|
||||||
when 'moderator'
|
|
||||||
staff?
|
|
||||||
when 'admin'
|
|
||||||
admin?
|
|
||||||
else
|
|
||||||
false
|
|
||||||
end
|
|
||||||
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
|
|
||||||
end
|
|
|
@ -15,10 +15,8 @@ class Form::AdminSettings
|
||||||
closed_registrations_message
|
closed_registrations_message
|
||||||
open_deletion
|
open_deletion
|
||||||
timeline_preview
|
timeline_preview
|
||||||
show_staff_badge
|
|
||||||
bootstrap_timeline_accounts
|
bootstrap_timeline_accounts
|
||||||
theme
|
theme
|
||||||
min_invite_role
|
|
||||||
activity_api_enabled
|
activity_api_enabled
|
||||||
peers_api_enabled
|
peers_api_enabled
|
||||||
show_known_fediverse_at_about_page
|
show_known_fediverse_at_about_page
|
||||||
|
@ -39,7 +37,6 @@ class Form::AdminSettings
|
||||||
BOOLEAN_KEYS = %i(
|
BOOLEAN_KEYS = %i(
|
||||||
open_deletion
|
open_deletion
|
||||||
timeline_preview
|
timeline_preview
|
||||||
show_staff_badge
|
|
||||||
activity_api_enabled
|
activity_api_enabled
|
||||||
peers_api_enabled
|
peers_api_enabled
|
||||||
show_known_fediverse_at_about_page
|
show_known_fediverse_at_about_page
|
||||||
|
@ -62,7 +59,6 @@ class Form::AdminSettings
|
||||||
validates :site_short_description, :site_description, html: { wrap_with: :p }
|
validates :site_short_description, :site_description, html: { wrap_with: :p }
|
||||||
validates :site_extended_description, :site_terms, :closed_registrations_message, html: true
|
validates :site_extended_description, :site_terms, :closed_registrations_message, html: true
|
||||||
validates :registrations_mode, inclusion: { in: %w(open approved none) }
|
validates :registrations_mode, inclusion: { in: %w(open approved none) }
|
||||||
validates :min_invite_role, inclusion: { in: %w(disabled user moderator admin) }
|
|
||||||
validates :site_contact_email, :site_contact_username, presence: true
|
validates :site_contact_email, :site_contact_username, presence: true
|
||||||
validates :site_contact_username, existing_username: true
|
validates :site_contact_username, existing_username: true
|
||||||
validates :bootstrap_timeline_accounts, existing_username: { multiple: true }
|
validates :bootstrap_timeline_accounts, existing_username: { multiple: true }
|
||||||
|
|
|
@ -34,7 +34,7 @@ module Trends
|
||||||
|
|
||||||
return if links_requiring_review.empty? && tags_requiring_review.empty? && statuses_requiring_review.empty?
|
return if links_requiring_review.empty? && tags_requiring_review.empty? && statuses_requiring_review.empty?
|
||||||
|
|
||||||
User.staff.includes(:account).find_each do |user|
|
User.those_who_can(:manage_taxonomies).includes(:account).find_each do |user|
|
||||||
AdminMailer.new_trends(user.account, links_requiring_review, tags_requiring_review, statuses_requiring_review).deliver_later! if user.allows_trends_review_emails?
|
AdminMailer.new_trends(user.account, links_requiring_review, tags_requiring_review, statuses_requiring_review).deliver_later! if user.allows_trends_review_emails?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
# sign_in_token_sent_at :datetime
|
# sign_in_token_sent_at :datetime
|
||||||
# webauthn_id :string
|
# webauthn_id :string
|
||||||
# sign_up_ip :inet
|
# sign_up_ip :inet
|
||||||
|
# role_id :bigint(8)
|
||||||
#
|
#
|
||||||
|
|
||||||
class User < ApplicationRecord
|
class User < ApplicationRecord
|
||||||
|
@ -50,7 +51,6 @@ class User < ApplicationRecord
|
||||||
)
|
)
|
||||||
|
|
||||||
include Settings::Extend
|
include Settings::Extend
|
||||||
include UserRoles
|
|
||||||
include Redisable
|
include Redisable
|
||||||
include LanguagesHelper
|
include LanguagesHelper
|
||||||
|
|
||||||
|
@ -79,6 +79,7 @@ class User < ApplicationRecord
|
||||||
belongs_to :account, inverse_of: :user
|
belongs_to :account, inverse_of: :user
|
||||||
belongs_to :invite, counter_cache: :uses, optional: true
|
belongs_to :invite, counter_cache: :uses, optional: true
|
||||||
belongs_to :created_by_application, class_name: 'Doorkeeper::Application', optional: true
|
belongs_to :created_by_application, class_name: 'Doorkeeper::Application', optional: true
|
||||||
|
belongs_to :role, class_name: 'UserRole', optional: true
|
||||||
accepts_nested_attributes_for :account
|
accepts_nested_attributes_for :account
|
||||||
|
|
||||||
has_many :applications, class_name: 'Doorkeeper::Application', as: :owner
|
has_many :applications, class_name: 'Doorkeeper::Application', as: :owner
|
||||||
|
@ -103,6 +104,7 @@ class User < ApplicationRecord
|
||||||
validates_with RegistrationFormTimeValidator, on: :create
|
validates_with RegistrationFormTimeValidator, on: :create
|
||||||
validates :website, absence: true, on: :create
|
validates :website, absence: true, on: :create
|
||||||
validates :confirm_password, absence: true, on: :create
|
validates :confirm_password, absence: true, on: :create
|
||||||
|
validate :validate_role_elevation
|
||||||
|
|
||||||
scope :recent, -> { order(id: :desc) }
|
scope :recent, -> { order(id: :desc) }
|
||||||
scope :pending, -> { where(approved: false) }
|
scope :pending, -> { where(approved: false) }
|
||||||
|
@ -117,6 +119,7 @@ class User < ApplicationRecord
|
||||||
scope :emailable, -> { confirmed.enabled.joins(:account).merge(Account.searchable) }
|
scope :emailable, -> { confirmed.enabled.joins(:account).merge(Account.searchable) }
|
||||||
|
|
||||||
before_validation :sanitize_languages
|
before_validation :sanitize_languages
|
||||||
|
before_validation :sanitize_role
|
||||||
before_create :set_approved
|
before_create :set_approved
|
||||||
after_commit :send_pending_devise_notifications
|
after_commit :send_pending_devise_notifications
|
||||||
after_create_commit :trigger_webhooks
|
after_create_commit :trigger_webhooks
|
||||||
|
@ -135,8 +138,28 @@ class User < ApplicationRecord
|
||||||
:disable_swiping, :always_send_emails,
|
:disable_swiping, :always_send_emails,
|
||||||
to: :settings, prefix: :setting, allow_nil: false
|
to: :settings, prefix: :setting, allow_nil: false
|
||||||
|
|
||||||
|
delegate :can?, to: :role
|
||||||
|
|
||||||
attr_reader :invite_code
|
attr_reader :invite_code
|
||||||
attr_writer :external, :bypass_invite_request_check
|
attr_writer :external, :bypass_invite_request_check, :current_account
|
||||||
|
|
||||||
|
def self.those_who_can(*any_of_privileges)
|
||||||
|
matching_role_ids = UserRole.that_can(*any_of_privileges).map(&:id)
|
||||||
|
|
||||||
|
if matching_role_ids.empty?
|
||||||
|
none
|
||||||
|
else
|
||||||
|
where(role_id: matching_role_ids)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def role
|
||||||
|
if role_id.nil?
|
||||||
|
UserRole.everyone
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def confirmed?
|
def confirmed?
|
||||||
confirmed_at.present?
|
confirmed_at.present?
|
||||||
|
@ -441,6 +464,11 @@ class User < ApplicationRecord
|
||||||
self.chosen_languages = nil if chosen_languages.empty?
|
self.chosen_languages = nil if chosen_languages.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def sanitize_role
|
||||||
|
return if role.nil?
|
||||||
|
self.role = nil if role.everyone?
|
||||||
|
end
|
||||||
|
|
||||||
def prepare_new_user!
|
def prepare_new_user!
|
||||||
BootstrapTimelineWorker.perform_async(account_id)
|
BootstrapTimelineWorker.perform_async(account_id)
|
||||||
ActivityTracker.increment('activity:accounts:local')
|
ActivityTracker.increment('activity:accounts:local')
|
||||||
|
@ -453,7 +481,7 @@ class User < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def notify_staff_about_pending_account!
|
def notify_staff_about_pending_account!
|
||||||
User.staff.includes(:account).find_each do |u|
|
User.those_who_can(:manage_users).includes(:account).find_each do |u|
|
||||||
next unless u.allows_pending_account_emails?
|
next unless u.allows_pending_account_emails?
|
||||||
AdminMailer.new_pending_account(u.account, self).deliver_later
|
AdminMailer.new_pending_account(u.account, self).deliver_later
|
||||||
end
|
end
|
||||||
|
@ -471,6 +499,10 @@ class User < ApplicationRecord
|
||||||
email_changed? && !external? && !(Rails.env.test? || Rails.env.development?)
|
email_changed? && !external? && !(Rails.env.test? || Rails.env.development?)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def validate_role_elevation
|
||||||
|
errors.add(:role_id, :elevated) if defined?(@current_account) && role&.overrides?(@current_account&.user_role)
|
||||||
|
end
|
||||||
|
|
||||||
def invite_text_required?
|
def invite_text_required?
|
||||||
Setting.require_invite_text && !invited? && !external? && !bypass_invite_request_check?
|
Setting.require_invite_text && !invited? && !external? && !bypass_invite_request_check?
|
||||||
end
|
end
|
||||||
|
|
179
app/models/user_role.rb
Normal file
179
app/models/user_role.rb
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# == Schema Information
|
||||||
|
#
|
||||||
|
# Table name: user_roles
|
||||||
|
#
|
||||||
|
# id :bigint(8) not null, primary key
|
||||||
|
# name :string default(""), not null
|
||||||
|
# color :string default(""), not null
|
||||||
|
# position :integer default(0), not null
|
||||||
|
# permissions :bigint(8) default(0), not null
|
||||||
|
# highlighted :boolean default(FALSE), not null
|
||||||
|
# created_at :datetime not null
|
||||||
|
# updated_at :datetime not null
|
||||||
|
#
|
||||||
|
|
||||||
|
class UserRole < ApplicationRecord
|
||||||
|
FLAGS = {
|
||||||
|
administrator: (1 << 0),
|
||||||
|
view_devops: (1 << 1),
|
||||||
|
view_audit_log: (1 << 2),
|
||||||
|
view_dashboard: (1 << 3),
|
||||||
|
manage_reports: (1 << 4),
|
||||||
|
manage_federation: (1 << 5),
|
||||||
|
manage_settings: (1 << 6),
|
||||||
|
manage_blocks: (1 << 7),
|
||||||
|
manage_taxonomies: (1 << 8),
|
||||||
|
manage_appeals: (1 << 9),
|
||||||
|
manage_users: (1 << 10),
|
||||||
|
manage_invites: (1 << 11),
|
||||||
|
manage_rules: (1 << 12),
|
||||||
|
manage_announcements: (1 << 13),
|
||||||
|
manage_custom_emojis: (1 << 14),
|
||||||
|
manage_webhooks: (1 << 15),
|
||||||
|
invite_users: (1 << 16),
|
||||||
|
manage_roles: (1 << 17),
|
||||||
|
manage_user_access: (1 << 18),
|
||||||
|
delete_user_data: (1 << 19),
|
||||||
|
}.freeze
|
||||||
|
|
||||||
|
module Flags
|
||||||
|
NONE = 0
|
||||||
|
ALL = FLAGS.values.reduce(&:|)
|
||||||
|
|
||||||
|
DEFAULT = FLAGS[:invite_users]
|
||||||
|
|
||||||
|
CATEGORIES = {
|
||||||
|
invites: %i(
|
||||||
|
invite_users
|
||||||
|
).freeze,
|
||||||
|
|
||||||
|
moderation: %w(
|
||||||
|
view_dashboard
|
||||||
|
view_audit_log
|
||||||
|
manage_users
|
||||||
|
manage_user_access
|
||||||
|
delete_user_data
|
||||||
|
manage_reports
|
||||||
|
manage_appeals
|
||||||
|
manage_federation
|
||||||
|
manage_blocks
|
||||||
|
manage_taxonomies
|
||||||
|
manage_invites
|
||||||
|
).freeze,
|
||||||
|
|
||||||
|
administration: %w(
|
||||||
|
manage_settings
|
||||||
|
manage_rules
|
||||||
|
manage_roles
|
||||||
|
manage_webhooks
|
||||||
|
manage_custom_emojis
|
||||||
|
manage_announcements
|
||||||
|
).freeze,
|
||||||
|
|
||||||
|
devops: %w(
|
||||||
|
view_devops
|
||||||
|
).freeze,
|
||||||
|
|
||||||
|
special: %i(
|
||||||
|
administrator
|
||||||
|
).freeze,
|
||||||
|
}.freeze
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_writer :current_account
|
||||||
|
|
||||||
|
validates :name, presence: true, unless: :everyone?
|
||||||
|
validates :color, format: { with: /\A#?(?:[A-F0-9]{3}){1,2}\z/i }, unless: -> { color.blank? }
|
||||||
|
|
||||||
|
validate :validate_permissions_elevation
|
||||||
|
validate :validate_position_elevation
|
||||||
|
validate :validate_dangerous_permissions
|
||||||
|
|
||||||
|
before_validation :set_position
|
||||||
|
|
||||||
|
scope :assignable, -> { where.not(id: -99).order(position: :asc) }
|
||||||
|
|
||||||
|
has_many :users, inverse_of: :role, foreign_key: 'role_id', dependent: :nullify
|
||||||
|
|
||||||
|
def self.nobody
|
||||||
|
@nobody ||= UserRole.new(permissions: Flags::NONE, position: -1)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.everyone
|
||||||
|
UserRole.find(-99)
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
UserRole.create!(id: -99, permissions: Flags::DEFAULT)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.that_can(*any_of_privileges)
|
||||||
|
all.select { |role| role.can?(*any_of_privileges) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def everyone?
|
||||||
|
id == -99
|
||||||
|
end
|
||||||
|
|
||||||
|
def nobody?
|
||||||
|
id.nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
def permissions_as_keys
|
||||||
|
FLAGS.keys.select { |privilege| permissions & FLAGS[privilege] == FLAGS[privilege] }.map(&:to_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
def permissions_as_keys=(value)
|
||||||
|
self.permissions = value.map(&:presence).compact.reduce(Flags::NONE) { |bitmask, privilege| FLAGS.key?(privilege.to_sym) ? (bitmask | FLAGS[privilege.to_sym]) : bitmask }
|
||||||
|
end
|
||||||
|
|
||||||
|
def can?(*any_of_privileges)
|
||||||
|
any_of_privileges.any? { |privilege| in_permissions?(privilege) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def overrides?(other_role)
|
||||||
|
other_role.nil? || position > other_role.position
|
||||||
|
end
|
||||||
|
|
||||||
|
def computed_permissions
|
||||||
|
# If called on the everyone role, no further computation needed
|
||||||
|
return permissions if everyone?
|
||||||
|
|
||||||
|
# If called on the nobody role, no permissions are there to be given
|
||||||
|
return Flags::NONE if nobody?
|
||||||
|
|
||||||
|
# Otherwise, compute permissions based on special conditions
|
||||||
|
@computed_permissions ||= begin
|
||||||
|
permissions = self.class.everyone.permissions | self.permissions
|
||||||
|
|
||||||
|
if permissions & FLAGS[:administrator] == FLAGS[:administrator]
|
||||||
|
Flags::ALL
|
||||||
|
else
|
||||||
|
permissions
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def in_permissions?(privilege)
|
||||||
|
raise ArgumentError, "Unknown privilege: #{privilege}" unless FLAGS.key?(privilege)
|
||||||
|
computed_permissions & FLAGS[privilege] == FLAGS[privilege]
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_position
|
||||||
|
self.position = -1 if everyone?
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_permissions_elevation
|
||||||
|
errors.add(:permissions_as_keys, :elevated) if defined?(@current_account) && @current_account.user_role.computed_permissions & permissions != permissions
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_position_elevation
|
||||||
|
errors.add(:position, :elevated) if defined?(@current_account) && @current_account.user_role.position < position
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_dangerous_permissions
|
||||||
|
errors.add(:permissions_as_keys, :dangerous) if everyone? && Flags::DEFAULT & permissions != permissions
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
class AccountModerationNotePolicy < ApplicationPolicy
|
class AccountModerationNotePolicy < ApplicationPolicy
|
||||||
def create?
|
def create?
|
||||||
staff?
|
role.can?(:manage_reports)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
admin? || owner?
|
owner? || (role.can?(:manage_reports) && role.overrides?(record.account.user_role))
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -2,74 +2,66 @@
|
||||||
|
|
||||||
class AccountPolicy < ApplicationPolicy
|
class AccountPolicy < ApplicationPolicy
|
||||||
def index?
|
def index?
|
||||||
staff?
|
role.can?(:manage_users)
|
||||||
end
|
end
|
||||||
|
|
||||||
def show?
|
def show?
|
||||||
staff?
|
role.can?(:manage_users)
|
||||||
end
|
end
|
||||||
|
|
||||||
def warn?
|
def warn?
|
||||||
staff? && !record.user&.staff?
|
role.can?(:manage_users, :manage_reports) && role.overrides?(record.user_role)
|
||||||
end
|
end
|
||||||
|
|
||||||
def suspend?
|
def suspend?
|
||||||
staff? && !record.user&.staff? && !record.instance_actor?
|
role.can?(:manage_users, :manage_reports) && role.overrides?(record.user_role) && !record.instance_actor?
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
record.suspended_temporarily? && admin?
|
record.suspended_temporarily? && role.can?(:delete_user_data)
|
||||||
end
|
end
|
||||||
|
|
||||||
def unsuspend?
|
def unsuspend?
|
||||||
staff? && record.suspension_origin_local?
|
role.can?(:manage_users) && record.suspension_origin_local?
|
||||||
end
|
end
|
||||||
|
|
||||||
def sensitive?
|
def sensitive?
|
||||||
staff? && !record.user&.staff?
|
role.can?(:manage_users, :manage_reports) && role.overrides?(record.user_role)
|
||||||
end
|
end
|
||||||
|
|
||||||
def unsensitive?
|
def unsensitive?
|
||||||
staff?
|
role.can?(:manage_users)
|
||||||
end
|
end
|
||||||
|
|
||||||
def silence?
|
def silence?
|
||||||
staff? && !record.user&.staff?
|
role.can?(:manage_users, :manage_reports) && role.overrides?(record.user_role)
|
||||||
end
|
end
|
||||||
|
|
||||||
def unsilence?
|
def unsilence?
|
||||||
staff?
|
role.can?(:manage_users)
|
||||||
end
|
end
|
||||||
|
|
||||||
def redownload?
|
def redownload?
|
||||||
admin?
|
role.can?(:manage_federation)
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_avatar?
|
def remove_avatar?
|
||||||
staff?
|
role.can?(:manage_users, :manage_reports) && role.overrides?(record.user_role)
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_header?
|
def remove_header?
|
||||||
staff?
|
role.can?(:manage_users, :manage_reports) && role.overrides?(record.user_role)
|
||||||
end
|
|
||||||
|
|
||||||
def subscribe?
|
|
||||||
admin?
|
|
||||||
end
|
|
||||||
|
|
||||||
def unsubscribe?
|
|
||||||
admin?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def memorialize?
|
def memorialize?
|
||||||
admin? && !record.user&.admin? && !record.instance_actor?
|
role.can?(:delete_user_data) && role.overrides?(record.user_role) && !record.instance_actor?
|
||||||
end
|
end
|
||||||
|
|
||||||
def unblock_email?
|
def unblock_email?
|
||||||
staff?
|
role.can?(:manage_users)
|
||||||
end
|
end
|
||||||
|
|
||||||
def review?
|
def review?
|
||||||
staff?
|
role.can?(:manage_taxonomies)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
class AccountWarningPolicy < ApplicationPolicy
|
class AccountWarningPolicy < ApplicationPolicy
|
||||||
def show?
|
def show?
|
||||||
target? || staff?
|
target? || role.can?(:manage_appeals)
|
||||||
end
|
end
|
||||||
|
|
||||||
def appeal?
|
def appeal?
|
||||||
|
|
|
@ -2,18 +2,18 @@
|
||||||
|
|
||||||
class AccountWarningPresetPolicy < ApplicationPolicy
|
class AccountWarningPresetPolicy < ApplicationPolicy
|
||||||
def index?
|
def index?
|
||||||
staff?
|
role.can?(:manage_settings)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create?
|
def create?
|
||||||
staff?
|
role.can?(:manage_settings)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update?
|
def update?
|
||||||
staff?
|
role.can?(:manage_settings)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
staff?
|
role.can?(:manage_settings)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,18 +2,18 @@
|
||||||
|
|
||||||
class AnnouncementPolicy < ApplicationPolicy
|
class AnnouncementPolicy < ApplicationPolicy
|
||||||
def index?
|
def index?
|
||||||
staff?
|
role.can?(:manage_announcements)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create?
|
def create?
|
||||||
admin?
|
role.can?(:manage_announcements)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update?
|
def update?
|
||||||
admin?
|
role.can?(:manage_announcements)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
admin?
|
role.can?(:manage_announcements)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,12 +2,14 @@
|
||||||
|
|
||||||
class AppealPolicy < ApplicationPolicy
|
class AppealPolicy < ApplicationPolicy
|
||||||
def index?
|
def index?
|
||||||
staff?
|
role.can?(:manage_appeals)
|
||||||
end
|
end
|
||||||
|
|
||||||
def approve?
|
def approve?
|
||||||
record.pending? && staff?
|
record.pending? && role.can?(:manage_appeals)
|
||||||
end
|
end
|
||||||
|
|
||||||
alias reject? approve?
|
def reject?
|
||||||
|
record.pending? && role.can?(:manage_appeals)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,8 +8,6 @@ class ApplicationPolicy
|
||||||
@record = record
|
@record = record
|
||||||
end
|
end
|
||||||
|
|
||||||
delegate :admin?, :moderator?, :staff?, to: :current_user, allow_nil: true
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def current_user
|
def current_user
|
||||||
|
@ -19,4 +17,8 @@ class ApplicationPolicy
|
||||||
def user_signed_in?
|
def user_signed_in?
|
||||||
!current_user.nil?
|
!current_user.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def role
|
||||||
|
current_user&.role || UserRole.nobody
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
7
app/policies/audit_log_policy.rb
Normal file
7
app/policies/audit_log_policy.rb
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AuditLogPolicy < ApplicationPolicy
|
||||||
|
def index?
|
||||||
|
role.can?(:view_audit_log)
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,30 +2,30 @@
|
||||||
|
|
||||||
class CustomEmojiPolicy < ApplicationPolicy
|
class CustomEmojiPolicy < ApplicationPolicy
|
||||||
def index?
|
def index?
|
||||||
staff?
|
role.can?(:manage_custom_emojis)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create?
|
def create?
|
||||||
admin?
|
role.can?(:manage_custom_emojis)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update?
|
def update?
|
||||||
admin?
|
role.can?(:manage_custom_emojis)
|
||||||
end
|
end
|
||||||
|
|
||||||
def copy?
|
def copy?
|
||||||
admin?
|
role.can?(:manage_custom_emojis)
|
||||||
end
|
end
|
||||||
|
|
||||||
def enable?
|
def enable?
|
||||||
staff?
|
role.can?(:manage_custom_emojis)
|
||||||
end
|
end
|
||||||
|
|
||||||
def disable?
|
def disable?
|
||||||
staff?
|
role.can?(:manage_custom_emojis)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
admin?
|
role.can?(:manage_custom_emojis)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
7
app/policies/dashboard_policy.rb
Normal file
7
app/policies/dashboard_policy.rb
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class DashboardPolicy < ApplicationPolicy
|
||||||
|
def index?
|
||||||
|
role.can?(:view_dashboard)
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,14 +2,14 @@
|
||||||
|
|
||||||
class DeliveryPolicy < ApplicationPolicy
|
class DeliveryPolicy < ApplicationPolicy
|
||||||
def clear_delivery_errors?
|
def clear_delivery_errors?
|
||||||
admin?
|
role.can?(:manage_federation)
|
||||||
end
|
end
|
||||||
|
|
||||||
def restart_delivery?
|
def restart_delivery?
|
||||||
admin?
|
role.can?(:manage_federation)
|
||||||
end
|
end
|
||||||
|
|
||||||
def stop_delivery?
|
def stop_delivery?
|
||||||
admin?
|
role.can?(:manage_federation)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,18 +2,18 @@
|
||||||
|
|
||||||
class DomainAllowPolicy < ApplicationPolicy
|
class DomainAllowPolicy < ApplicationPolicy
|
||||||
def index?
|
def index?
|
||||||
admin?
|
role.can?(:manage_federation)
|
||||||
end
|
end
|
||||||
|
|
||||||
def show?
|
def show?
|
||||||
admin?
|
role.can?(:manage_federation)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create?
|
def create?
|
||||||
admin?
|
role.can?(:manage_federation)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
admin?
|
role.can?(:manage_federation)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,22 +2,22 @@
|
||||||
|
|
||||||
class DomainBlockPolicy < ApplicationPolicy
|
class DomainBlockPolicy < ApplicationPolicy
|
||||||
def index?
|
def index?
|
||||||
admin?
|
role.can?(:manage_federation)
|
||||||
end
|
end
|
||||||
|
|
||||||
def show?
|
def show?
|
||||||
admin?
|
role.can?(:manage_federation)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create?
|
def create?
|
||||||
admin?
|
role.can?(:manage_federation)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update?
|
def update?
|
||||||
admin?
|
role.can?(:manage_federation)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
admin?
|
role.can?(:manage_federation)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
|
|
||||||
class EmailDomainBlockPolicy < ApplicationPolicy
|
class EmailDomainBlockPolicy < ApplicationPolicy
|
||||||
def index?
|
def index?
|
||||||
admin?
|
role.can?(:manage_blocks)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create?
|
def create?
|
||||||
admin?
|
role.can?(:manage_blocks)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
admin?
|
role.can?(:manage_blocks)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
|
|
||||||
class FollowRecommendationPolicy < ApplicationPolicy
|
class FollowRecommendationPolicy < ApplicationPolicy
|
||||||
def show?
|
def show?
|
||||||
staff?
|
role.can?(:manage_taxonomies)
|
||||||
end
|
end
|
||||||
|
|
||||||
def suppress?
|
def suppress?
|
||||||
staff?
|
role.can?(:manage_taxonomies)
|
||||||
end
|
end
|
||||||
|
|
||||||
def unsuppress?
|
def unsuppress?
|
||||||
staff?
|
role.can?(:manage_taxonomies)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
|
|
||||||
class InstancePolicy < ApplicationPolicy
|
class InstancePolicy < ApplicationPolicy
|
||||||
def index?
|
def index?
|
||||||
admin?
|
role.can?(:manage_federation)
|
||||||
end
|
end
|
||||||
|
|
||||||
def show?
|
def show?
|
||||||
admin?
|
role.can?(:manage_federation)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
admin?
|
role.can?(:manage_federation)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,19 +2,19 @@
|
||||||
|
|
||||||
class InvitePolicy < ApplicationPolicy
|
class InvitePolicy < ApplicationPolicy
|
||||||
def index?
|
def index?
|
||||||
staff?
|
role.can?(:manage_invites)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create?
|
def create?
|
||||||
min_required_role?
|
role.can?(:invite_users)
|
||||||
end
|
end
|
||||||
|
|
||||||
def deactivate_all?
|
def deactivate_all?
|
||||||
admin?
|
role.can?(:manage_invites)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
owner? || (Setting.min_invite_role == 'admin' ? admin? : staff?)
|
owner? || role.can?(:manage_invites)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -22,8 +22,4 @@ class InvitePolicy < ApplicationPolicy
|
||||||
def owner?
|
def owner?
|
||||||
record.user_id == current_user&.id
|
record.user_id == current_user&.id
|
||||||
end
|
end
|
||||||
|
|
||||||
def min_required_role?
|
|
||||||
current_user&.role?(Setting.min_invite_role)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
|
|
||||||
class IpBlockPolicy < ApplicationPolicy
|
class IpBlockPolicy < ApplicationPolicy
|
||||||
def index?
|
def index?
|
||||||
admin?
|
role.can?(:manage_blocks)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create?
|
def create?
|
||||||
admin?
|
role.can?(:manage_blocks)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
admin?
|
role.can?(:manage_blocks)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
class PreviewCardPolicy < ApplicationPolicy
|
class PreviewCardPolicy < ApplicationPolicy
|
||||||
def index?
|
def index?
|
||||||
staff?
|
role.can?(:manage_taxonomies)
|
||||||
end
|
end
|
||||||
|
|
||||||
def review?
|
def review?
|
||||||
staff?
|
role.can?(:manage_taxonomies)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
class PreviewCardProviderPolicy < ApplicationPolicy
|
class PreviewCardProviderPolicy < ApplicationPolicy
|
||||||
def index?
|
def index?
|
||||||
staff?
|
role.can?(:manage_taxonomies)
|
||||||
end
|
end
|
||||||
|
|
||||||
def review?
|
def review?
|
||||||
staff?
|
role.can?(:manage_taxonomies)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
|
|
||||||
class RelayPolicy < ApplicationPolicy
|
class RelayPolicy < ApplicationPolicy
|
||||||
def update?
|
def update?
|
||||||
admin?
|
role.can?(:manage_federation)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
class ReportNotePolicy < ApplicationPolicy
|
class ReportNotePolicy < ApplicationPolicy
|
||||||
def create?
|
def create?
|
||||||
staff?
|
role.can?(:manage_reports)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
admin? || owner?
|
owner? || (role.can?(:manage_reports) && role.overrides?(record.account.user_role))
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
|
|
||||||
class ReportPolicy < ApplicationPolicy
|
class ReportPolicy < ApplicationPolicy
|
||||||
def update?
|
def update?
|
||||||
staff?
|
role.can?(:manage_reports)
|
||||||
end
|
end
|
||||||
|
|
||||||
def index?
|
def index?
|
||||||
staff?
|
role.can?(:manage_reports)
|
||||||
end
|
end
|
||||||
|
|
||||||
def show?
|
def show?
|
||||||
staff?
|
role.can?(:manage_reports)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,18 +2,18 @@
|
||||||
|
|
||||||
class RulePolicy < ApplicationPolicy
|
class RulePolicy < ApplicationPolicy
|
||||||
def index?
|
def index?
|
||||||
staff?
|
role.can?(:manage_rules)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create?
|
def create?
|
||||||
admin?
|
role.can?(:manage_rules)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update?
|
def update?
|
||||||
admin?
|
role.can?(:manage_rules)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
admin?
|
role.can?(:manage_rules)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
|
|
||||||
class SettingsPolicy < ApplicationPolicy
|
class SettingsPolicy < ApplicationPolicy
|
||||||
def update?
|
def update?
|
||||||
admin?
|
role.can?(:manage_settings)
|
||||||
end
|
end
|
||||||
|
|
||||||
def show?
|
def show?
|
||||||
admin?
|
role.can?(:manage_settings)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
admin?
|
role.can?(:manage_settings)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,7 +8,7 @@ class StatusPolicy < ApplicationPolicy
|
||||||
end
|
end
|
||||||
|
|
||||||
def index?
|
def index?
|
||||||
staff?
|
role.can?(:manage_reports, :manage_users)
|
||||||
end
|
end
|
||||||
|
|
||||||
def show?
|
def show?
|
||||||
|
@ -32,17 +32,17 @@ class StatusPolicy < ApplicationPolicy
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
staff? || owned?
|
role.can?(:manage_reports) || owned?
|
||||||
end
|
end
|
||||||
|
|
||||||
alias unreblog? destroy?
|
alias unreblog? destroy?
|
||||||
|
|
||||||
def update?
|
def update?
|
||||||
staff? || owned?
|
role.can?(:manage_reports) || owned?
|
||||||
end
|
end
|
||||||
|
|
||||||
def review?
|
def review?
|
||||||
staff?
|
role.can?(:manage_taxonomies)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -2,18 +2,18 @@
|
||||||
|
|
||||||
class TagPolicy < ApplicationPolicy
|
class TagPolicy < ApplicationPolicy
|
||||||
def index?
|
def index?
|
||||||
staff?
|
role.can?(:manage_taxonomies)
|
||||||
end
|
end
|
||||||
|
|
||||||
def show?
|
def show?
|
||||||
staff?
|
role.can?(:manage_taxonomies)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update?
|
def update?
|
||||||
staff?
|
role.can?(:manage_taxonomies)
|
||||||
end
|
end
|
||||||
|
|
||||||
def review?
|
def review?
|
||||||
staff?
|
role.can?(:manage_taxonomies)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,52 +2,38 @@
|
||||||
|
|
||||||
class UserPolicy < ApplicationPolicy
|
class UserPolicy < ApplicationPolicy
|
||||||
def reset_password?
|
def reset_password?
|
||||||
staff? && !record.staff?
|
role.can?(:manage_user_access) && role.overrides?(record.role)
|
||||||
end
|
end
|
||||||
|
|
||||||
def change_email?
|
def change_email?
|
||||||
staff? && !record.staff?
|
role.can?(:manage_user_access) && role.overrides?(record.role)
|
||||||
end
|
end
|
||||||
|
|
||||||
def disable_2fa?
|
def disable_2fa?
|
||||||
admin? && !record.staff?
|
role.can?(:manage_user_access) && role.overrides?(record.role)
|
||||||
|
end
|
||||||
|
|
||||||
|
def change_role?
|
||||||
|
role.can?(:manage_roles) && role.overrides?(record.role)
|
||||||
end
|
end
|
||||||
|
|
||||||
def confirm?
|
def confirm?
|
||||||
staff? && !record.confirmed?
|
role.can?(:manage_user_access) && !record.confirmed?
|
||||||
end
|
end
|
||||||
|
|
||||||
def enable?
|
def enable?
|
||||||
staff?
|
role.can?(:manage_users)
|
||||||
end
|
end
|
||||||
|
|
||||||
def approve?
|
def approve?
|
||||||
staff? && !record.approved?
|
role.can?(:manage_users) && !record.approved?
|
||||||
end
|
end
|
||||||
|
|
||||||
def reject?
|
def reject?
|
||||||
staff? && !record.approved?
|
role.can?(:manage_users) && !record.approved?
|
||||||
end
|
end
|
||||||
|
|
||||||
def disable?
|
def disable?
|
||||||
staff? && !record.admin?
|
role.can?(:manage_users) && role.overrides?(record.role)
|
||||||
end
|
|
||||||
|
|
||||||
def promote?
|
|
||||||
admin? && promotable?
|
|
||||||
end
|
|
||||||
|
|
||||||
def demote?
|
|
||||||
admin? && !record.admin? && demoteable?
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def promotable?
|
|
||||||
record.approved? && (!record.staff? || !record.admin?)
|
|
||||||
end
|
|
||||||
|
|
||||||
def demoteable?
|
|
||||||
record.staff?
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
19
app/policies/user_role_policy.rb
Normal file
19
app/policies/user_role_policy.rb
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class UserRolePolicy < ApplicationPolicy
|
||||||
|
def index?
|
||||||
|
role.can?(:manage_roles)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
role.can?(:manage_roles)
|
||||||
|
end
|
||||||
|
|
||||||
|
def update?
|
||||||
|
role.can?(:manage_roles) && role.overrides?(record)
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy?
|
||||||
|
!record.everyone? && role.can?(:manage_roles) && role.overrides?(record) && role.id != record.id
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,34 +2,34 @@
|
||||||
|
|
||||||
class WebhookPolicy < ApplicationPolicy
|
class WebhookPolicy < ApplicationPolicy
|
||||||
def index?
|
def index?
|
||||||
admin?
|
role.can?(:manage_webhooks)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create?
|
def create?
|
||||||
admin?
|
role.can?(:manage_webhooks)
|
||||||
end
|
end
|
||||||
|
|
||||||
def show?
|
def show?
|
||||||
admin?
|
role.can?(:manage_webhooks)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update?
|
def update?
|
||||||
admin?
|
role.can?(:manage_webhooks)
|
||||||
end
|
end
|
||||||
|
|
||||||
def enable?
|
def enable?
|
||||||
admin?
|
role.can?(:manage_webhooks)
|
||||||
end
|
end
|
||||||
|
|
||||||
def disable?
|
def disable?
|
||||||
admin?
|
role.can?(:manage_webhooks)
|
||||||
end
|
end
|
||||||
|
|
||||||
def rotate_secret?
|
def rotate_secret?
|
||||||
admin?
|
role.can?(:manage_webhooks)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
admin?
|
role.can?(:manage_webhooks)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,4 +3,8 @@
|
||||||
class InitialStatePresenter < ActiveModelSerializers::Model
|
class InitialStatePresenter < ActiveModelSerializers::Model
|
||||||
attributes :settings, :push_subscription, :token,
|
attributes :settings, :push_subscription, :token,
|
||||||
:current_account, :admin, :text, :visibility
|
:current_account, :admin, :text, :visibility
|
||||||
|
|
||||||
|
def role
|
||||||
|
current_account&.user_role
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,6 +6,7 @@ class InitialStateSerializer < ActiveModel::Serializer
|
||||||
:languages
|
:languages
|
||||||
|
|
||||||
has_one :push_subscription, serializer: REST::WebPushSubscriptionSerializer
|
has_one :push_subscription, serializer: REST::WebPushSubscriptionSerializer
|
||||||
|
has_one :role, serializer: REST::RoleSerializer
|
||||||
|
|
||||||
def meta
|
def meta
|
||||||
store = {
|
store = {
|
||||||
|
@ -19,7 +20,6 @@ class InitialStateSerializer < ActiveModel::Serializer
|
||||||
repository: Mastodon::Version.repository,
|
repository: Mastodon::Version.repository,
|
||||||
source_url: Mastodon::Version.source_url,
|
source_url: Mastodon::Version.source_url,
|
||||||
version: Mastodon::Version.to_s,
|
version: Mastodon::Version.to_s,
|
||||||
invites_enabled: Setting.min_invite_role == 'user',
|
|
||||||
limited_federation_mode: Rails.configuration.x.whitelist_mode,
|
limited_federation_mode: Rails.configuration.x.whitelist_mode,
|
||||||
mascot: instance_presenter.mascot&.file&.url,
|
mascot: instance_presenter.mascot&.file&.url,
|
||||||
profile_directory: Setting.profile_directory,
|
profile_directory: Setting.profile_directory,
|
||||||
|
@ -39,7 +39,6 @@ class InitialStateSerializer < ActiveModel::Serializer
|
||||||
store[:advanced_layout] = object.current_account.user.setting_advanced_layout
|
store[:advanced_layout] = object.current_account.user.setting_advanced_layout
|
||||||
store[:use_blurhash] = object.current_account.user.setting_use_blurhash
|
store[:use_blurhash] = object.current_account.user.setting_use_blurhash
|
||||||
store[:use_pending_items] = object.current_account.user.setting_use_pending_items
|
store[:use_pending_items] = object.current_account.user.setting_use_pending_items
|
||||||
store[:is_staff] = object.current_account.user.staff?
|
|
||||||
store[:trends] = Setting.trends && object.current_account.user.setting_trends
|
store[:trends] = Setting.trends && object.current_account.user.setting_trends
|
||||||
store[:crop_images] = object.current_account.user.setting_crop_images
|
store[:crop_images] = object.current_account.user.setting_crop_images
|
||||||
else
|
else
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
class REST::CredentialAccountSerializer < REST::AccountSerializer
|
class REST::CredentialAccountSerializer < REST::AccountSerializer
|
||||||
attributes :source
|
attributes :source
|
||||||
|
|
||||||
|
has_one :role, serializer: REST::RoleSerializer
|
||||||
|
|
||||||
def source
|
def source
|
||||||
user = object.user
|
user = object.user
|
||||||
|
|
||||||
|
@ -15,4 +17,8 @@ class REST::CredentialAccountSerializer < REST::AccountSerializer
|
||||||
follow_requests_count: FollowRequest.where(target_account: object).limit(40).count,
|
follow_requests_count: FollowRequest.where(target_account: object).limit(40).count,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def role
|
||||||
|
object.user_role
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -93,7 +93,7 @@ class REST::InstanceSerializer < ActiveModel::Serializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def invites_enabled
|
def invites_enabled
|
||||||
Setting.min_invite_role == 'user'
|
UserRole.everyone.can?(:invite_users)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
13
app/serializers/rest/role_serializer.rb
Normal file
13
app/serializers/rest/role_serializer.rb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class REST::RoleSerializer < ActiveModel::Serializer
|
||||||
|
attributes :id, :name, :permissions, :color, :highlighted
|
||||||
|
|
||||||
|
def id
|
||||||
|
object.id.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def permissions
|
||||||
|
object.computed_permissions.to_s
|
||||||
|
end
|
||||||
|
end
|
|
@ -61,11 +61,11 @@ class AccountSearchService < BaseService
|
||||||
end
|
end
|
||||||
|
|
||||||
def advanced_search_results
|
def advanced_search_results
|
||||||
Account.advanced_search_for(terms_for_query, account, limit_for_non_exact_results, options[:following], offset)
|
Account.advanced_search_for(terms_for_query, account, limit: limit_for_non_exact_results, following: options[:following], offset: offset)
|
||||||
end
|
end
|
||||||
|
|
||||||
def simple_search_results
|
def simple_search_results
|
||||||
Account.search_for(terms_for_query, limit_for_non_exact_results, offset)
|
Account.search_for(terms_for_query, limit: limit_for_non_exact_results, offset: offset)
|
||||||
end
|
end
|
||||||
|
|
||||||
def from_elasticsearch
|
def from_elasticsearch
|
||||||
|
|
|
@ -22,7 +22,7 @@ class AppealService < BaseService
|
||||||
end
|
end
|
||||||
|
|
||||||
def notify_staff!
|
def notify_staff!
|
||||||
User.staff.includes(:account).each do |u|
|
User.those_who_can(:manage_appeals).includes(:account).each do |u|
|
||||||
AdminMailer.new_appeal(u.account, @appeal).deliver_later if u.allows_appeal_emails?
|
AdminMailer.new_appeal(u.account, @appeal).deliver_later if u.allows_appeal_emails?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,7 +17,7 @@ class BootstrapTimelineService < BaseService
|
||||||
end
|
end
|
||||||
|
|
||||||
def notify_staff!
|
def notify_staff!
|
||||||
User.staff.includes(:account).find_each do |user|
|
User.those_who_can(:manage_users).includes(:account).find_each do |user|
|
||||||
LocalNotificationWorker.perform_async(user.account_id, @source_account.id, 'Account', 'admin.sign_up')
|
LocalNotificationWorker.perform_async(user.account_id, @source_account.id, 'Account', 'admin.sign_up')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue