diff --git a/.rubocop.yml b/.rubocop.yml index 9e3ff21f2..8dc2d1c47 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -67,7 +67,7 @@ Lint/UselessAccessModifier: - class_methods Metrics/AbcSize: - Max: 100 + Max: 115 Exclude: - 'lib/mastodon/*_cli.rb' @@ -84,7 +84,7 @@ Metrics/BlockNesting: Metrics/ClassLength: CountComments: false - Max: 400 + Max: 500 Exclude: - 'lib/mastodon/*_cli.rb' diff --git a/app/controllers/admin/account_actions_controller.rb b/app/controllers/admin/account_actions_controller.rb index ea56fa0ac..3f2e28b6a 100644 --- a/app/controllers/admin/account_actions_controller.rb +++ b/app/controllers/admin/account_actions_controller.rb @@ -5,11 +5,15 @@ module Admin before_action :set_account 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) @warning_presets = AccountWarningPreset.all end def create + authorize @account, :show? + account_action = Admin::AccountAction.new(resource_params) account_action.target_account = @account account_action.current_account = current_account diff --git a/app/controllers/admin/accounts_controller.rb b/app/controllers/admin/accounts_controller.rb index e0ae71b9f..46c9aba91 100644 --- a/app/controllers/admin/accounts_controller.rb +++ b/app/controllers/admin/accounts_controller.rb @@ -14,6 +14,8 @@ module Admin end def batch + authorize :account, :index? + @form = Form::AccountBatch.new(form_account_batch_params.merge(current_account: current_account, action: action_from_button)) @form.save rescue ActionController::ParameterMissing diff --git a/app/controllers/admin/action_logs_controller.rb b/app/controllers/admin/action_logs_controller.rb index 2d77620df..42edec15a 100644 --- a/app/controllers/admin/action_logs_controller.rb +++ b/app/controllers/admin/action_logs_controller.rb @@ -4,7 +4,10 @@ module Admin class ActionLogsController < BaseController 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 diff --git a/app/controllers/admin/base_controller.rb b/app/controllers/admin/base_controller.rb index 7b81a2b01..5b7a7ec11 100644 --- a/app/controllers/admin/base_controller.rb +++ b/app/controllers/admin/base_controller.rb @@ -7,8 +7,8 @@ module Admin layout 'admin' - before_action :require_staff! before_action :set_body_classes + after_action :verify_authorized private diff --git a/app/controllers/admin/custom_emojis_controller.rb b/app/controllers/admin/custom_emojis_controller.rb index 71efb543e..2c33e9f8f 100644 --- a/app/controllers/admin/custom_emojis_controller.rb +++ b/app/controllers/admin/custom_emojis_controller.rb @@ -29,6 +29,8 @@ module Admin end 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.save rescue ActionController::ParameterMissing diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb index da9c6dd16..924b623ad 100644 --- a/app/controllers/admin/dashboard_controller.rb +++ b/app/controllers/admin/dashboard_controller.rb @@ -5,7 +5,9 @@ module Admin include Redisable 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) @pending_users_count = User.pending.count @pending_reports_count = Report.unresolved.count diff --git a/app/controllers/admin/email_domain_blocks_controller.rb b/app/controllers/admin/email_domain_blocks_controller.rb index a4bbbba5b..593457b94 100644 --- a/app/controllers/admin/email_domain_blocks_controller.rb +++ b/app/controllers/admin/email_domain_blocks_controller.rb @@ -12,6 +12,8 @@ module Admin end 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.save rescue ActionController::ParameterMissing diff --git a/app/controllers/admin/follow_recommendations_controller.rb b/app/controllers/admin/follow_recommendations_controller.rb index e3eac62b3..841e3cc7f 100644 --- a/app/controllers/admin/follow_recommendations_controller.rb +++ b/app/controllers/admin/follow_recommendations_controller.rb @@ -12,6 +12,8 @@ module Admin end def update + authorize :follow_recommendation, :show? + @form = Form::AccountBatch.new(form_account_batch_params.merge(current_account: current_account, action: action_from_button)) @form.save rescue ActionController::ParameterMissing diff --git a/app/controllers/admin/ip_blocks_controller.rb b/app/controllers/admin/ip_blocks_controller.rb index 92b8b0d2b..a87520f4e 100644 --- a/app/controllers/admin/ip_blocks_controller.rb +++ b/app/controllers/admin/ip_blocks_controller.rb @@ -29,6 +29,8 @@ module Admin end 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.save rescue ActionController::ParameterMissing diff --git a/app/controllers/admin/relationships_controller.rb b/app/controllers/admin/relationships_controller.rb index 085ded21c..67645f054 100644 --- a/app/controllers/admin/relationships_controller.rb +++ b/app/controllers/admin/relationships_controller.rb @@ -7,7 +7,7 @@ module Admin PER_PAGE = 40 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) @form = Form::AccountBatch.new diff --git a/app/controllers/admin/roles_controller.rb b/app/controllers/admin/roles_controller.rb index 13f56e9be..3e502ccc4 100644 --- a/app/controllers/admin/roles_controller.rb +++ b/app/controllers/admin/roles_controller.rb @@ -2,20 +2,63 @@ module Admin class RolesController < BaseController - before_action :set_user + before_action :set_role, except: [:index, :new, :create] - def promote - authorize @user, :promote? - @user.promote! - log_action :promote, @user - redirect_to admin_account_path(@user.account_id) + def index + authorize :user_role, :index? + + @roles = UserRole.order(position: :desc).page(params[:page]) end - def demote - authorize @user, :demote? - @user.demote! - log_action :demote, @user - redirect_to admin_account_path(@user.account_id) + def new + authorize :user_role, :create? + + @role = UserRole.new + 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 diff --git a/app/controllers/admin/statuses_controller.rb b/app/controllers/admin/statuses_controller.rb index 817c0caa9..084921ceb 100644 --- a/app/controllers/admin/statuses_controller.rb +++ b/app/controllers/admin/statuses_controller.rb @@ -14,6 +14,8 @@ module Admin end 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.save! rescue ActionController::ParameterMissing diff --git a/app/controllers/admin/subscriptions_controller.rb b/app/controllers/admin/subscriptions_controller.rb deleted file mode 100644 index 40500ef43..000000000 --- a/app/controllers/admin/subscriptions_controller.rb +++ /dev/null @@ -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 diff --git a/app/controllers/admin/trends/links/preview_card_providers_controller.rb b/app/controllers/admin/trends/links/preview_card_providers_controller.rb index 40a466cd6..97dee8eca 100644 --- a/app/controllers/admin/trends/links/preview_card_providers_controller.rb +++ b/app/controllers/admin/trends/links/preview_card_providers_controller.rb @@ -2,13 +2,15 @@ class Admin::Trends::Links::PreviewCardProvidersController < Admin::BaseController def index - authorize :preview_card_provider, :index? + authorize :preview_card_provider, :review? @preview_card_providers = filtered_preview_card_providers.page(params[:page]) @form = Trends::PreviewCardProviderBatch.new end 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.save rescue ActionController::ParameterMissing diff --git a/app/controllers/admin/trends/links_controller.rb b/app/controllers/admin/trends/links_controller.rb index 434eec5fe..a497eae41 100644 --- a/app/controllers/admin/trends/links_controller.rb +++ b/app/controllers/admin/trends/links_controller.rb @@ -2,13 +2,15 @@ class Admin::Trends::LinksController < Admin::BaseController def index - authorize :preview_card, :index? + authorize :preview_card, :review? @preview_cards = filtered_preview_cards.page(params[:page]) @form = Trends::PreviewCardBatch.new end 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.save rescue ActionController::ParameterMissing diff --git a/app/controllers/admin/trends/statuses_controller.rb b/app/controllers/admin/trends/statuses_controller.rb index 766242738..c538962f9 100644 --- a/app/controllers/admin/trends/statuses_controller.rb +++ b/app/controllers/admin/trends/statuses_controller.rb @@ -2,13 +2,15 @@ class Admin::Trends::StatusesController < Admin::BaseController def index - authorize :status, :index? + authorize :status, :review? @statuses = filtered_statuses.page(params[:page]) @form = Trends::StatusBatch.new end def batch + authorize :status, :review? + @form = Trends::StatusBatch.new(trends_status_batch_params.merge(current_account: current_account, action: action_from_button)) @form.save rescue ActionController::ParameterMissing diff --git a/app/controllers/admin/trends/tags_controller.rb b/app/controllers/admin/trends/tags_controller.rb index f4d1ec0d1..98dd6c8ec 100644 --- a/app/controllers/admin/trends/tags_controller.rb +++ b/app/controllers/admin/trends/tags_controller.rb @@ -2,13 +2,15 @@ class Admin::Trends::TagsController < Admin::BaseController def index - authorize :tag, :index? + authorize :tag, :review? @tags = filtered_tags.page(params[:page]) @form = Trends::TagBatch.new end def batch + authorize :tag, :review? + @form = Trends::TagBatch.new(trends_tag_batch_params.merge(current_account: current_account, action: action_from_button)) @form.save rescue ActionController::ParameterMissing diff --git a/app/controllers/admin/users/roles_controller.rb b/app/controllers/admin/users/roles_controller.rb new file mode 100644 index 000000000..0db50cee9 --- /dev/null +++ b/app/controllers/admin/users/roles_controller.rb @@ -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 diff --git a/app/controllers/admin/two_factor_authentications_controller.rb b/app/controllers/admin/users/two_factor_authentications_controller.rb similarity index 86% rename from app/controllers/admin/two_factor_authentications_controller.rb rename to app/controllers/admin/users/two_factor_authentications_controller.rb index f7fb7eb8f..5e3fb2b3c 100644 --- a/app/controllers/admin/two_factor_authentications_controller.rb +++ b/app/controllers/admin/users/two_factor_authentications_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Admin - class TwoFactorAuthenticationsController < BaseController + class Users::TwoFactorAuthenticationsController < BaseController before_action :set_target_user def destroy diff --git a/app/controllers/api/v1/admin/account_actions_controller.rb b/app/controllers/api/v1/admin/account_actions_controller.rb index 6c9e04402..7249797a4 100644 --- a/app/controllers/api/v1/admin/account_actions_controller.rb +++ b/app/controllers/api/v1/admin/account_actions_controller.rb @@ -1,11 +1,16 @@ # frozen_string_literal: true class Api::V1::Admin::AccountActionsController < Api::BaseController + include Authorization + before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:accounts' } - before_action :require_staff! before_action :set_account + after_action :verify_authorized + def create + authorize @account, :show? + account_action = Admin::AccountAction.new(resource_params) account_action.target_account = @account account_action.current_account = current_account diff --git a/app/controllers/api/v1/admin/accounts_controller.rb b/app/controllers/api/v1/admin/accounts_controller.rb index 65ed69f7b..0dee02e94 100644 --- a/app/controllers/api/v1/admin/accounts_controller.rb +++ b/app/controllers/api/v1/admin/accounts_controller.rb @@ -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:write', :'admin:write:accounts' }, except: [:index, :show] - before_action :require_staff! before_action :set_accounts, only: :index before_action :set_account, except: :index before_action :require_local_account!, only: [:enable, :approve, :reject] + after_action :verify_authorized after_action :insert_pagination_headers, only: :index FILTER_PARAMS = %i( @@ -119,7 +119,9 @@ class Api::V1::Admin::AccountsController < Api::BaseController translated_params[:status] = status.to_s if params[status].present? 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 end diff --git a/app/controllers/api/v1/admin/dimensions_controller.rb b/app/controllers/api/v1/admin/dimensions_controller.rb index 49a5be1c3..4a72ad08b 100644 --- a/app/controllers/api/v1/admin/dimensions_controller.rb +++ b/app/controllers/api/v1/admin/dimensions_controller.rb @@ -1,11 +1,15 @@ # frozen_string_literal: true class Api::V1::Admin::DimensionsController < Api::BaseController + include Authorization + before_action -> { authorize_if_got_token! :'admin:read' } - before_action :require_staff! before_action :set_dimensions + after_action :verify_authorized + def create + authorize :dashboard, :index? render json: @dimensions, each_serializer: REST::Admin::DimensionSerializer end diff --git a/app/controllers/api/v1/admin/domain_allows_controller.rb b/app/controllers/api/v1/admin/domain_allows_controller.rb index 838978ddb..59aa807d6 100644 --- a/app/controllers/api/v1/admin/domain_allows_controller.rb +++ b/app/controllers/api/v1/admin/domain_allows_controller.rb @@ -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:write', :'admin:write:domain_allows' }, except: [:index, :show] - before_action :require_staff! before_action :set_domain_allows, only: :index before_action :set_domain_allow, only: [:show, :destroy] + after_action :verify_authorized after_action :insert_pagination_headers, only: :index PAGINATION_PARAMS = %i(limit).freeze diff --git a/app/controllers/api/v1/admin/domain_blocks_controller.rb b/app/controllers/api/v1/admin/domain_blocks_controller.rb index 229870eee..de8fd9d08 100644 --- a/app/controllers/api/v1/admin/domain_blocks_controller.rb +++ b/app/controllers/api/v1/admin/domain_blocks_controller.rb @@ -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:write', :'admin:write:domain_blocks' }, except: [:index, :show] - before_action :require_staff! before_action :set_domain_blocks, only: :index before_action :set_domain_block, only: [:show, :update, :destroy] + after_action :verify_authorized after_action :insert_pagination_headers, only: :index PAGINATION_PARAMS = %i(limit).freeze diff --git a/app/controllers/api/v1/admin/measures_controller.rb b/app/controllers/api/v1/admin/measures_controller.rb index da95d3422..d78d7e10b 100644 --- a/app/controllers/api/v1/admin/measures_controller.rb +++ b/app/controllers/api/v1/admin/measures_controller.rb @@ -1,11 +1,15 @@ # frozen_string_literal: true class Api::V1::Admin::MeasuresController < Api::BaseController + include Authorization + before_action -> { authorize_if_got_token! :'admin:read' } - before_action :require_staff! before_action :set_measures + after_action :verify_authorized + def create + authorize :dashboard, :index? render json: @measures, each_serializer: REST::Admin::MeasureSerializer end diff --git a/app/controllers/api/v1/admin/reports_controller.rb b/app/controllers/api/v1/admin/reports_controller.rb index 865ba3d23..9dfb181a2 100644 --- a/app/controllers/api/v1/admin/reports_controller.rb +++ b/app/controllers/api/v1/admin/reports_controller.rb @@ -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:write', :'admin:write:reports' }, except: [:index, :show] - before_action :require_staff! before_action :set_reports, only: :index before_action :set_report, except: :index + after_action :verify_authorized after_action :insert_pagination_headers, only: :index FILTER_PARAMS = %i( diff --git a/app/controllers/api/v1/admin/retention_controller.rb b/app/controllers/api/v1/admin/retention_controller.rb index 98d1a3d81..59d6b8388 100644 --- a/app/controllers/api/v1/admin/retention_controller.rb +++ b/app/controllers/api/v1/admin/retention_controller.rb @@ -1,11 +1,15 @@ # frozen_string_literal: true class Api::V1::Admin::RetentionController < Api::BaseController + include Authorization + before_action -> { authorize_if_got_token! :'admin:read' } - before_action :require_staff! before_action :set_cohorts + after_action :verify_authorized + def create + authorize :dashboard, :index? render json: @cohorts, each_serializer: REST::Admin::CohortSerializer end diff --git a/app/controllers/api/v1/admin/trends/links_controller.rb b/app/controllers/api/v1/admin/trends/links_controller.rb index 0a191fe4b..cc6388980 100644 --- a/app/controllers/api/v1/admin/trends/links_controller.rb +++ b/app/controllers/api/v1/admin/trends/links_controller.rb @@ -1,17 +1,19 @@ # 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 :require_staff! - before_action :set_links - - def index - render json: @links, each_serializer: REST::Trends::LinkSerializer - end private - def set_links - @links = Trends.links.query.limit(limit_param(10)) + def enabled? + 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 diff --git a/app/controllers/api/v1/admin/trends/statuses_controller.rb b/app/controllers/api/v1/admin/trends/statuses_controller.rb index cb145f165..c39f77363 100644 --- a/app/controllers/api/v1/admin/trends/statuses_controller.rb +++ b/app/controllers/api/v1/admin/trends/statuses_controller.rb @@ -1,17 +1,19 @@ # 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 :require_staff! - before_action :set_statuses - - def index - render json: @statuses, each_serializer: REST::StatusSerializer - end private - def set_statuses - @statuses = cache_collection(Trends.statuses.query.limit(limit_param(DEFAULT_STATUSES_LIMIT)), Status) + def enabled? + 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 diff --git a/app/controllers/api/v1/admin/trends/tags_controller.rb b/app/controllers/api/v1/admin/trends/tags_controller.rb index 9c28b0412..f3c0c4b6b 100644 --- a/app/controllers/api/v1/admin/trends/tags_controller.rb +++ b/app/controllers/api/v1/admin/trends/tags_controller.rb @@ -1,17 +1,19 @@ # 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 :require_staff! - before_action :set_tags - - def index - render json: @tags, each_serializer: REST::Admin::TagSerializer - end private - def set_tags - @tags = Trends.tags.query.limit(limit_param(10)) + def enabled? + 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 diff --git a/app/controllers/api/v1/trends/links_controller.rb b/app/controllers/api/v1/trends/links_controller.rb index 2385fe438..1a9f918f2 100644 --- a/app/controllers/api/v1/trends/links_controller.rb +++ b/app/controllers/api/v1/trends/links_controller.rb @@ -13,10 +13,14 @@ class Api::V1::Trends::LinksController < Api::BaseController private + def enabled? + Setting.trends + end + def set_links @links = begin - if Setting.trends - links_from_trends + if enabled? + links_from_trends.offset(offset_param).limit(limit_param(DEFAULT_LINKS_LIMIT)) else [] end @@ -24,7 +28,7 @@ class Api::V1::Trends::LinksController < Api::BaseController end 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 def insert_pagination_headers diff --git a/app/controllers/api/v1/trends/statuses_controller.rb b/app/controllers/api/v1/trends/statuses_controller.rb index 1f2fff582..c275d5fc8 100644 --- a/app/controllers/api/v1/trends/statuses_controller.rb +++ b/app/controllers/api/v1/trends/statuses_controller.rb @@ -11,10 +11,14 @@ class Api::V1::Trends::StatusesController < Api::BaseController private + def enabled? + Setting.trends + end + def set_statuses @statuses = begin - if Setting.trends - cache_collection(statuses_from_trends, Status) + if enabled? + cache_collection(statuses_from_trends.offset(offset_param).limit(limit_param(DEFAULT_STATUSES_LIMIT)), Status) else [] end @@ -24,7 +28,7 @@ class Api::V1::Trends::StatusesController < Api::BaseController def statuses_from_trends scope = Trends.statuses.query.allowed.in_locale(content_locale) scope = scope.filtered_for(current_account) if user_signed_in? - scope.offset(offset_param).limit(limit_param(DEFAULT_STATUSES_LIMIT)) + scope end def insert_pagination_headers diff --git a/app/controllers/api/v1/trends/tags_controller.rb b/app/controllers/api/v1/trends/tags_controller.rb index 38003f599..41f9ffac1 100644 --- a/app/controllers/api/v1/trends/tags_controller.rb +++ b/app/controllers/api/v1/trends/tags_controller.rb @@ -13,16 +13,24 @@ class Api::V1::Trends::TagsController < Api::BaseController private + def enabled? + Setting.trends + end + def set_tags @tags = begin - if Setting.trends - Trends.tags.query.allowed.offset(offset_param).limit(limit_param(DEFAULT_TAGS_LIMIT)) + if enabled? + tags_from_trends.offset(offset_param).limit(limit_param(DEFAULT_TAGS_LIMIT)) else [] end end end + def tags_from_trends + Trends.tags.query.allowed + end + def insert_pagination_headers set_pagination_headers(next_path, prev_path) end diff --git a/app/controllers/api/v2/admin/accounts_controller.rb b/app/controllers/api/v2/admin/accounts_controller.rb index a89e6835e..bcc1a0733 100644 --- a/app/controllers/api/v2/admin/accounts_controller.rb +++ b/app/controllers/api/v2/admin/accounts_controller.rb @@ -11,6 +11,7 @@ class Api::V2::Admin::AccountsController < Api::V1::Admin::AccountsController email ip invited_by + role_ids ).freeze PAGINATION_PARAMS = (%i(limit) + FILTER_PARAMS).freeze @@ -18,7 +19,17 @@ class Api::V2::Admin::AccountsController < Api::V1::Admin::AccountsController private 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 def filter_params diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 3d2f8280b..615536b96 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -56,14 +56,6 @@ class ApplicationController < ActionController::Base store_location_for(:user, request.url) unless [:json, :rss].include?(request.format&.to_sym) end - def require_admin! - forbidden unless current_user&.admin? - end - - def require_staff! - forbidden unless current_user&.staff? - end - def require_functional! redirect_to edit_user_registration_path unless current_user.functional? end diff --git a/app/controllers/custom_css_controller.rb b/app/controllers/custom_css_controller.rb index e1dc5eaf6..9270c467d 100644 --- a/app/controllers/custom_css_controller.rb +++ b/app/controllers/custom_css_controller.rb @@ -13,6 +13,6 @@ class CustomCssController < ApplicationController def show expires_in 3.minutes, public: true request.session_options[:skip] = true - render plain: Setting.custom_css || '', content_type: 'text/css' + render content_type: 'text/css' end end diff --git a/app/helpers/accounts_helper.rb b/app/helpers/accounts_helper.rb index d37634964..59664373d 100644 --- a/app/helpers/accounts_helper.rb +++ b/app/helpers/accounts_helper.rb @@ -61,21 +61,13 @@ module AccountsHelper end end - def account_badge(account, all: false) + def account_badge(account) if account.bot? content_tag(:div, content_tag(:div, t('accounts.roles.bot'), class: 'account-role bot'), class: 'roles') elsif account.group? 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 - content_tag(:div, class: 'roles') do - 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 + elsif account.user_role&.highlighted? + content_tag(:div, content_tag(:div, account.user_role.name, class: "account-role user-role-#{account.user_role.id}"), class: 'roles') end end diff --git a/app/javascript/mastodon/components/status_action_bar.js b/app/javascript/mastodon/components/status_action_bar.js index ab8755be0..d44da482d 100644 --- a/app/javascript/mastodon/components/status_action_bar.js +++ b/app/javascript/mastodon/components/status_action_bar.js @@ -6,8 +6,9 @@ import IconButton from './icon_button'; import DropdownMenuContainer from '../containers/dropdown_menu_container'; import { defineMessages, injectIntl } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { me, isStaff } from '../initial_state'; +import { me } from '../initial_state'; import classNames from 'classnames'; +import { PERMISSION_MANAGE_USERS } from 'mastodon/permissions'; const messages = defineMessages({ delete: { id: 'status.delete', defaultMessage: 'Delete' }, @@ -55,6 +56,7 @@ class StatusActionBar extends ImmutablePureComponent { static contextTypes = { router: PropTypes.object, + identity: PropTypes.object, }; 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({ 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')}` }); diff --git a/app/javascript/mastodon/containers/mastodon.js b/app/javascript/mastodon/containers/mastodon.js index 0c3f6afa8..f4bef4686 100644 --- a/app/javascript/mastodon/containers/mastodon.js +++ b/app/javascript/mastodon/containers/mastodon.js @@ -26,6 +26,7 @@ const createIdentityContext = state => ({ signedIn: !!state.meta.me, accountId: state.meta.me, accessToken: state.meta.access_token, + permissions: state.role.permissions, }); export default class Mastodon extends React.PureComponent { diff --git a/app/javascript/mastodon/features/account/components/header.js b/app/javascript/mastodon/features/account/components/header.js index 8e6b9f063..1ad9341c7 100644 --- a/app/javascript/mastodon/features/account/components/header.js +++ b/app/javascript/mastodon/features/account/components/header.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import Button from 'mastodon/components/button'; 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 Icon from 'mastodon/components/icon'; 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 DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container'; import AccountNoteContainer from '../containers/account_note_container'; +import { PERMISSION_MANAGE_USERS } from 'mastodon/permissions'; const messages = defineMessages({ unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' }, @@ -64,6 +65,10 @@ const dateFormatOptions = { export default @injectIntl class Header extends ImmutablePureComponent { + static contextTypes = { + identity: PropTypes.object, + }; + static propTypes = { account: ImmutablePropTypes.map, 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({ text: intl.formatMessage(messages.admin_account, { name: account.get('username') }), href: `/admin/accounts/${account.get('id')}` }); } diff --git a/app/javascript/mastodon/features/notifications/components/column_settings.js b/app/javascript/mastodon/features/notifications/components/column_settings.js index 61df79b46..b1618c1b4 100644 --- a/app/javascript/mastodon/features/notifications/components/column_settings.js +++ b/app/javascript/mastodon/features/notifications/components/column_settings.js @@ -5,10 +5,14 @@ import { FormattedMessage } from 'react-intl'; import ClearColumnButton from './clear_column_button'; import GrantPermissionButton from './grant_permission_button'; 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 { + static contextTypes = { + identity: PropTypes.object, + }; + static propTypes = { settings: ImmutablePropTypes.map.isRequired, pushSettings: ImmutablePropTypes.map.isRequired, @@ -166,7 +170,7 @@ export default class ColumnSettings extends React.PureComponent { - {isStaff && ( + {(this.context.identity.permissions & PERMISSION_MANAGE_USERS === PERMISSION_MANAGE_USERS) && (
<a>
and <em>
.
title: Server description
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index ea4f68562..932f34d82 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -96,6 +96,13 @@ en:
name: You can only change the casing of the letters, for example, to make it more readable
user:
chosen_languages: When checked, only posts in selected languages will be displayed in public timelines
+ role: The role controls which permissions the user has
+ user_role:
+ color: Color to be used for the role throughout the UI, as RGB in hex format
+ highlighted: This makes the role publicly visible
+ name: Public name of the role, if role is set to be displayed as a badge
+ permissions_as_keys: Users with this role will have access to...
+ position: Higher role decides conflict resolution in certain situations
webhook:
events: Select events to send
url: Where events will be sent to
@@ -232,6 +239,14 @@ en:
name: Hashtag
trendable: Allow this hashtag to appear under trends
usable: Allow posts to use this hashtag
+ user:
+ role: Role
+ user_role:
+ color: Badge color
+ highlighted: Display role as badge on user profiles
+ name: Name
+ permissions_as_keys: Permissions
+ position: Priority
webhook:
events: Enabled events
url: Endpoint URL
diff --git a/config/navigation.rb b/config/navigation.rb
index ec5719e3e..706de0471 100644
--- a/config/navigation.rb
+++ b/config/navigation.rb
@@ -2,66 +2,67 @@
SimpleNavigation::Configuration.run do |navigation|
navigation.items do |n|
- n.item :web, safe_join([fa_icon('chevron-left fw'), t('settings.back')]), root_url
+ n.item :web, safe_join([fa_icon('chevron-left fw'), t('settings.back')]), root_path
- n.item :profile, safe_join([fa_icon('user fw'), t('settings.profile')]), settings_profile_url, if: -> { current_user.functional? } do |s|
- s.item :profile, safe_join([fa_icon('pencil fw'), t('settings.appearance')]), settings_profile_url
- s.item :featured_tags, safe_join([fa_icon('hashtag fw'), t('settings.featured_tags')]), settings_featured_tags_url
+ n.item :profile, safe_join([fa_icon('user fw'), t('settings.profile')]), settings_profile_path, if: -> { current_user.functional? } do |s|
+ s.item :profile, safe_join([fa_icon('pencil fw'), t('settings.appearance')]), settings_profile_path
+ s.item :featured_tags, safe_join([fa_icon('hashtag fw'), t('settings.featured_tags')]), settings_featured_tags_path
end
- n.item :preferences, safe_join([fa_icon('cog fw'), t('settings.preferences')]), settings_preferences_url, if: -> { current_user.functional? } do |s|
- s.item :appearance, safe_join([fa_icon('desktop fw'), t('settings.appearance')]), settings_preferences_appearance_url
- s.item :notifications, safe_join([fa_icon('bell fw'), t('settings.notifications')]), settings_preferences_notifications_url
- s.item :other, safe_join([fa_icon('cog fw'), t('preferences.other')]), settings_preferences_other_url
+ n.item :preferences, safe_join([fa_icon('cog fw'), t('settings.preferences')]), settings_preferences_path, if: -> { current_user.functional? } do |s|
+ s.item :appearance, safe_join([fa_icon('desktop fw'), t('settings.appearance')]), settings_preferences_appearance_path
+ s.item :notifications, safe_join([fa_icon('bell fw'), t('settings.notifications')]), settings_preferences_notifications_path
+ s.item :other, safe_join([fa_icon('cog fw'), t('preferences.other')]), settings_preferences_other_path
end
- n.item :relationships, safe_join([fa_icon('users fw'), t('settings.relationships')]), relationships_url, if: -> { current_user.functional? }
+ n.item :relationships, safe_join([fa_icon('users fw'), t('settings.relationships')]), relationships_path, if: -> { current_user.functional? }
n.item :filters, safe_join([fa_icon('filter fw'), t('filters.index.title')]), filters_path, highlights_on: %r{/filters}, if: -> { current_user.functional? }
- n.item :statuses_cleanup, safe_join([fa_icon('history fw'), t('settings.statuses_cleanup')]), statuses_cleanup_url, if: -> { current_user.functional? }
+ n.item :statuses_cleanup, safe_join([fa_icon('history fw'), t('settings.statuses_cleanup')]), statuses_cleanup_path, if: -> { current_user.functional? }
- n.item :security, safe_join([fa_icon('lock fw'), t('settings.account')]), edit_user_registration_url do |s|
- s.item :password, safe_join([fa_icon('lock fw'), t('settings.account_settings')]), edit_user_registration_url, highlights_on: %r{/auth/edit|/settings/delete|/settings/migration|/settings/aliases|/settings/login_activities|^/disputes}
- s.item :two_factor_authentication, safe_join([fa_icon('mobile fw'), t('settings.two_factor_authentication')]), settings_two_factor_authentication_methods_url, highlights_on: %r{/settings/two_factor_authentication|/settings/otp_authentication|/settings/security_keys}
- s.item :authorized_apps, safe_join([fa_icon('list fw'), t('settings.authorized_apps')]), oauth_authorized_applications_url
+ n.item :security, safe_join([fa_icon('lock fw'), t('settings.account')]), edit_user_registration_path do |s|
+ s.item :password, safe_join([fa_icon('lock fw'), t('settings.account_settings')]), edit_user_registration_path, highlights_on: %r{/auth/edit|/settings/delete|/settings/migration|/settings/aliases|/settings/login_activities|^/disputes}
+ s.item :two_factor_authentication, safe_join([fa_icon('mobile fw'), t('settings.two_factor_authentication')]), settings_two_factor_authentication_methods_path, highlights_on: %r{/settings/two_factor_authentication|/settings/otp_authentication|/settings/security_keys}
+ s.item :authorized_apps, safe_join([fa_icon('list fw'), t('settings.authorized_apps')]), oauth_authorized_applications_path
end
- n.item :data, safe_join([fa_icon('cloud-download fw'), t('settings.import_and_export')]), settings_export_url do |s|
- s.item :import, safe_join([fa_icon('cloud-upload fw'), t('settings.import')]), settings_import_url, if: -> { current_user.functional? }
- s.item :export, safe_join([fa_icon('cloud-download fw'), t('settings.export')]), settings_export_url
+ n.item :data, safe_join([fa_icon('cloud-download fw'), t('settings.import_and_export')]), settings_export_path do |s|
+ s.item :import, safe_join([fa_icon('cloud-upload fw'), t('settings.import')]), settings_import_path, if: -> { current_user.functional? }
+ s.item :export, safe_join([fa_icon('cloud-download fw'), t('settings.export')]), settings_export_path
end
- n.item :invites, safe_join([fa_icon('user-plus fw'), t('invites.title')]), invites_path, if: proc { Setting.min_invite_role == 'user' && current_user.functional? }
- n.item :development, safe_join([fa_icon('code fw'), t('settings.development')]), settings_applications_url, if: -> { current_user.functional? }
+ n.item :invites, safe_join([fa_icon('user-plus fw'), t('invites.title')]), invites_path, if: -> { current_user.can?(:invite_users) && current_user.functional? }
+ n.item :development, safe_join([fa_icon('code fw'), t('settings.development')]), settings_applications_path, if: -> { current_user.functional? }
- n.item :trends, safe_join([fa_icon('fire fw'), t('admin.trends.title')]), admin_trends_tags_path, if: proc { current_user.staff? } do |s|
+ n.item :trends, safe_join([fa_icon('fire fw'), t('admin.trends.title')]), admin_trends_statuses_path, if: -> { current_user.can?(:manage_taxonomies) } do |s|
s.item :statuses, safe_join([fa_icon('comments-o fw'), t('admin.trends.statuses.title')]), admin_trends_statuses_path, highlights_on: %r{/admin/trends/statuses}
s.item :tags, safe_join([fa_icon('hashtag fw'), t('admin.trends.tags.title')]), admin_trends_tags_path, highlights_on: %r{/admin/tags|/admin/trends/tags}
s.item :links, safe_join([fa_icon('newspaper-o fw'), t('admin.trends.links.title')]), admin_trends_links_path, highlights_on: %r{/admin/trends/links}
end
- n.item :moderation, safe_join([fa_icon('gavel fw'), t('moderation.title')]), admin_reports_url, if: proc { current_user.staff? } do |s|
- s.item :action_logs, safe_join([fa_icon('bars fw'), t('admin.action_logs.title')]), admin_action_logs_url
- s.item :reports, safe_join([fa_icon('flag fw'), t('admin.reports.title')]), admin_reports_url, highlights_on: %r{/admin/reports}
- s.item :accounts, safe_join([fa_icon('users fw'), t('admin.accounts.title')]), admin_accounts_url(origin: 'local'), highlights_on: %r{/admin/accounts|/admin/pending_accounts|/admin/disputes}
- s.item :invites, safe_join([fa_icon('user-plus fw'), t('admin.invites.title')]), admin_invites_path
- s.item :follow_recommendations, safe_join([fa_icon('user-plus fw'), t('admin.follow_recommendations.title')]), admin_follow_recommendations_path, highlights_on: %r{/admin/follow_recommendations}
- s.item :instances, safe_join([fa_icon('cloud fw'), t('admin.instances.title')]), admin_instances_url(limited: whitelist_mode? ? nil : '1'), highlights_on: %r{/admin/instances|/admin/domain_blocks|/admin/domain_allows}, if: -> { current_user.admin? }
- s.item :email_domain_blocks, safe_join([fa_icon('envelope fw'), t('admin.email_domain_blocks.title')]), admin_email_domain_blocks_url, highlights_on: %r{/admin/email_domain_blocks}, if: -> { current_user.admin? }
- s.item :ip_blocks, safe_join([fa_icon('ban fw'), t('admin.ip_blocks.title')]), admin_ip_blocks_url, highlights_on: %r{/admin/ip_blocks}, if: -> { current_user.admin? }
+ n.item :moderation, safe_join([fa_icon('gavel fw'), t('moderation.title')]), nil, if: -> { current_user.can?(:manage_reports, :view_audit_log, :manage_users, :manage_invites, :manage_taxonomies, :manage_federation, :manage_blocks) } do |s|
+ s.item :reports, safe_join([fa_icon('flag fw'), t('admin.reports.title')]), admin_reports_path, highlights_on: %r{/admin/reports}, if: -> { current_user.can?(:manage_reports) }
+ s.item :accounts, safe_join([fa_icon('users fw'), t('admin.accounts.title')]), admin_accounts_path(origin: 'local'), highlights_on: %r{/admin/accounts|/admin/pending_accounts|/admin/disputes|/admin/users}, if: -> { current_user.can?(:manage_users) }
+ s.item :invites, safe_join([fa_icon('user-plus fw'), t('admin.invites.title')]), admin_invites_path, if: -> { current_user.can?(:manage_invites) }
+ s.item :follow_recommendations, safe_join([fa_icon('user-plus fw'), t('admin.follow_recommendations.title')]), admin_follow_recommendations_path, highlights_on: %r{/admin/follow_recommendations}, if: -> { current_user.can?(:manage_taxonomies) }
+ s.item :instances, safe_join([fa_icon('cloud fw'), t('admin.instances.title')]), admin_instances_path(limited: whitelist_mode? ? nil : '1'), highlights_on: %r{/admin/instances|/admin/domain_blocks|/admin/domain_allows}, if: -> { current_user.can?(:manage_federation) }
+ s.item :email_domain_blocks, safe_join([fa_icon('envelope fw'), t('admin.email_domain_blocks.title')]), admin_email_domain_blocks_path, highlights_on: %r{/admin/email_domain_blocks}, if: -> { current_user.can?(:manage_blocks) }
+ s.item :ip_blocks, safe_join([fa_icon('ban fw'), t('admin.ip_blocks.title')]), admin_ip_blocks_path, highlights_on: %r{/admin/ip_blocks}, if: -> { current_user.can?(:manage_blocks) }
+ s.item :action_logs, safe_join([fa_icon('bars fw'), t('admin.action_logs.title')]), admin_action_logs_path, if: -> { current_user.can?(:view_audit_log) }
end
- n.item :admin, safe_join([fa_icon('cogs fw'), t('admin.title')]), admin_dashboard_url, if: proc { current_user.staff? } do |s|
- s.item :dashboard, safe_join([fa_icon('tachometer fw'), t('admin.dashboard.title')]), admin_dashboard_url
- s.item :settings, safe_join([fa_icon('cogs fw'), t('admin.settings.title')]), edit_admin_settings_url, if: -> { current_user.admin? }, highlights_on: %r{/admin/settings}
- s.item :rules, safe_join([fa_icon('gavel fw'), t('admin.rules.title')]), admin_rules_path, highlights_on: %r{/admin/rules}
- s.item :announcements, safe_join([fa_icon('bullhorn fw'), t('admin.announcements.title')]), admin_announcements_path, highlights_on: %r{/admin/announcements}
- s.item :custom_emojis, safe_join([fa_icon('smile-o fw'), t('admin.custom_emojis.title')]), admin_custom_emojis_url, highlights_on: %r{/admin/custom_emojis}
- s.item :webhooks, safe_join([fa_icon('inbox fw'), t('admin.webhooks.title')]), admin_webhooks_path, highlights_on: %r{/admin/webhooks}
- s.item :relays, safe_join([fa_icon('exchange fw'), t('admin.relays.title')]), admin_relays_url, if: -> { current_user.admin? && !whitelist_mode? }, highlights_on: %r{/admin/relays}
- s.item :sidekiq, safe_join([fa_icon('diamond fw'), 'Sidekiq']), sidekiq_url, link_html: { target: 'sidekiq' }, if: -> { current_user.admin? }
- s.item :pghero, safe_join([fa_icon('database fw'), 'PgHero']), pghero_url, link_html: { target: 'pghero' }, if: -> { current_user.admin? }
+ n.item :admin, safe_join([fa_icon('cogs fw'), t('admin.title')]), nil, if: -> { current_user.can?(:view_dashboard, :manage_settings, :manage_rules, :manage_announcements, :manage_custom_emojis, :manage_webhooks, :manage_federation) } do |s|
+ s.item :dashboard, safe_join([fa_icon('tachometer fw'), t('admin.dashboard.title')]), admin_dashboard_path, if: -> { current_user.can?(:view_dashboard) }
+ s.item :settings, safe_join([fa_icon('cogs fw'), t('admin.settings.title')]), edit_admin_settings_path, if: -> { current_user.can?(:manage_settings) }, highlights_on: %r{/admin/settings}
+ s.item :rules, safe_join([fa_icon('gavel fw'), t('admin.rules.title')]), admin_rules_path, highlights_on: %r{/admin/rules}, if: -> { current_user.can?(:manage_rules) }
+ s.item :roles, safe_join([fa_icon('vcard fw'), t('admin.roles.title')]), admin_roles_path, highlights_on: %r{/admin/roles}, if: -> { current_user.can?(:manage_roles) }
+ s.item :announcements, safe_join([fa_icon('bullhorn fw'), t('admin.announcements.title')]), admin_announcements_path, highlights_on: %r{/admin/announcements}, if: -> { current_user.can?(:manage_announcements) }
+ s.item :custom_emojis, safe_join([fa_icon('smile-o fw'), t('admin.custom_emojis.title')]), admin_custom_emojis_path, highlights_on: %r{/admin/custom_emojis}, if: -> { current_user.can?(:manage_custom_emojis) }
+ s.item :webhooks, safe_join([fa_icon('inbox fw'), t('admin.webhooks.title')]), admin_webhooks_path, highlights_on: %r{/admin/webhooks}, if: -> { current_user.can?(:manage_webhooks) }
+ s.item :relays, safe_join([fa_icon('exchange fw'), t('admin.relays.title')]), admin_relays_path, highlights_on: %r{/admin/relays}, if: -> { !whitelist_mode? && current_user.can?(:manage_federation) }
end
- n.item :logout, safe_join([fa_icon('sign-out fw'), t('auth.logout')]), destroy_user_session_url, link_html: { 'data-method' => 'delete' }
+ n.item :sidekiq, safe_join([fa_icon('diamond fw'), 'Sidekiq']), sidekiq_path, link_html: { target: 'sidekiq' }, if: -> { current_user.can?(:view_devops) }
+ n.item :pghero, safe_join([fa_icon('database fw'), 'PgHero']), pghero_path, link_html: { target: 'pghero' }, if: -> { current_user.can?(:view_devops) }
+ n.item :logout, safe_join([fa_icon('sign-out fw'), t('auth.logout')]), destroy_user_session_path, link_html: { 'data-method' => 'delete' }
end
end
diff --git a/config/roles.yml b/config/roles.yml
new file mode 100644
index 000000000..f443250d1
--- /dev/null
+++ b/config/roles.yml
@@ -0,0 +1,35 @@
+moderator:
+ name: Moderator
+ position: 10
+ permissions:
+ - view_dashboard
+ - view_audit_log
+ - manage_users
+ - manage_reports
+ - manage_taxonomies
+admin:
+ name: Admin
+ position: 100
+ permissions:
+ - view_dashboard
+ - view_audit_log
+ - manage_users
+ - manage_user_access
+ - delete_user_data
+ - manage_reports
+ - manage_taxonomies
+ - manage_federation
+ - manage_settings
+ - manage_blocks
+ - manage_appeals
+ - manage_rules
+ - manage_invites
+ - manage_announcements
+ - manage_custom_emojis
+ - manage_webhooks
+ - manage_roles
+owner:
+ name: Owner
+ position: 1000
+ permissions:
+ - administrator
diff --git a/config/routes.rb b/config/routes.rb
index 4abf55655..177c1cff4 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -10,7 +10,7 @@ Rails.application.routes.draw do
get 'health', to: 'health#show'
- authenticate :user, lambda { |u| u.admin? } do
+ authenticate :user, lambda { |u| u.role&.can?(:view_devops) } do
mount Sidekiq::Web, at: 'sidekiq', as: :sidekiq
mount PgHero::Engine, at: 'pghero', as: :pghero
end
@@ -295,17 +295,11 @@ Rails.application.routes.draw do
post :resend
end
end
-
- resource :role, only: [] do
- member do
- post :promote
- post :demote
- end
- end
end
resources :users, only: [] do
- resource :two_factor_authentication, only: [:destroy]
+ resource :two_factor_authentication, only: [:destroy], controller: 'users/two_factor_authentications'
+ resource :role, only: [:show, :update], controller: 'users/roles'
end
resources :custom_emojis, only: [:index, :new, :create] do
@@ -320,6 +314,7 @@ Rails.application.routes.draw do
end
end
+ resources :roles, except: [:show]
resources :account_moderation_notes, only: [:create, :destroy]
resource :follow_recommendations, only: [:show, :update]
resources :tags, only: [:show, :update]
diff --git a/db/migrate/20220611210335_create_user_roles.rb b/db/migrate/20220611210335_create_user_roles.rb
new file mode 100644
index 000000000..6b7f2b637
--- /dev/null
+++ b/db/migrate/20220611210335_create_user_roles.rb
@@ -0,0 +1,13 @@
+class CreateUserRoles < ActiveRecord::Migration[6.1]
+ def change
+ create_table :user_roles do |t|
+ t.string :name, null: false, default: ''
+ t.string :color, null: false, default: ''
+ t.integer :position, null: false, default: 0
+ t.bigint :permissions, null: false, default: 0
+ t.boolean :highlighted, null: false, default: false
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20220611212541_add_role_id_to_users.rb b/db/migrate/20220611212541_add_role_id_to_users.rb
new file mode 100644
index 000000000..2fda647d4
--- /dev/null
+++ b/db/migrate/20220611212541_add_role_id_to_users.rb
@@ -0,0 +1,8 @@
+class AddRoleIdToUsers < ActiveRecord::Migration[6.1]
+ disable_ddl_transaction!
+
+ def change
+ safety_assured { add_reference :users, :role, foreign_key: { to_table: 'user_roles', on_delete: :nullify }, index: false }
+ add_index :users, :role_id, algorithm: :concurrently, where: 'role_id IS NOT NULL'
+ end
+end
diff --git a/db/post_migrate/20220617202502_migrate_roles.rb b/db/post_migrate/20220617202502_migrate_roles.rb
new file mode 100644
index 000000000..b7a7b2201
--- /dev/null
+++ b/db/post_migrate/20220617202502_migrate_roles.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class MigrateRoles < ActiveRecord::Migration[5.2]
+ disable_ddl_transaction!
+
+ class UserRole < ApplicationRecord; end
+ class User < ApplicationRecord; end
+
+ def up
+ load Rails.root.join('db', 'seeds', '03_roles.rb')
+
+ admin_role = UserRole.find_by(name: 'Admin')
+ moderator_role = UserRole.find_by(name: 'Moderator')
+
+ User.where(admin: true).in_batches.update_all(role_id: admin_role.id)
+ User.where(moderator: true).in_batches.update_all(role_id: moderator_role.id)
+ end
+
+ def down
+ admin_role = UserRole.find_by(name: 'Admin')
+ moderator_role = UserRole.find_by(name: 'Moderator')
+
+ User.where(role_id: admin_role.id).in_batches.update_all(admin: true) if admin_role
+ User.where(role_id: moderator_role.id).in_batches.update_all(moderator: true) if moderator_role
+ end
+end
diff --git a/db/post_migrate/20220704024901_migrate_settings_to_user_roles.rb b/db/post_migrate/20220704024901_migrate_settings_to_user_roles.rb
new file mode 100644
index 000000000..254690cc3
--- /dev/null
+++ b/db/post_migrate/20220704024901_migrate_settings_to_user_roles.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+class MigrateSettingsToUserRoles < ActiveRecord::Migration[6.1]
+ disable_ddl_transaction!
+
+ class UserRole < ApplicationRecord; end
+
+ def up
+ owner_role = UserRole.find_by(name: 'Owner')
+ admin_role = UserRole.find_by(name: 'Admin')
+ moderator_role = UserRole.find_by(name: 'Moderator')
+ everyone_role = UserRole.find_by(id: -99)
+
+ min_invite_role = Setting.min_invite_role
+ show_staff_badge = Setting.show_staff_badge
+
+ if everyone_role
+ everyone_role.permissions &= ~::UserRole::FLAGS[:invite_users] unless min_invite_role == 'user'
+ everyone_role.save
+ end
+
+ if owner_role
+ owner_role.highlighted = show_staff_badge
+ owner_role.save
+ end
+
+ if admin_role
+ admin_role.permissions |= ::UserRole::FLAGS[:invite_users] if %w(admin moderator).include?(min_invite_role)
+ admin_role.highlighted = show_staff_badge
+ admin_role.save
+ end
+
+ if moderator_role
+ moderator_role.permissions |= ::UserRole::FLAGS[:invite_users] if %w(moderator).include?(min_invite_role)
+ moderator_role.highlighted = show_staff_badge
+ moderator_role.save
+ end
+ end
+
+ def down; end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 759dc712b..54966ef64 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2022_06_13_110903) do
+ActiveRecord::Schema.define(version: 2022_07_04_024901) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -968,6 +968,16 @@ ActiveRecord::Schema.define(version: 2022_06_13_110903) do
t.index ["user_id"], name: "index_user_invite_requests_on_user_id"
end
+ create_table "user_roles", force: :cascade do |t|
+ t.string "name", default: "", null: false
+ t.string "color", default: "", null: false
+ t.integer "position", default: 0, null: false
+ t.bigint "permissions", default: 0, null: false
+ t.boolean "highlighted", default: false, null: false
+ t.datetime "created_at", precision: 6, null: false
+ t.datetime "updated_at", precision: 6, null: false
+ end
+
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.datetime "created_at", null: false
@@ -1003,11 +1013,13 @@ ActiveRecord::Schema.define(version: 2022_06_13_110903) do
t.string "webauthn_id"
t.inet "sign_up_ip"
t.boolean "skip_sign_in_token"
+ t.bigint "role_id"
t.index ["account_id"], name: "index_users_on_account_id"
t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
t.index ["created_by_application_id"], name: "index_users_on_created_by_application_id", where: "(created_by_application_id IS NOT NULL)"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, opclass: :text_pattern_ops, where: "(reset_password_token IS NOT NULL)"
+ t.index ["role_id"], name: "index_users_on_role_id", where: "(role_id IS NOT NULL)"
end
create_table "web_push_subscriptions", force: :cascade do |t|
@@ -1159,6 +1171,7 @@ ActiveRecord::Schema.define(version: 2022_06_13_110903) do
add_foreign_key "users", "accounts", name: "fk_50500f500d", on_delete: :cascade
add_foreign_key "users", "invites", on_delete: :nullify
add_foreign_key "users", "oauth_applications", column: "created_by_application_id", on_delete: :nullify
+ add_foreign_key "users", "user_roles", column: "role_id", on_delete: :nullify
add_foreign_key "web_push_subscriptions", "oauth_access_tokens", column: "access_token_id", on_delete: :cascade
add_foreign_key "web_push_subscriptions", "users", on_delete: :cascade
add_foreign_key "web_settings", "users", name: "fk_11910667b2", on_delete: :cascade
diff --git a/db/seeds.rb b/db/seeds.rb
index 0bfb5d0db..1ca300de7 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -1,11 +1,5 @@
-Doorkeeper::Application.create!(name: 'Web', superapp: true, redirect_uri: Doorkeeper.configuration.native_redirect_uri, scopes: 'read write follow push')
+# frozen_string_literal: true
-domain = ENV['LOCAL_DOMAIN'] || Rails.configuration.x.local_domain
-account = Account.find_or_initialize_by(id: -99, actor_type: 'Application', locked: true, username: domain)
-account.save!
-
-if Rails.env.development?
- admin = Account.where(username: 'admin').first_or_initialize(username: 'admin')
- admin.save(validate: false)
- User.where(email: "admin@#{domain}").first_or_initialize(email: "admin@#{domain}", password: 'mastodonadmin', password_confirmation: 'mastodonadmin', confirmed_at: Time.now.utc, admin: true, account: admin, agreement: true, approved: true).save!
+Dir[Rails.root.join('db', 'seeds', '*.rb')].sort.each do |seed|
+ load seed
end
diff --git a/db/seeds/01_web_app.rb b/db/seeds/01_web_app.rb
new file mode 100644
index 000000000..a457a883b
--- /dev/null
+++ b/db/seeds/01_web_app.rb
@@ -0,0 +1 @@
+Doorkeeper::Application.create_with(name: 'Web', redirect_uri: Doorkeeper.configuration.native_redirect_uri, scopes: 'read write follow push').find_or_create_by(superapp: true)
diff --git a/db/seeds/02_instance_actor.rb b/db/seeds/02_instance_actor.rb
new file mode 100644
index 000000000..39186b273
--- /dev/null
+++ b/db/seeds/02_instance_actor.rb
@@ -0,0 +1 @@
+Account.create_with(actor_type: 'Application', locked: true, username: ENV['LOCAL_DOMAIN'] || Rails.configuration.x.local_domain).find_or_create_by(id: -99)
diff --git a/db/seeds/03_roles.rb b/db/seeds/03_roles.rb
new file mode 100644
index 000000000..7fedf0f71
--- /dev/null
+++ b/db/seeds/03_roles.rb
@@ -0,0 +1,9 @@
+# Pre-create base role
+UserRole.everyone
+
+# Create default roles defined in config file
+default_roles = YAML.load_file(Rails.root.join('config', 'roles.yml'))
+
+default_roles.each do |_, config|
+ UserRole.create_with(position: config['position'], permissions_as_keys: config['permissions'], highlighted: true).find_or_create_by(name: config['name'])
+end
diff --git a/db/seeds/04_admin.rb b/db/seeds/04_admin.rb
new file mode 100644
index 000000000..a67040e4e
--- /dev/null
+++ b/db/seeds/04_admin.rb
@@ -0,0 +1,8 @@
+if Rails.env.development?
+ domain = ENV['LOCAL_DOMAIN'] || Rails.configuration.x.local_domain
+
+ admin = Account.where(username: 'admin').first_or_initialize(username: 'admin')
+ admin.save(validate: false)
+
+ User.where(email: "admin@#{domain}").first_or_initialize(email: "admin@#{domain}", password: 'mastodonadmin', password_confirmation: 'mastodonadmin', confirmed_at: Time.now.utc, role: UserRole.find_by(name: 'Owner'), account: admin, agreement: true, approved: true).save!
+end
diff --git a/lib/mastodon/accounts_cli.rb b/lib/mastodon/accounts_cli.rb
index 7256d1da9..29c934453 100644
--- a/lib/mastodon/accounts_cli.rb
+++ b/lib/mastodon/accounts_cli.rb
@@ -54,7 +54,7 @@ module Mastodon
option :email, required: true
option :confirmed, type: :boolean
- option :role, default: 'user', enum: %w(user moderator admin)
+ option :role
option :reattach, type: :boolean
option :force, type: :boolean
desc 'create USERNAME', 'Create a new user'
@@ -65,8 +65,7 @@ module Mastodon
With the --confirmed option, the confirmation e-mail will
be skipped and the account will be active straight away.
- With the --role option one of "user", "admin" or "moderator"
- can be supplied. Defaults to "user"
+ With the --role option, the role can be supplied.
With the --reattach option, the new user will be reattached
to a given existing username of an old account. If the old
@@ -75,9 +74,22 @@ module Mastodon
username to the new account anyway.
LONG_DESC
def create(username)
+ role_id = nil
+
+ if options[:role]
+ role = UserRole.find_by(name: options[:role])
+
+ if role.nil?
+ say('Cannot find user role with that name', :red)
+ exit(1)
+ end
+
+ role_id = role.id
+ end
+
account = Account.new(username: username)
password = SecureRandom.hex
- user = User.new(email: options[:email], password: password, agreement: true, approved: true, admin: options[:role] == 'admin', moderator: options[:role] == 'moderator', confirmed_at: options[:confirmed] ? Time.now.utc : nil, bypass_invite_request_check: true)
+ user = User.new(email: options[:email], password: password, agreement: true, approved: true, role_id: role_id, confirmed_at: options[:confirmed] ? Time.now.utc : nil, bypass_invite_request_check: true)
if options[:reattach]
account = Account.find_local(username) || Account.new(username: username)
@@ -106,14 +118,14 @@ module Mastodon
user.errors.to_h.each do |key, error|
say('Failure/Error: ', :red)
say(key)
- say(' ' + error, :red)
+ say(" #{error}", :red)
end
exit(1)
end
end
- option :role, enum: %w(user moderator admin)
+ option :role
option :email
option :confirm, type: :boolean
option :enable, type: :boolean
@@ -125,8 +137,7 @@ module Mastodon
long_desc <<-LONG_DESC
Modify a user account.
- With the --role option, update the user's role to one of "user",
- "moderator" or "admin".
+ With the --role option, update the user's role.
With the --email option, update the user's e-mail address. With
the --confirm option, mark the user's e-mail as confirmed.
@@ -152,8 +163,14 @@ module Mastodon
end
if options[:role]
- user.admin = options[:role] == 'admin'
- user.moderator = options[:role] == 'moderator'
+ role = UserRole.find_by(name: options[:role])
+
+ if role.nil?
+ say('Cannot find user role with that name', :red)
+ exit(1)
+ end
+
+ user.role_id = role.id
end
password = SecureRandom.hex if options[:reset_password]
@@ -172,7 +189,7 @@ module Mastodon
user.errors.to_h.each do |key, error|
say('Failure/Error: ', :red)
say(key)
- say(' ' + error, :red)
+ say(" #{error}", :red)
end
exit(1)
@@ -319,7 +336,7 @@ module Mastodon
unless skip_domains.empty?
say('The following domains were not available during the check:', :yellow)
- skip_domains.each { |domain| say(' ' + domain) }
+ skip_domains.each { |domain| say(" #{domain}") }
end
end
diff --git a/lib/simple_navigation/item_extensions.rb b/lib/simple_navigation/item_extensions.rb
new file mode 100644
index 000000000..28af37a18
--- /dev/null
+++ b/lib/simple_navigation/item_extensions.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module SimpleNavigation
+ module ItemExtensions
+ def url
+ if @url.nil? && @sub_navigation
+ @sub_navigation.items.first.url
+ else
+ @url
+ end
+ end
+ end
+end
+
+SimpleNavigation::Item.prepend(SimpleNavigation::ItemExtensions)
diff --git a/spec/controllers/admin/account_moderation_notes_controller_spec.rb b/spec/controllers/admin/account_moderation_notes_controller_spec.rb
index 410ce6543..d3f3263f8 100644
--- a/spec/controllers/admin/account_moderation_notes_controller_spec.rb
+++ b/spec/controllers/admin/account_moderation_notes_controller_spec.rb
@@ -3,7 +3,7 @@ require 'rails_helper'
RSpec.describe Admin::AccountModerationNotesController, type: :controller do
render_views
- let(:user) { Fabricate(:user, admin: true) }
+ let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
let(:target_account) { Fabricate(:account) }
before do
diff --git a/spec/controllers/admin/accounts_controller_spec.rb b/spec/controllers/admin/accounts_controller_spec.rb
index 1779fb7c0..1bd51a0c8 100644
--- a/spec/controllers/admin/accounts_controller_spec.rb
+++ b/spec/controllers/admin/accounts_controller_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Admin::AccountsController, type: :controller do
before { sign_in current_user, scope: :user }
describe 'GET #index' do
- let(:current_user) { Fabricate(:user, admin: true) }
+ let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
around do |example|
default_per_page = Account.default_per_page
@@ -60,7 +60,7 @@ RSpec.describe Admin::AccountsController, type: :controller do
end
describe 'GET #show' do
- let(:current_user) { Fabricate(:user, admin: true) }
+ let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
let(:account) { Fabricate(:account) }
it 'returns http success' do
@@ -72,15 +72,15 @@ RSpec.describe Admin::AccountsController, type: :controller do
describe 'POST #memorialize' do
subject { post :memorialize, params: { id: account.id } }
- let(:current_user) { Fabricate(:user, admin: current_user_admin) }
+ let(:current_user) { Fabricate(:user, role: current_role) }
let(:account) { user.account }
- let(:user) { Fabricate(:user, admin: target_user_admin) }
+ let(:user) { Fabricate(:user, role: target_role) }
context 'when user is admin' do
- let(:current_user_admin) { true }
+ let(:current_role) { UserRole.find_by(name: 'Admin') }
context 'when target user is admin' do
- let(:target_user_admin) { true }
+ let(:target_role) { UserRole.find_by(name: 'Admin') }
it 'fails to memorialize account' do
is_expected.to have_http_status :forbidden
@@ -89,7 +89,7 @@ RSpec.describe Admin::AccountsController, type: :controller do
end
context 'when target user is not admin' do
- let(:target_user_admin) { false }
+ let(:target_role) { UserRole.find_by(name: 'Moderator') }
it 'succeeds in memorializing account' do
is_expected.to redirect_to admin_account_path(account.id)
@@ -99,10 +99,10 @@ RSpec.describe Admin::AccountsController, type: :controller do
end
context 'when user is not admin' do
- let(:current_user_admin) { false }
+ let(:current_role) { UserRole.find_by(name: 'Moderator') }
context 'when target user is admin' do
- let(:target_user_admin) { true }
+ let(:target_role) { UserRole.find_by(name: 'Admin') }
it 'fails to memorialize account' do
is_expected.to have_http_status :forbidden
@@ -111,7 +111,7 @@ RSpec.describe Admin::AccountsController, type: :controller do
end
context 'when target user is not admin' do
- let(:target_user_admin) { false }
+ let(:target_role) { UserRole.find_by(name: 'Moderator') }
it 'fails to memorialize account' do
is_expected.to have_http_status :forbidden
@@ -124,12 +124,12 @@ RSpec.describe Admin::AccountsController, type: :controller do
describe 'POST #enable' do
subject { post :enable, params: { id: account.id } }
- let(:current_user) { Fabricate(:user, admin: admin) }
+ let(:current_user) { Fabricate(:user, role: role) }
let(:account) { user.account }
let(:user) { Fabricate(:user, disabled: true) }
context 'when user is admin' do
- let(:admin) { true }
+ let(:role) { UserRole.find_by(name: 'Admin') }
it 'succeeds in enabling account' do
is_expected.to redirect_to admin_account_path(account.id)
@@ -138,7 +138,7 @@ RSpec.describe Admin::AccountsController, type: :controller do
end
context 'when user is not admin' do
- let(:admin) { false }
+ let(:role) { UserRole.everyone }
it 'fails to enable account' do
is_expected.to have_http_status :forbidden
@@ -150,19 +150,23 @@ RSpec.describe Admin::AccountsController, type: :controller do
describe 'POST #redownload' do
subject { post :redownload, params: { id: account.id } }
- let(:current_user) { Fabricate(:user, admin: admin) }
- let(:account) { Fabricate(:account) }
+ let(:current_user) { Fabricate(:user, role: role) }
+ let(:account) { Fabricate(:account, domain: 'example.com') }
+
+ before do
+ allow_any_instance_of(ResolveAccountService).to receive(:call)
+ end
context 'when user is admin' do
- let(:admin) { true }
+ let(:role) { UserRole.find_by(name: 'Admin') }
- it 'succeeds in redownloadin' do
+ it 'succeeds in redownloading' do
is_expected.to redirect_to admin_account_path(account.id)
end
end
context 'when user is not admin' do
- let(:admin) { false }
+ let(:role) { UserRole.everyone }
it 'fails to redownload' do
is_expected.to have_http_status :forbidden
@@ -173,11 +177,11 @@ RSpec.describe Admin::AccountsController, type: :controller do
describe 'POST #remove_avatar' do
subject { post :remove_avatar, params: { id: account.id } }
- let(:current_user) { Fabricate(:user, admin: admin) }
+ let(:current_user) { Fabricate(:user, role: role) }
let(:account) { Fabricate(:account) }
context 'when user is admin' do
- let(:admin) { true }
+ let(:role) { UserRole.find_by(name: 'Admin') }
it 'succeeds in removing avatar' do
is_expected.to redirect_to admin_account_path(account.id)
@@ -185,7 +189,7 @@ RSpec.describe Admin::AccountsController, type: :controller do
end
context 'when user is not admin' do
- let(:admin) { false }
+ let(:role) { UserRole.everyone }
it 'fails to remove avatar' do
is_expected.to have_http_status :forbidden
@@ -196,12 +200,12 @@ RSpec.describe Admin::AccountsController, type: :controller do
describe 'POST #unblock_email' do
subject { post :unblock_email, params: { id: account.id } }
- let(:current_user) { Fabricate(:user, admin: admin) }
+ let(:current_user) { Fabricate(:user, role: role) }
let(:account) { Fabricate(:account, suspended: true) }
let!(:email_block) { Fabricate(:canonical_email_block, reference_account: account) }
context 'when user is admin' do
- let(:admin) { true }
+ let(:role) { UserRole.find_by(name: 'Admin') }
it 'succeeds in removing email blocks' do
expect { subject }.to change { CanonicalEmailBlock.where(reference_account: account).count }.from(1).to(0)
@@ -214,7 +218,7 @@ RSpec.describe Admin::AccountsController, type: :controller do
end
context 'when user is not admin' do
- let(:admin) { false }
+ let(:role) { UserRole.everyone }
it 'fails to remove avatar' do
subject
diff --git a/spec/controllers/admin/action_logs_controller_spec.rb b/spec/controllers/admin/action_logs_controller_spec.rb
index 4720ed2e2..c1957258f 100644
--- a/spec/controllers/admin/action_logs_controller_spec.rb
+++ b/spec/controllers/admin/action_logs_controller_spec.rb
@@ -5,7 +5,7 @@ require 'rails_helper'
describe Admin::ActionLogsController, type: :controller do
describe 'GET #index' do
it 'returns 200' do
- sign_in Fabricate(:user, admin: true)
+ sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin'))
get :index, params: { page: 1 }
expect(response).to have_http_status(200)
diff --git a/spec/controllers/admin/base_controller_spec.rb b/spec/controllers/admin/base_controller_spec.rb
index 9ac833623..44be91951 100644
--- a/spec/controllers/admin/base_controller_spec.rb
+++ b/spec/controllers/admin/base_controller_spec.rb
@@ -5,13 +5,14 @@ require 'rails_helper'
describe Admin::BaseController, type: :controller do
controller do
def success
+ authorize :dashboard, :index?
render 'admin/reports/show'
end
end
it 'requires administrator or moderator' do
routes.draw { get 'success' => 'admin/base#success' }
- sign_in(Fabricate(:user, admin: false, moderator: false))
+ sign_in(Fabricate(:user))
get :success
expect(response).to have_http_status(:forbidden)
@@ -19,14 +20,14 @@ describe Admin::BaseController, type: :controller do
it 'renders admin layout as a moderator' do
routes.draw { get 'success' => 'admin/base#success' }
- sign_in(Fabricate(:user, moderator: true))
+ sign_in(Fabricate(:user, role: UserRole.find_by(name: 'Moderator')))
get :success
expect(response).to render_template layout: 'admin'
end
it 'renders admin layout as an admin' do
routes.draw { get 'success' => 'admin/base#success' }
- sign_in(Fabricate(:user, admin: true))
+ sign_in(Fabricate(:user, role: UserRole.find_by(name: 'Admin')))
get :success
expect(response).to render_template layout: 'admin'
end
diff --git a/spec/controllers/admin/change_email_controller_spec.rb b/spec/controllers/admin/change_email_controller_spec.rb
index e7f3f7c97..cf8a27d39 100644
--- a/spec/controllers/admin/change_email_controller_spec.rb
+++ b/spec/controllers/admin/change_email_controller_spec.rb
@@ -3,7 +3,7 @@ require 'rails_helper'
RSpec.describe Admin::ChangeEmailsController, type: :controller do
render_views
- let(:admin) { Fabricate(:user, admin: true) }
+ let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
sign_in admin
diff --git a/spec/controllers/admin/confirmations_controller_spec.rb b/spec/controllers/admin/confirmations_controller_spec.rb
index 5b4f7e925..6268903c4 100644
--- a/spec/controllers/admin/confirmations_controller_spec.rb
+++ b/spec/controllers/admin/confirmations_controller_spec.rb
@@ -4,7 +4,7 @@ RSpec.describe Admin::ConfirmationsController, type: :controller do
render_views
before do
- sign_in Fabricate(:user, admin: true), scope: :user
+ sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin')), scope: :user
end
describe 'POST #create' do
diff --git a/spec/controllers/admin/custom_emojis_controller_spec.rb b/spec/controllers/admin/custom_emojis_controller_spec.rb
index a8d96948c..06cd0c22d 100644
--- a/spec/controllers/admin/custom_emojis_controller_spec.rb
+++ b/spec/controllers/admin/custom_emojis_controller_spec.rb
@@ -3,7 +3,7 @@ require 'rails_helper'
describe Admin::CustomEmojisController do
render_views
- let(:user) { Fabricate(:user, admin: true) }
+ let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
sign_in user, scope: :user
diff --git a/spec/controllers/admin/dashboard_controller_spec.rb b/spec/controllers/admin/dashboard_controller_spec.rb
index 7824854f9..6231a09a2 100644
--- a/spec/controllers/admin/dashboard_controller_spec.rb
+++ b/spec/controllers/admin/dashboard_controller_spec.rb
@@ -12,7 +12,7 @@ describe Admin::DashboardController, type: :controller do
Admin::SystemCheck::Message.new(:rules_check, nil, admin_rules_path),
Admin::SystemCheck::Message.new(:sidekiq_process_check, 'foo, bar'),
])
- sign_in Fabricate(:user, admin: true)
+ sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin'))
end
it 'returns 200' do
diff --git a/spec/controllers/admin/disputes/appeals_controller_spec.rb b/spec/controllers/admin/disputes/appeals_controller_spec.rb
index 6a06f9406..712657791 100644
--- a/spec/controllers/admin/disputes/appeals_controller_spec.rb
+++ b/spec/controllers/admin/disputes/appeals_controller_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Admin::Disputes::AppealsController, type: :controller do
end
describe 'POST #approve' do
- let(:current_user) { Fabricate(:user, admin: true) }
+ let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
allow(UserMailer).to receive(:appeal_approved).and_return(double('email', deliver_later: nil))
@@ -35,7 +35,7 @@ RSpec.describe Admin::Disputes::AppealsController, type: :controller do
end
describe 'POST #reject' do
- let(:current_user) { Fabricate(:user, admin: true) }
+ let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
allow(UserMailer).to receive(:appeal_rejected).and_return(double('email', deliver_later: nil))
diff --git a/spec/controllers/admin/domain_blocks_controller_spec.rb b/spec/controllers/admin/domain_blocks_controller_spec.rb
index ecc79292b..5c2dcd268 100644
--- a/spec/controllers/admin/domain_blocks_controller_spec.rb
+++ b/spec/controllers/admin/domain_blocks_controller_spec.rb
@@ -4,7 +4,7 @@ RSpec.describe Admin::DomainBlocksController, type: :controller do
render_views
before do
- sign_in Fabricate(:user, admin: true), scope: :user
+ sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin')), scope: :user
end
describe 'GET #new' do
diff --git a/spec/controllers/admin/email_domain_blocks_controller_spec.rb b/spec/controllers/admin/email_domain_blocks_controller_spec.rb
index cf194579d..e9cef4a94 100644
--- a/spec/controllers/admin/email_domain_blocks_controller_spec.rb
+++ b/spec/controllers/admin/email_domain_blocks_controller_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Admin::EmailDomainBlocksController, type: :controller do
render_views
before do
- sign_in Fabricate(:user, admin: true), scope: :user
+ sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin')), scope: :user
end
describe 'GET #index' do
diff --git a/spec/controllers/admin/instances_controller_spec.rb b/spec/controllers/admin/instances_controller_spec.rb
index 53427b874..337f7a80c 100644
--- a/spec/controllers/admin/instances_controller_spec.rb
+++ b/spec/controllers/admin/instances_controller_spec.rb
@@ -3,7 +3,7 @@ require 'rails_helper'
RSpec.describe Admin::InstancesController, type: :controller do
render_views
- let(:current_user) { Fabricate(:user, admin: true) }
+ let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
let!(:account) { Fabricate(:account, domain: 'popular') }
let!(:account2) { Fabricate(:account, domain: 'popular') }
@@ -35,11 +35,11 @@ RSpec.describe Admin::InstancesController, type: :controller do
describe 'DELETE #destroy' do
subject { delete :destroy, params: { id: Instance.first.id } }
- let(:current_user) { Fabricate(:user, admin: admin) }
+ let(:current_user) { Fabricate(:user, role: role) }
let(:account) { Fabricate(:account) }
context 'when user is admin' do
- let(:admin) { true }
+ let(:role) { UserRole.find_by(name: 'Admin') }
it 'succeeds in purging instance' do
is_expected.to redirect_to admin_instances_path
@@ -47,7 +47,7 @@ RSpec.describe Admin::InstancesController, type: :controller do
end
context 'when user is not admin' do
- let(:admin) { false }
+ let(:role) { nil }
it 'fails to purge instance' do
is_expected.to have_http_status :forbidden
diff --git a/spec/controllers/admin/invites_controller_spec.rb b/spec/controllers/admin/invites_controller_spec.rb
index 449a699e4..1fb488742 100644
--- a/spec/controllers/admin/invites_controller_spec.rb
+++ b/spec/controllers/admin/invites_controller_spec.rb
@@ -5,7 +5,7 @@ require 'rails_helper'
describe Admin::InvitesController do
render_views
- let(:user) { Fabricate(:user, admin: true) }
+ let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
sign_in user, scope: :user
diff --git a/spec/controllers/admin/report_notes_controller_spec.rb b/spec/controllers/admin/report_notes_controller_spec.rb
index c0013f41a..fa7572d18 100644
--- a/spec/controllers/admin/report_notes_controller_spec.rb
+++ b/spec/controllers/admin/report_notes_controller_spec.rb
@@ -3,7 +3,7 @@ require 'rails_helper'
describe Admin::ReportNotesController do
render_views
- let(:user) { Fabricate(:user, admin: true) }
+ let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
sign_in user, scope: :user
diff --git a/spec/controllers/admin/reports_controller_spec.rb b/spec/controllers/admin/reports_controller_spec.rb
index d421f0739..4cd1524bf 100644
--- a/spec/controllers/admin/reports_controller_spec.rb
+++ b/spec/controllers/admin/reports_controller_spec.rb
@@ -3,7 +3,7 @@ require 'rails_helper'
describe Admin::ReportsController do
render_views
- let(:user) { Fabricate(:user, admin: true) }
+ let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
before do
sign_in user, scope: :user
end
diff --git a/spec/controllers/admin/resets_controller_spec.rb b/spec/controllers/admin/resets_controller_spec.rb
index 28510b5af..aeb172318 100644
--- a/spec/controllers/admin/resets_controller_spec.rb
+++ b/spec/controllers/admin/resets_controller_spec.rb
@@ -5,7 +5,7 @@ describe Admin::ResetsController do
let(:account) { Fabricate(:account) }
before do
- sign_in Fabricate(:user, admin: true), scope: :user
+ sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin')), scope: :user
end
describe 'POST #create' do
diff --git a/spec/controllers/admin/roles_controller_spec.rb b/spec/controllers/admin/roles_controller_spec.rb
index 8e0de73cb..8ff891205 100644
--- a/spec/controllers/admin/roles_controller_spec.rb
+++ b/spec/controllers/admin/roles_controller_spec.rb
@@ -3,31 +3,247 @@ require 'rails_helper'
describe Admin::RolesController do
render_views
- let(:admin) { Fabricate(:user, admin: true) }
+ let(:permissions) { UserRole::Flags::NONE }
+ let(:current_role) { UserRole.create(name: 'Foo', permissions: permissions, position: 10) }
+ let(:current_user) { Fabricate(:user, role: current_role) }
before do
- sign_in admin, scope: :user
+ sign_in current_user, scope: :user
end
- describe 'POST #promote' do
- subject { post :promote, params: { account_id: user.account_id } }
+ describe 'GET #index' do
+ before do
+ get :index
+ end
- let(:user) { Fabricate(:user, moderator: false, admin: false) }
+ context 'when user does not have permission to manage roles' do
+ it 'returns http forbidden' do
+ expect(response).to have_http_status(:forbidden)
+ end
+ end
- it 'promotes user' do
- expect(subject).to redirect_to admin_account_path(user.account_id)
- expect(user.reload).to be_moderator
+ context 'when user has permission to manage roles' do
+ let(:permissions) { UserRole::FLAGS[:manage_roles] }
+
+ it 'returns http success' do
+ expect(response).to have_http_status(:success)
+ end
end
end
- describe 'POST #demote' do
- subject { post :demote, params: { account_id: user.account_id } }
+ describe 'GET #new' do
+ before do
+ get :new
+ end
- let(:user) { Fabricate(:user, moderator: true, admin: false) }
+ context 'when user does not have permission to manage roles' do
+ it 'returns http forbidden' do
+ expect(response).to have_http_status(:forbidden)
+ end
+ end
- it 'demotes user' do
- expect(subject).to redirect_to admin_account_path(user.account_id)
- expect(user.reload).not_to be_moderator
+ context 'when user has permission to manage roles' do
+ let(:permissions) { UserRole::FLAGS[:manage_roles] }
+
+ it 'returns http success' do
+ expect(response).to have_http_status(:success)
+ end
+ end
+ end
+
+ describe 'POST #create' do
+ let(:selected_position) { 1 }
+ let(:selected_permissions_as_keys) { %w(manage_roles) }
+
+ before do
+ post :create, params: { user_role: { name: 'Bar', position: selected_position, permissions_as_keys: selected_permissions_as_keys } }
+ end
+
+ context 'when user has permission to manage roles' do
+ let(:permissions) { UserRole::FLAGS[:manage_roles] }
+
+ context 'when new role\'s does not elevate above the user\'s role' do
+ let(:selected_position) { 1 }
+ let(:selected_permissions_as_keys) { %w(manage_roles) }
+
+ it 'redirects to roles page' do
+ expect(response).to redirect_to(admin_roles_path)
+ end
+
+ it 'creates new role' do
+ expect(UserRole.find_by(name: 'Bar')).to_not be_nil
+ end
+ end
+
+ context 'when new role\'s position is higher than user\'s role' do
+ let(:selected_position) { 100 }
+ let(:selected_permissions_as_keys) { %w(manage_roles) }
+
+ it 'renders new template' do
+ expect(response).to render_template(:new)
+ end
+
+ it 'does not create new role' do
+ expect(UserRole.find_by(name: 'Bar')).to be_nil
+ end
+ end
+
+ context 'when new role has permissions the user does not have' do
+ let(:selected_position) { 1 }
+ let(:selected_permissions_as_keys) { %w(manage_roles manage_users manage_reports) }
+
+ it 'renders new template' do
+ expect(response).to render_template(:new)
+ end
+
+ it 'does not create new role' do
+ expect(UserRole.find_by(name: 'Bar')).to be_nil
+ end
+ end
+
+ context 'when user has administrator permission' do
+ let(:permissions) { UserRole::FLAGS[:administrator] }
+
+ let(:selected_position) { 1 }
+ let(:selected_permissions_as_keys) { %w(manage_roles manage_users manage_reports) }
+
+ it 'redirects to roles page' do
+ expect(response).to redirect_to(admin_roles_path)
+ end
+
+ it 'creates new role' do
+ expect(UserRole.find_by(name: 'Bar')).to_not be_nil
+ end
+ end
+ end
+ end
+
+ describe 'GET #edit' do
+ let(:role_position) { 8 }
+ let(:role) { UserRole.create(name: 'Bar', permissions: UserRole::FLAGS[:manage_users], position: role_position) }
+
+ before do
+ get :edit, params: { id: role.id }
+ end
+
+ context 'when user does not have permission to manage roles' do
+ it 'returns http forbidden' do
+ expect(response).to have_http_status(:forbidden)
+ end
+ end
+
+ context 'when user has permission to manage roles' do
+ let(:permissions) { UserRole::FLAGS[:manage_roles] }
+
+ context 'when user outranks the role' do
+ it 'returns http success' do
+ expect(response).to have_http_status(:success)
+ end
+ end
+
+ context 'when role outranks user' do
+ let(:role_position) { current_role.position + 1 }
+
+ it 'returns http forbidden' do
+ expect(response).to have_http_status(:forbidden)
+ end
+ end
+ end
+ end
+
+ describe 'PUT #update' do
+ let(:role_position) { 8 }
+ let(:role_permissions) { UserRole::FLAGS[:manage_users] }
+ let(:role) { UserRole.create(name: 'Bar', permissions: role_permissions, position: role_position) }
+
+ let(:selected_position) { 8 }
+ let(:selected_permissions_as_keys) { %w(manage_users) }
+
+ before do
+ put :update, params: { id: role.id, user_role: { name: 'Baz', position: selected_position, permissions_as_keys: selected_permissions_as_keys } }
+ end
+
+ context 'when user does not have permission to manage roles' do
+ it 'returns http forbidden' do
+ expect(response).to have_http_status(:forbidden)
+ end
+
+ it 'does not update the role' do
+ expect(role.reload.name).to eq 'Bar'
+ end
+ end
+
+ context 'when user has permission to manage roles' do
+ let(:permissions) { UserRole::FLAGS[:manage_roles] }
+
+ context 'when role has permissions the user doesn\'t' do
+ it 'renders edit template' do
+ expect(response).to render_template(:edit)
+ end
+
+ it 'does not update the role' do
+ expect(role.reload.name).to eq 'Bar'
+ end
+ end
+
+ context 'when user has all permissions of the role' do
+ let(:permissions) { UserRole::FLAGS[:manage_roles] | UserRole::FLAGS[:manage_users] }
+
+ context 'when user outranks the role' do
+ it 'redirects to roles page' do
+ expect(response).to redirect_to(admin_roles_path)
+ end
+
+ it 'updates the role' do
+ expect(role.reload.name).to eq 'Baz'
+ end
+ end
+
+ context 'when role outranks user' do
+ let(:role_position) { current_role.position + 1 }
+
+ it 'returns http forbidden' do
+ expect(response).to have_http_status(:forbidden)
+ end
+
+ it 'does not update the role' do
+ expect(role.reload.name).to eq 'Bar'
+ end
+ end
+ end
+ end
+ end
+
+ describe 'DELETE #destroy' do
+ let(:role_position) { 8 }
+ let(:role) { UserRole.create(name: 'Bar', permissions: UserRole::FLAGS[:manage_users], position: role_position) }
+
+ before do
+ delete :destroy, params: { id: role.id }
+ end
+
+ context 'when user does not have permission to manage roles' do
+ it 'returns http forbidden' do
+ expect(response).to have_http_status(:forbidden)
+ end
+ end
+
+ context 'when user has permission to manage roles' do
+ let(:permissions) { UserRole::FLAGS[:manage_roles] }
+
+ context 'when user outranks the role' do
+ it 'redirects to roles page' do
+ expect(response).to redirect_to(admin_roles_path)
+ end
+ end
+
+ context 'when role outranks user' do
+ let(:role_position) { current_role.position + 1 }
+
+ it 'returns http forbidden' do
+ expect(response).to have_http_status(:forbidden)
+ end
+ end
end
end
end
diff --git a/spec/controllers/admin/settings_controller_spec.rb b/spec/controllers/admin/settings_controller_spec.rb
index 6cf0ee20a..46749f76c 100644
--- a/spec/controllers/admin/settings_controller_spec.rb
+++ b/spec/controllers/admin/settings_controller_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Admin::SettingsController, type: :controller do
describe 'When signed in as an admin' do
before do
- sign_in Fabricate(:user, admin: true), scope: :user
+ sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin')), scope: :user
end
describe 'GET #edit' do
diff --git a/spec/controllers/admin/statuses_controller_spec.rb b/spec/controllers/admin/statuses_controller_spec.rb
index de32fd18e..227688e23 100644
--- a/spec/controllers/admin/statuses_controller_spec.rb
+++ b/spec/controllers/admin/statuses_controller_spec.rb
@@ -3,7 +3,7 @@ require 'rails_helper'
describe Admin::StatusesController do
render_views
- let(:user) { Fabricate(:user, admin: true) }
+ let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
let(:account) { Fabricate(:account) }
let!(:status) { Fabricate(:status, account: account) }
let(:media_attached_status) { Fabricate(:status, account: account, sensitive: !sensitive) }
diff --git a/spec/controllers/admin/tags_controller_spec.rb b/spec/controllers/admin/tags_controller_spec.rb
index 85c801a9c..52fd09eb1 100644
--- a/spec/controllers/admin/tags_controller_spec.rb
+++ b/spec/controllers/admin/tags_controller_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Admin::TagsController, type: :controller do
render_views
before do
- sign_in Fabricate(:user, admin: true)
+ sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin'))
end
describe 'GET #show' do
diff --git a/spec/controllers/admin/users/roles_controller.rb b/spec/controllers/admin/users/roles_controller.rb
new file mode 100644
index 000000000..bd6a3fa67
--- /dev/null
+++ b/spec/controllers/admin/users/roles_controller.rb
@@ -0,0 +1,81 @@
+require 'rails_helper'
+
+describe Admin::Users::RolesController do
+ render_views
+
+ let(:current_role) { UserRole.create(name: 'Foo', permissions: UserRole::FLAGS[:manage_roles], position: 10) }
+ let(:current_user) { Fabricate(:user, role: current_role) }
+
+ let(:previous_role) { nil }
+ let(:user) { Fabricate(:user, role: previous_role) }
+
+ before do
+ sign_in current_user, scope: :user
+ end
+
+ describe 'GET #show' do
+ before do
+ get :show, params: { user_id: user.id }
+ end
+
+ it 'returns http success' do
+ expect(response).to have_http_status(:success)
+ end
+
+ context 'when target user is higher ranked than current user' do
+ let(:previous_role) { UserRole.create(name: 'Baz', permissions: UserRole::FLAGS[:administrator], position: 100) }
+
+ it 'returns http forbidden' do
+ expect(response).to have_http_status(:forbidden)
+ end
+ end
+ end
+
+ describe 'PUT #update' do
+ let(:selected_role) { UserRole.create(name: 'Bar', permissions: permissions, position: position) }
+
+ before do
+ put :update, params: { user_id: user.id, user: { role_id: selected_role.id } }
+ end
+
+ context do
+ let(:permissions) { UserRole::FLAGS[:manage_roles] }
+ let(:position) { 1 }
+
+ it 'updates user role' do
+ expect(user.reload.role_id).to eq selected_role&.id
+ end
+
+ it 'redirects back to account page' do
+ expect(response).to redirect_to(admin_account_path(user.account_id))
+ end
+ end
+
+ context 'when selected role has higher position than current user\'s role' do
+ let(:permissions) { UserRole::FLAGS[:administrator] }
+ let(:position) { 100 }
+
+ it 'does not update user role' do
+ expect(user.reload.role_id).to eq previous_role&.id
+ end
+
+ it 'renders edit form' do
+ expect(response).to render_template(:show)
+ end
+ end
+
+ context 'when target user is higher ranked than current user' do
+ let(:previous_role) { UserRole.create(name: 'Baz', permissions: UserRole::FLAGS[:administrator], position: 100) }
+ let(:permissions) { UserRole::FLAGS[:manage_roles] }
+ let(:position) { 1 }
+
+ it 'does not update user role' do
+ expect(user.reload.role_id).to eq previous_role&.id
+ end
+
+ it 'returns http forbidden' do
+ expect(response).to have_http_status(:forbidden)
+ end
+ end
+ end
+end
diff --git a/spec/controllers/admin/two_factor_authentications_controller_spec.rb b/spec/controllers/admin/users/two_factor_authentications_controller_spec.rb
similarity index 90%
rename from spec/controllers/admin/two_factor_authentications_controller_spec.rb
rename to spec/controllers/admin/users/two_factor_authentications_controller_spec.rb
index c65095729..e56264ef6 100644
--- a/spec/controllers/admin/two_factor_authentications_controller_spec.rb
+++ b/spec/controllers/admin/users/two_factor_authentications_controller_spec.rb
@@ -1,12 +1,13 @@
require 'rails_helper'
require 'webauthn/fake_client'
-describe Admin::TwoFactorAuthenticationsController do
+describe Admin::Users::TwoFactorAuthenticationsController do
render_views
let(:user) { Fabricate(:user) }
+
before do
- sign_in Fabricate(:user, admin: true), scope: :user
+ sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin')), scope: :user
end
describe 'DELETE #destroy' do
diff --git a/spec/controllers/api/v1/admin/account_actions_controller_spec.rb b/spec/controllers/api/v1/admin/account_actions_controller_spec.rb
index 601290b82..199395f55 100644
--- a/spec/controllers/api/v1/admin/account_actions_controller_spec.rb
+++ b/spec/controllers/api/v1/admin/account_actions_controller_spec.rb
@@ -3,7 +3,7 @@ require 'rails_helper'
RSpec.describe Api::V1::Admin::AccountActionsController, type: :controller do
render_views
- let(:role) { 'moderator' }
+ let(:role) { UserRole.find_by(name: 'Moderator') }
let(:user) { Fabricate(:user, role: role) }
let(:scopes) { 'admin:read admin:write' }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
@@ -22,7 +22,7 @@ RSpec.describe Api::V1::Admin::AccountActionsController, type: :controller do
end
shared_examples 'forbidden for wrong role' do |wrong_role|
- let(:role) { wrong_role }
+ let(:role) { UserRole.find_by(name: wrong_role) }
it 'returns http forbidden' do
expect(response).to have_http_status(403)
@@ -35,7 +35,7 @@ RSpec.describe Api::V1::Admin::AccountActionsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
+ it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
expect(response).to have_http_status(200)
diff --git a/spec/controllers/api/v1/admin/accounts_controller_spec.rb b/spec/controllers/api/v1/admin/accounts_controller_spec.rb
index b69595f7e..cd38030e0 100644
--- a/spec/controllers/api/v1/admin/accounts_controller_spec.rb
+++ b/spec/controllers/api/v1/admin/accounts_controller_spec.rb
@@ -3,7 +3,7 @@ require 'rails_helper'
RSpec.describe Api::V1::Admin::AccountsController, type: :controller do
render_views
- let(:role) { 'moderator' }
+ let(:role) { UserRole.find_by(name: 'Moderator') }
let(:user) { Fabricate(:user, role: role) }
let(:scopes) { 'admin:read admin:write' }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
@@ -22,7 +22,7 @@ RSpec.describe Api::V1::Admin::AccountsController, type: :controller do
end
shared_examples 'forbidden for wrong role' do |wrong_role|
- let(:role) { wrong_role }
+ let(:role) { UserRole.find_by(name: wrong_role) }
it 'returns http forbidden' do
expect(response).to have_http_status(403)
@@ -46,7 +46,7 @@ RSpec.describe Api::V1::Admin::AccountsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
+ it_behaves_like 'forbidden for wrong role', ''
[
[{ active: 'true', local: 'true', staff: 'true' }, [:admin_account]],
@@ -77,7 +77,7 @@ RSpec.describe Api::V1::Admin::AccountsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
+ it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -91,7 +91,7 @@ RSpec.describe Api::V1::Admin::AccountsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
+ it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -109,7 +109,7 @@ RSpec.describe Api::V1::Admin::AccountsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
+ it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -127,7 +127,7 @@ RSpec.describe Api::V1::Admin::AccountsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
+ it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -145,7 +145,7 @@ RSpec.describe Api::V1::Admin::AccountsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
+ it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -163,7 +163,7 @@ RSpec.describe Api::V1::Admin::AccountsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
+ it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -181,7 +181,7 @@ RSpec.describe Api::V1::Admin::AccountsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
+ it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
expect(response).to have_http_status(200)
diff --git a/spec/controllers/api/v1/admin/domain_allows_controller_spec.rb b/spec/controllers/api/v1/admin/domain_allows_controller_spec.rb
index edee3ab6c..26a391a60 100644
--- a/spec/controllers/api/v1/admin/domain_allows_controller_spec.rb
+++ b/spec/controllers/api/v1/admin/domain_allows_controller_spec.rb
@@ -3,7 +3,7 @@ require 'rails_helper'
RSpec.describe Api::V1::Admin::DomainAllowsController, type: :controller do
render_views
- let(:role) { 'admin' }
+ let(:role) { UserRole.find_by(name: 'Admin') }
let(:user) { Fabricate(:user, role: role) }
let(:scopes) { 'admin:read admin:write' }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
@@ -21,7 +21,7 @@ RSpec.describe Api::V1::Admin::DomainAllowsController, type: :controller do
end
shared_examples 'forbidden for wrong role' do |wrong_role|
- let(:role) { wrong_role }
+ let(:role) { UserRole.find_by(name: wrong_role) }
it 'returns http forbidden' do
expect(response).to have_http_status(403)
@@ -36,8 +36,8 @@ RSpec.describe Api::V1::Admin::DomainAllowsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
- it_behaves_like 'forbidden for wrong role', 'moderator'
+ it_behaves_like 'forbidden for wrong role', ''
+ it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -58,8 +58,8 @@ RSpec.describe Api::V1::Admin::DomainAllowsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
- it_behaves_like 'forbidden for wrong role', 'moderator'
+ it_behaves_like 'forbidden for wrong role', ''
+ it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -79,8 +79,8 @@ RSpec.describe Api::V1::Admin::DomainAllowsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
- it_behaves_like 'forbidden for wrong role', 'moderator'
+ it_behaves_like 'forbidden for wrong role', ''
+ it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -99,8 +99,8 @@ RSpec.describe Api::V1::Admin::DomainAllowsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
- it_behaves_like 'forbidden for wrong role', 'moderator'
+ it_behaves_like 'forbidden for wrong role', ''
+ it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do
expect(response).to have_http_status(200)
diff --git a/spec/controllers/api/v1/admin/domain_blocks_controller_spec.rb b/spec/controllers/api/v1/admin/domain_blocks_controller_spec.rb
index 196f6dc28..f12285b2a 100644
--- a/spec/controllers/api/v1/admin/domain_blocks_controller_spec.rb
+++ b/spec/controllers/api/v1/admin/domain_blocks_controller_spec.rb
@@ -3,7 +3,7 @@ require 'rails_helper'
RSpec.describe Api::V1::Admin::DomainBlocksController, type: :controller do
render_views
- let(:role) { 'admin' }
+ let(:role) { UserRole.find_by(name: 'Admin') }
let(:user) { Fabricate(:user, role: role) }
let(:scopes) { 'admin:read admin:write' }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
@@ -21,7 +21,7 @@ RSpec.describe Api::V1::Admin::DomainBlocksController, type: :controller do
end
shared_examples 'forbidden for wrong role' do |wrong_role|
- let(:role) { wrong_role }
+ let(:role) { UserRole.find_by(name: wrong_role) }
it 'returns http forbidden' do
expect(response).to have_http_status(403)
@@ -36,8 +36,8 @@ RSpec.describe Api::V1::Admin::DomainBlocksController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
- it_behaves_like 'forbidden for wrong role', 'moderator'
+ it_behaves_like 'forbidden for wrong role', ''
+ it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -58,8 +58,8 @@ RSpec.describe Api::V1::Admin::DomainBlocksController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
- it_behaves_like 'forbidden for wrong role', 'moderator'
+ it_behaves_like 'forbidden for wrong role', ''
+ it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -79,8 +79,8 @@ RSpec.describe Api::V1::Admin::DomainBlocksController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
- it_behaves_like 'forbidden for wrong role', 'moderator'
+ it_behaves_like 'forbidden for wrong role', ''
+ it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -100,8 +100,8 @@ RSpec.describe Api::V1::Admin::DomainBlocksController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
- it_behaves_like 'forbidden for wrong role', 'moderator'
+ it_behaves_like 'forbidden for wrong role', ''
+ it_behaves_like 'forbidden for wrong role', 'Moderator'
it 'returns http success' do
expect(response).to have_http_status(200)
diff --git a/spec/controllers/api/v1/admin/reports_controller_spec.rb b/spec/controllers/api/v1/admin/reports_controller_spec.rb
index b6df53048..880e72030 100644
--- a/spec/controllers/api/v1/admin/reports_controller_spec.rb
+++ b/spec/controllers/api/v1/admin/reports_controller_spec.rb
@@ -3,7 +3,7 @@ require 'rails_helper'
RSpec.describe Api::V1::Admin::ReportsController, type: :controller do
render_views
- let(:role) { 'moderator' }
+ let(:role) { UserRole.find_by(name: 'Moderator') }
let(:user) { Fabricate(:user, role: role) }
let(:scopes) { 'admin:read admin:write' }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
@@ -22,7 +22,7 @@ RSpec.describe Api::V1::Admin::ReportsController, type: :controller do
end
shared_examples 'forbidden for wrong role' do |wrong_role|
- let(:role) { wrong_role }
+ let(:role) { UserRole.find_by(name: wrong_role) }
it 'returns http forbidden' do
expect(response).to have_http_status(403)
@@ -35,7 +35,7 @@ RSpec.describe Api::V1::Admin::ReportsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
+ it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -48,7 +48,7 @@ RSpec.describe Api::V1::Admin::ReportsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
+ it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -61,7 +61,7 @@ RSpec.describe Api::V1::Admin::ReportsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
+ it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -74,7 +74,7 @@ RSpec.describe Api::V1::Admin::ReportsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
+ it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -87,7 +87,7 @@ RSpec.describe Api::V1::Admin::ReportsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
+ it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
expect(response).to have_http_status(200)
@@ -100,7 +100,7 @@ RSpec.describe Api::V1::Admin::ReportsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
+ it_behaves_like 'forbidden for wrong role', ''
it 'returns http success' do
expect(response).to have_http_status(200)
diff --git a/spec/controllers/api/v1/reports_controller_spec.rb b/spec/controllers/api/v1/reports_controller_spec.rb
index b5baf60e1..dbc64e704 100644
--- a/spec/controllers/api/v1/reports_controller_spec.rb
+++ b/spec/controllers/api/v1/reports_controller_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe Api::V1::ReportsController, type: :controller do
end
describe 'POST #create' do
- let!(:admin) { Fabricate(:user, admin: true) }
+ let!(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
let(:scopes) { 'write:reports' }
let(:status) { Fabricate(:status) }
diff --git a/spec/controllers/api/v2/admin/accounts_controller_spec.rb b/spec/controllers/api/v2/admin/accounts_controller_spec.rb
index 3212ddb84..2508a9e05 100644
--- a/spec/controllers/api/v2/admin/accounts_controller_spec.rb
+++ b/spec/controllers/api/v2/admin/accounts_controller_spec.rb
@@ -3,7 +3,7 @@ require 'rails_helper'
RSpec.describe Api::V2::Admin::AccountsController, type: :controller do
render_views
- let(:role) { 'moderator' }
+ let(:role) { UserRole.find_by(name: 'Moderator') }
let(:user) { Fabricate(:user, role: role) }
let(:scopes) { 'admin:read admin:write' }
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
@@ -22,7 +22,7 @@ RSpec.describe Api::V2::Admin::AccountsController, type: :controller do
end
shared_examples 'forbidden for wrong role' do |wrong_role|
- let(:role) { wrong_role }
+ let(:role) { UserRole.find_by(name: wrong_role) }
it 'returns http forbidden' do
expect(response).to have_http_status(403)
@@ -46,7 +46,7 @@ RSpec.describe Api::V2::Admin::AccountsController, type: :controller do
end
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- it_behaves_like 'forbidden for wrong role', 'user'
+ it_behaves_like 'forbidden for wrong role', ''
[
[{ status: 'active', origin: 'local', permissions: 'staff' }, [:admin_account]],
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index 53e163d49..1b002e01c 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -183,70 +183,6 @@ describe ApplicationController, type: :controller do
end
end
- describe 'require_admin!' do
- controller do
- before_action :require_admin!
-
- def success
- head 200
- end
- end
-
- before do
- routes.draw { get 'success' => 'anonymous#success' }
- end
-
- it 'returns a 403 if current user is not admin' do
- sign_in(Fabricate(:user, admin: false))
- get 'success'
- expect(response).to have_http_status(403)
- end
-
- it 'returns a 403 if current user is only a moderator' do
- sign_in(Fabricate(:user, moderator: true))
- get 'success'
- expect(response).to have_http_status(403)
- end
-
- it 'does nothing if current user is admin' do
- sign_in(Fabricate(:user, admin: true))
- get 'success'
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'require_staff!' do
- controller do
- before_action :require_staff!
-
- def success
- head 200
- end
- end
-
- before do
- routes.draw { get 'success' => 'anonymous#success' }
- end
-
- it 'returns a 403 if current user is not admin or moderator' do
- sign_in(Fabricate(:user, admin: false, moderator: false))
- get 'success'
- expect(response).to have_http_status(403)
- end
-
- it 'does nothing if current user is moderator' do
- sign_in(Fabricate(:user, moderator: true))
- get 'success'
- expect(response).to have_http_status(200)
- end
-
- it 'does nothing if current user is admin' do
- sign_in(Fabricate(:user, admin: true))
- get 'success'
- expect(response).to have_http_status(200)
- end
- end
-
describe 'forbidden' do
controller do
def route_forbidden
diff --git a/spec/controllers/disputes/appeals_controller_spec.rb b/spec/controllers/disputes/appeals_controller_spec.rb
index faa571fc9..90f222f49 100644
--- a/spec/controllers/disputes/appeals_controller_spec.rb
+++ b/spec/controllers/disputes/appeals_controller_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Disputes::AppealsController, type: :controller do
before { sign_in current_user, scope: :user }
- let!(:admin) { Fabricate(:user, admin: true) }
+ let!(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
describe '#create' do
let(:current_user) { Fabricate(:user) }
diff --git a/spec/controllers/invites_controller_spec.rb b/spec/controllers/invites_controller_spec.rb
index 76e617e6b..23b98fb12 100644
--- a/spec/controllers/invites_controller_spec.rb
+++ b/spec/controllers/invites_controller_spec.rb
@@ -7,30 +7,30 @@ describe InvitesController do
sign_in user
end
- around do |example|
- min_invite_role = Setting.min_invite_role
- example.run
- Setting.min_invite_role = min_invite_role
- end
-
describe 'GET #index' do
subject { get :index }
- let(:user) { Fabricate(:user, moderator: false, admin: false) }
+ let(:user) { Fabricate(:user) }
let!(:invite) { Fabricate(:invite, user: user) }
- context 'when user is a staff' do
+ context 'when everyone can invite' do
+ before do
+ UserRole.everyone.update(permissions: UserRole.everyone.permissions | UserRole::FLAGS[:invite_users])
+ end
+
it 'renders index page' do
- Setting.min_invite_role = 'user'
expect(subject).to render_template :index
expect(assigns(:invites)).to include invite
expect(assigns(:invites).count).to eq 1
end
end
- context 'when user is not a staff' do
+ context 'when not everyone can invite' do
+ before do
+ UserRole.everyone.update(permissions: UserRole.everyone.permissions & ~UserRole::FLAGS[:invite_users])
+ end
+
it 'returns 403' do
- Setting.min_invite_role = 'modelator'
expect(subject).to have_http_status 403
end
end
@@ -39,8 +39,12 @@ describe InvitesController do
describe 'POST #create' do
subject { post :create, params: { invite: { max_uses: '10', expires_in: 1800 } } }
- context 'when user is an admin' do
- let(:user) { Fabricate(:user, moderator: false, admin: true) }
+ context 'when everyone can invite' do
+ let(:user) { Fabricate(:user) }
+
+ before do
+ UserRole.everyone.update(permissions: UserRole.everyone.permissions | UserRole::FLAGS[:invite_users])
+ end
it 'succeeds to create a invite' do
expect { subject }.to change { Invite.count }.by(1)
@@ -49,8 +53,12 @@ describe InvitesController do
end
end
- context 'when user is not an admin' do
- let(:user) { Fabricate(:user, moderator: true, admin: false) }
+ context 'when not everyone can invite' do
+ let(:user) { Fabricate(:user) }
+
+ before do
+ UserRole.everyone.update(permissions: UserRole.everyone.permissions & ~UserRole::FLAGS[:invite_users])
+ end
it 'returns 403' do
expect(subject).to have_http_status 403
@@ -61,8 +69,8 @@ describe InvitesController do
describe 'DELETE #create' do
subject { delete :destroy, params: { id: invite.id } }
+ let(:user) { Fabricate(:user) }
let!(:invite) { Fabricate(:invite, user: user, expires_at: nil) }
- let(:user) { Fabricate(:user, moderator: false, admin: true) }
it 'expires invite' do
expect(subject).to redirect_to invites_path
diff --git a/spec/fabricators/user_role_fabricator.rb b/spec/fabricators/user_role_fabricator.rb
new file mode 100644
index 000000000..28f76c8c4
--- /dev/null
+++ b/spec/fabricators/user_role_fabricator.rb
@@ -0,0 +1,5 @@
+Fabricator(:user_role) do
+ name "MyString"
+ color "MyString"
+ permissions ""
+end
\ No newline at end of file
diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb
index dc0ca3da3..467d41836 100644
--- a/spec/models/account_spec.rb
+++ b/spec/models/account_spec.rb
@@ -445,7 +445,7 @@ RSpec.describe Account, type: :model do
it 'accepts arbitrary limits' do
2.times.each { Fabricate(:account, display_name: "Display Name") }
- results = Account.search_for("display", 1)
+ results = Account.search_for("display", limit: 1)
expect(results.size).to eq 1
end
@@ -473,7 +473,7 @@ RSpec.describe Account, type: :model do
)
account.follow!(match)
- results = Account.advanced_search_for('A?l\i:c e', account, 10, true)
+ results = Account.advanced_search_for('A?l\i:c e', account, limit: 10, following: true)
expect(results).to eq [match]
end
@@ -485,7 +485,7 @@ RSpec.describe Account, type: :model do
domain: 'example.com'
)
- results = Account.advanced_search_for('A?l\i:c e', account, 10, true)
+ results = Account.advanced_search_for('A?l\i:c e', account, limit: 10, following: true)
expect(results).to eq []
end
@@ -498,7 +498,7 @@ RSpec.describe Account, type: :model do
suspended: true
)
- results = Account.advanced_search_for('username', account, 10, true)
+ results = Account.advanced_search_for('username', account, limit: 10, following: true)
expect(results).to eq []
end
@@ -511,7 +511,7 @@ RSpec.describe Account, type: :model do
match.user.update(approved: false)
- results = Account.advanced_search_for('username', account, 10, true)
+ results = Account.advanced_search_for('username', account, limit: 10, following: true)
expect(results).to eq []
end
@@ -524,7 +524,7 @@ RSpec.describe Account, type: :model do
match.user.update(confirmed_at: nil)
- results = Account.advanced_search_for('username', account, 10, true)
+ results = Account.advanced_search_for('username', account, limit: 10, following: true)
expect(results).to eq []
end
end
@@ -588,7 +588,7 @@ RSpec.describe Account, type: :model do
it 'accepts arbitrary limits' do
2.times { Fabricate(:account, display_name: "Display Name") }
- results = Account.advanced_search_for("display", account, 1)
+ results = Account.advanced_search_for("display", account, limit: 1)
expect(results.size).to eq 1
end
diff --git a/spec/models/admin/account_action_spec.rb b/spec/models/admin/account_action_spec.rb
index 809c7fc46..b6a052b76 100644
--- a/spec/models/admin/account_action_spec.rb
+++ b/spec/models/admin/account_action_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Admin::AccountAction, type: :model do
describe '#save!' do
subject { account_action.save! }
- let(:account) { Fabricate(:user, admin: true).account }
+ let(:account) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:target_account) { Fabricate(:account) }
let(:type) { 'disable' }
diff --git a/spec/models/user_role_spec.rb b/spec/models/user_role_spec.rb
new file mode 100644
index 000000000..28019593e
--- /dev/null
+++ b/spec/models/user_role_spec.rb
@@ -0,0 +1,189 @@
+require 'rails_helper'
+
+RSpec.describe UserRole, type: :model do
+ subject { described_class.create(name: 'Foo', position: 1) }
+
+ describe '#can?' do
+ context 'with a single flag' do
+ it 'returns true if any of them are present' do
+ subject.permissions = UserRole::FLAGS[:manage_reports]
+ expect(subject.can?(:manage_reports)).to be true
+ end
+
+ it 'returns false if it is not set' do
+ expect(subject.can?(:manage_reports)).to be false
+ end
+ end
+
+ context 'with multiple flags' do
+ it 'returns true if any of them are present' do
+ subject.permissions = UserRole::FLAGS[:manage_users]
+ expect(subject.can?(:manage_reports, :manage_users)).to be true
+ end
+
+ it 'returns false if none of them are present' do
+ expect(subject.can?(:manage_reports, :manage_users)).to be false
+ end
+ end
+
+ context 'with an unknown flag' do
+ it 'raises an error' do
+ expect { subject.can?(:foo) }.to raise_error ArgumentError
+ end
+ end
+ end
+
+ describe '#overrides?' do
+ it 'returns true if other role has lower position' do
+ expect(subject.overrides?(described_class.new(position: subject.position - 1))).to be true
+ end
+
+ it 'returns true if other role is nil' do
+ expect(subject.overrides?(nil)).to be true
+ end
+
+ it 'returns false if other role has higher position' do
+ expect(subject.overrides?(described_class.new(position: subject.position + 1))).to be false
+ end
+ end
+
+ describe '#permissions_as_keys' do
+ before do
+ subject.permissions = UserRole::FLAGS[:invite_users] | UserRole::FLAGS[:view_dashboard] | UserRole::FLAGS[:manage_reports]
+ end
+
+ it 'returns an array' do
+ expect(subject.permissions_as_keys).to match_array %w(invite_users view_dashboard manage_reports)
+ end
+ end
+
+ describe '#permissions_as_keys=' do
+ let(:input) { }
+
+ before do
+ subject.permissions_as_keys = input
+ end
+
+ context 'with a single value' do
+ let(:input) { %w(manage_users) }
+
+ it 'sets permission flags' do
+ expect(subject.permissions).to eq UserRole::FLAGS[:manage_users]
+ end
+ end
+
+ context 'with multiple values' do
+ let(:input) { %w(manage_users manage_reports) }
+
+ it 'sets permission flags' do
+ expect(subject.permissions).to eq UserRole::FLAGS[:manage_users] | UserRole::FLAGS[:manage_reports]
+ end
+ end
+
+ context 'with an unknown value' do
+ let(:input) { %w(foo) }
+
+ it 'does not set permission flags' do
+ expect(subject.permissions).to eq UserRole::Flags::NONE
+ end
+ end
+ end
+
+ describe '#computed_permissions' do
+ context 'when the role is nobody' do
+ let(:subject) { described_class.nobody }
+
+ it 'returns none' do
+ expect(subject.computed_permissions).to eq UserRole::Flags::NONE
+ end
+ end
+
+ context 'when the role is everyone' do
+ let(:subject) { described_class.everyone }
+
+ it 'returns permissions' do
+ expect(subject.computed_permissions).to eq subject.permissions
+ end
+ end
+
+ context 'when role has the administrator flag' do
+ before do
+ subject.permissions = UserRole::FLAGS[:administrator]
+ end
+
+ it 'returns all permissions' do
+ expect(subject.computed_permissions).to eq UserRole::Flags::ALL
+ end
+ end
+
+ context do
+ it 'returns permissions combined with the everyone role' do
+ expect(subject.computed_permissions).to eq described_class.everyone.permissions
+ end
+ end
+ end
+
+ describe '.everyone' do
+ subject { described_class.everyone }
+
+ it 'returns a role' do
+ expect(subject).to be_kind_of(described_class)
+ end
+
+ it 'is identified as the everyone role' do
+ expect(subject.everyone?).to be true
+ end
+
+ it 'has default permissions' do
+ expect(subject.permissions).to eq UserRole::FLAGS[:invite_users]
+ end
+
+ it 'has negative position' do
+ expect(subject.position).to eq -1
+ end
+ end
+
+ describe '.nobody' do
+ subject { described_class.nobody }
+
+ it 'returns a role' do
+ expect(subject).to be_kind_of(described_class)
+ end
+
+ it 'is identified as the nobody role' do
+ expect(subject.nobody?).to be true
+ end
+
+ it 'has no permissions' do
+ expect(subject.permissions).to eq UserRole::Flags::NONE
+ end
+
+ it 'has negative position' do
+ expect(subject.position).to eq -1
+ end
+ end
+
+ describe '#everyone?' do
+ it 'returns true when id is -99' do
+ subject.id = -99
+ expect(subject.everyone?).to be true
+ end
+
+ it 'returns false when id is not -99' do
+ subject.id = 123
+ expect(subject.everyone?).to be false
+ end
+ end
+
+ describe '#nobody?' do
+ it 'returns true when id is nil' do
+ subject.id = nil
+ expect(subject.nobody?).to be true
+ end
+
+ it 'returns false when id is not nil' do
+ subject.id = 123
+ expect(subject.nobody?).to be false
+ end
+ end
+end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 1645ab59e..a7da31e60 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -56,14 +56,6 @@ RSpec.describe User, type: :model do
end
end
- describe 'admins' do
- it 'returns an array of users who are admin' do
- user_1 = Fabricate(:user, admin: false)
- user_2 = Fabricate(:user, admin: true)
- expect(User.admins).to match_array([user_2])
- end
- end
-
describe 'confirmed' do
it 'returns an array of users who are confirmed' do
user_1 = Fabricate(:user, confirmed_at: nil)
@@ -289,49 +281,6 @@ RSpec.describe User, type: :model do
end
end
- describe '#role' do
- it 'returns admin for admin' do
- user = User.new(admin: true)
- expect(user.role).to eq 'admin'
- end
-
- it 'returns moderator for moderator' do
- user = User.new(moderator: true)
- expect(user.role).to eq 'moderator'
- end
-
- it 'returns user otherwise' do
- user = User.new
- expect(user.role).to eq 'user'
- end
- end
-
- describe '#role?' do
- it 'returns false when invalid role requested' do
- user = User.new(admin: true)
- expect(user.role?('disabled')).to be false
- end
-
- it 'returns true when exact role match' do
- user = User.new
- mod = User.new(moderator: true)
- admin = User.new(admin: true)
-
- expect(user.role?('user')).to be true
- expect(mod.role?('moderator')).to be true
- expect(admin.role?('admin')).to be true
- end
-
- it 'returns true when role higher than needed' do
- mod = User.new(moderator: true)
- admin = User.new(admin: true)
-
- expect(mod.role?('user')).to be true
- expect(admin.role?('user')).to be true
- expect(admin.role?('moderator')).to be true
- end
- end
-
describe '#disable!' do
subject(:user) { Fabricate(:user, disabled: false, current_sign_in_at: current_sign_in_at, last_sign_in_at: nil) }
let(:current_sign_in_at) { Time.zone.now }
@@ -420,110 +369,6 @@ RSpec.describe User, type: :model do
end
end
- describe '#promote!' do
- subject(:user) { Fabricate(:user, admin: is_admin, moderator: is_moderator) }
-
- before do
- user.promote!
- end
-
- context 'when user is an admin' do
- let(:is_admin) { true }
-
- context 'when user is a moderator' do
- let(:is_moderator) { true }
-
- it 'changes moderator filed false' do
- expect(user).to be_admin
- expect(user).not_to be_moderator
- end
- end
-
- context 'when user is not a moderator' do
- let(:is_moderator) { false }
-
- it 'does not change status' do
- expect(user).to be_admin
- expect(user).not_to be_moderator
- end
- end
- end
-
- context 'when user is not admin' do
- let(:is_admin) { false }
-
- context 'when user is a moderator' do
- let(:is_moderator) { true }
-
- it 'changes user into an admin' do
- expect(user).to be_admin
- expect(user).not_to be_moderator
- end
- end
-
- context 'when user is not a moderator' do
- let(:is_moderator) { false }
-
- it 'changes user into a moderator' do
- expect(user).not_to be_admin
- expect(user).to be_moderator
- end
- end
- end
- end
-
- describe '#demote!' do
- subject(:user) { Fabricate(:user, admin: admin, moderator: moderator) }
-
- before do
- user.demote!
- end
-
- context 'when user is an admin' do
- let(:admin) { true }
-
- context 'when user is a moderator' do
- let(:moderator) { true }
-
- it 'changes user into a moderator' do
- expect(user).not_to be_admin
- expect(user).to be_moderator
- end
- end
-
- context 'when user is not a moderator' do
- let(:moderator) { false }
-
- it 'changes user into a moderator' do
- expect(user).not_to be_admin
- expect(user).to be_moderator
- end
- end
- end
-
- context 'when user is not an admin' do
- let(:admin) { false }
-
- context 'when user is a moderator' do
- let(:moderator) { true }
-
- it 'changes user into a plain user' do
- expect(user).not_to be_admin
- expect(user).not_to be_moderator
- end
- end
-
- context 'when user is not a moderator' do
- let(:moderator) { false }
-
- it 'does not change any fields' do
- expect(user).not_to be_admin
- expect(user).not_to be_moderator
- end
- end
- end
- end
-
describe '#active_for_authentication?' do
subject { user.active_for_authentication? }
let(:user) { Fabricate(:user, disabled: disabled, confirmed_at: confirmed_at) }
@@ -560,4 +405,8 @@ RSpec.describe User, type: :model do
end
end
end
+
+ describe '.those_who_can' do
+ pending
+ end
end
diff --git a/spec/policies/account_moderation_note_policy_spec.rb b/spec/policies/account_moderation_note_policy_spec.rb
index 39ec2008a..846747346 100644
--- a/spec/policies/account_moderation_note_policy_spec.rb
+++ b/spec/policies/account_moderation_note_policy_spec.rb
@@ -5,7 +5,7 @@ require 'pundit/rspec'
RSpec.describe AccountModerationNotePolicy do
let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
+ let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
permissions :create? do
@@ -31,7 +31,7 @@ RSpec.describe AccountModerationNotePolicy do
context 'admin' do
it 'grants to destroy' do
- expect(subject).to permit(admin, AccountModerationNotePolicy)
+ expect(subject).to permit(admin, account_moderation_note)
end
end
diff --git a/spec/policies/account_policy_spec.rb b/spec/policies/account_policy_spec.rb
index b55eb65a7..0f23fd97e 100644
--- a/spec/policies/account_policy_spec.rb
+++ b/spec/policies/account_policy_spec.rb
@@ -5,7 +5,7 @@ require 'pundit/rspec'
RSpec.describe AccountPolicy do
let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
+ let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
let(:alice) { Fabricate(:account) }
@@ -55,7 +55,7 @@ RSpec.describe AccountPolicy do
end
end
- permissions :redownload?, :subscribe?, :unsubscribe? do
+ permissions :redownload? do
context 'admin' do
it 'permits' do
expect(subject).to permit(admin)
@@ -70,7 +70,7 @@ RSpec.describe AccountPolicy do
end
permissions :suspend?, :silence? do
- let(:staff) { Fabricate(:user, admin: true).account }
+ let(:staff) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
context 'staff' do
context 'record is staff' do
@@ -94,7 +94,7 @@ RSpec.describe AccountPolicy do
end
permissions :memorialize? do
- let(:other_admin) { Fabricate(:user, admin: true).account }
+ let(:other_admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
context 'admin' do
context 'record is admin' do
diff --git a/spec/policies/custom_emoji_policy_spec.rb b/spec/policies/custom_emoji_policy_spec.rb
index e4f1af3c1..6a6ef6694 100644
--- a/spec/policies/custom_emoji_policy_spec.rb
+++ b/spec/policies/custom_emoji_policy_spec.rb
@@ -5,7 +5,7 @@ require 'pundit/rspec'
RSpec.describe CustomEmojiPolicy do
let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
+ let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
permissions :index?, :enable?, :disable? do
diff --git a/spec/policies/domain_block_policy_spec.rb b/spec/policies/domain_block_policy_spec.rb
index b24ed9e3a..01b97e823 100644
--- a/spec/policies/domain_block_policy_spec.rb
+++ b/spec/policies/domain_block_policy_spec.rb
@@ -5,7 +5,7 @@ require 'pundit/rspec'
RSpec.describe DomainBlockPolicy do
let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
+ let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
permissions :index?, :show?, :create?, :destroy? do
diff --git a/spec/policies/email_domain_block_policy_spec.rb b/spec/policies/email_domain_block_policy_spec.rb
index 1ff55af8e..913075c3d 100644
--- a/spec/policies/email_domain_block_policy_spec.rb
+++ b/spec/policies/email_domain_block_policy_spec.rb
@@ -5,7 +5,7 @@ require 'pundit/rspec'
RSpec.describe EmailDomainBlockPolicy do
let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
+ let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
permissions :index?, :create?, :destroy? do
diff --git a/spec/policies/instance_policy_spec.rb b/spec/policies/instance_policy_spec.rb
index 71ef1fe50..f6f51af06 100644
--- a/spec/policies/instance_policy_spec.rb
+++ b/spec/policies/instance_policy_spec.rb
@@ -5,7 +5,7 @@ require 'pundit/rspec'
RSpec.describe InstancePolicy do
let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
+ let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
permissions :index?, :show?, :destroy? do
diff --git a/spec/policies/invite_policy_spec.rb b/spec/policies/invite_policy_spec.rb
index 122137804..01660322f 100644
--- a/spec/policies/invite_policy_spec.rb
+++ b/spec/policies/invite_policy_spec.rb
@@ -5,8 +5,8 @@ require 'pundit/rspec'
RSpec.describe InvitePolicy do
let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
- let(:john) { Fabricate(:account) }
+ let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
+ let(:john) { Fabricate(:user).account }
permissions :index? do
context 'staff?' do
@@ -17,16 +17,22 @@ RSpec.describe InvitePolicy do
end
permissions :create? do
- context 'min_required_role?' do
+ context 'has privilege' do
+ before do
+ UserRole.everyone.update(permissions: UserRole::FLAGS[:invite_users])
+ end
+
it 'permits' do
- allow_any_instance_of(described_class).to receive(:min_required_role?) { true }
expect(subject).to permit(john, Invite)
end
end
- context 'not min_required_role?' do
+ context 'does not have privilege' do
+ before do
+ UserRole.everyone.update(permissions: UserRole::Flags::NONE)
+ end
+
it 'denies' do
- allow_any_instance_of(described_class).to receive(:min_required_role?) { false }
expect(subject).to_not permit(john, Invite)
end
end
@@ -54,39 +60,15 @@ RSpec.describe InvitePolicy do
end
context 'not owner?' do
- context 'Setting.min_invite_role == "admin"' do
- before do
- Setting.min_invite_role = 'admin'
- end
-
- context 'admin?' do
- it 'permits' do
- expect(subject).to permit(admin, Fabricate(:invite))
- end
- end
-
- context 'not admin?' do
- it 'denies' do
- expect(subject).to_not permit(john, Fabricate(:invite))
- end
+ context 'admin?' do
+ it 'permits' do
+ expect(subject).to permit(admin, Fabricate(:invite))
end
end
- context 'Setting.min_invite_role != "admin"' do
- before do
- Setting.min_invite_role = 'else'
- end
-
- context 'staff?' do
- it 'permits' do
- expect(subject).to permit(admin, Fabricate(:invite))
- end
- end
-
- context 'not staff?' do
- it 'denies' do
- expect(subject).to_not permit(john, Fabricate(:invite))
- end
+ context 'not admin?' do
+ it 'denies' do
+ expect(subject).to_not permit(john, Fabricate(:invite))
end
end
end
diff --git a/spec/policies/relay_policy_spec.rb b/spec/policies/relay_policy_spec.rb
index 139d945dc..2c50ba1e9 100644
--- a/spec/policies/relay_policy_spec.rb
+++ b/spec/policies/relay_policy_spec.rb
@@ -5,7 +5,7 @@ require 'pundit/rspec'
RSpec.describe RelayPolicy do
let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
+ let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
permissions :update? do
diff --git a/spec/policies/report_note_policy_spec.rb b/spec/policies/report_note_policy_spec.rb
index c34f99b71..99f5ffb8e 100644
--- a/spec/policies/report_note_policy_spec.rb
+++ b/spec/policies/report_note_policy_spec.rb
@@ -5,7 +5,7 @@ require 'pundit/rspec'
RSpec.describe ReportNotePolicy do
let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
+ let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
permissions :create? do
@@ -25,7 +25,8 @@ RSpec.describe ReportNotePolicy do
permissions :destroy? do
context 'admin?' do
it 'permit' do
- expect(subject).to permit(admin, ReportNote)
+ report_note = Fabricate(:report_note, account: john)
+ expect(subject).to permit(admin, report_note)
end
end
diff --git a/spec/policies/report_policy_spec.rb b/spec/policies/report_policy_spec.rb
index 84c366d7f..8b005d8dd 100644
--- a/spec/policies/report_policy_spec.rb
+++ b/spec/policies/report_policy_spec.rb
@@ -5,7 +5,7 @@ require 'pundit/rspec'
RSpec.describe ReportPolicy do
let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
+ let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
permissions :update?, :index?, :show? do
diff --git a/spec/policies/settings_policy_spec.rb b/spec/policies/settings_policy_spec.rb
index 3fa183c50..e16ee51a4 100644
--- a/spec/policies/settings_policy_spec.rb
+++ b/spec/policies/settings_policy_spec.rb
@@ -5,7 +5,7 @@ require 'pundit/rspec'
RSpec.describe SettingsPolicy do
let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
+ let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
permissions :update?, :show? do
diff --git a/spec/policies/status_policy_spec.rb b/spec/policies/status_policy_spec.rb
index 28b808ee2..205ecd720 100644
--- a/spec/policies/status_policy_spec.rb
+++ b/spec/policies/status_policy_spec.rb
@@ -6,7 +6,7 @@ require 'pundit/rspec'
RSpec.describe StatusPolicy, type: :model do
subject { described_class }
- let(:admin) { Fabricate(:user, admin: true) }
+ let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
let(:alice) { Fabricate(:account, username: 'alice') }
let(:bob) { Fabricate(:account, username: 'bob') }
let(:status) { Fabricate(:status, account: alice) }
diff --git a/spec/policies/tag_policy_spec.rb b/spec/policies/tag_policy_spec.rb
index 256e6786a..9be7140fc 100644
--- a/spec/policies/tag_policy_spec.rb
+++ b/spec/policies/tag_policy_spec.rb
@@ -5,7 +5,7 @@ require 'pundit/rspec'
RSpec.describe TagPolicy do
let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
+ let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
permissions :index?, :show?, :update? do
diff --git a/spec/policies/user_policy_spec.rb b/spec/policies/user_policy_spec.rb
index 731c041d1..ff0916674 100644
--- a/spec/policies/user_policy_spec.rb
+++ b/spec/policies/user_policy_spec.rb
@@ -5,7 +5,7 @@ require 'pundit/rspec'
RSpec.describe UserPolicy do
let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
+ let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
let(:john) { Fabricate(:account) }
permissions :reset_password?, :change_email? do
@@ -111,57 +111,4 @@ RSpec.describe UserPolicy do
end
end
end
-
- permissions :promote? do
- context 'admin?' do
- context 'promotable?' do
- it 'permits' do
- expect(subject).to permit(admin, john.user)
- end
- end
-
- context '!promotable?' do
- it 'denies' do
- expect(subject).to_not permit(admin, admin.user)
- end
- end
- end
-
- context '!admin?' do
- it 'denies' do
- expect(subject).to_not permit(john, User)
- end
- end
- end
-
- permissions :demote? do
- context 'admin?' do
- context '!record.admin?' do
- context 'demoteable?' do
- it 'permits' do
- john.user.update(moderator: true)
- expect(subject).to permit(admin, john.user)
- end
- end
-
- context '!demoteable?' do
- it 'denies' do
- expect(subject).to_not permit(admin, john.user)
- end
- end
- end
-
- context 'record.admin?' do
- it 'denies' do
- expect(subject).to_not permit(admin, admin.user)
- end
- end
- end
-
- context '!admin?' do
- it 'denies' do
- expect(subject).to_not permit(john, User)
- end
- end
- end
end