diff --git a/.env.production.sample b/.env.production.sample index a513322cab..116e09991e 100644 --- a/.env.production.sample +++ b/.env.production.sample @@ -283,8 +283,8 @@ MAX_POLL_OPTION_CHARS=100 # If undefined or smaller than MAX_EMOJI_SIZE, the value # of MAX_EMOJI_SIZE will be used for MAX_REMOTE_EMOJI_SIZE # Units are in bytes -MAX_EMOJI_SIZE=51200 -MAX_REMOTE_EMOJI_SIZE=204800 +# MAX_EMOJI_SIZE=262144 +# MAX_REMOTE_EMOJI_SIZE=262144 # IP retention period # If undefined, the value of 31556952 (1 average year) will be used. @@ -302,3 +302,11 @@ SESSION_RETENTION_PERIOD=31556952 # Optional hCaptcha support # HCAPTCHA_SECRET_KEY= # HCAPTCHA_SITE_KEY= + +# IP and session retention +# ----------------------- +# Make sure to modify the scheduling of ip_cleanup_scheduler in config/sidekiq.yml +# to be less than daily if you lower IP_RETENTION_PERIOD below two days (172800). +# ----------------------- +IP_RETENTION_PERIOD=31556952 +SESSION_RETENTION_PERIOD=31556952 diff --git a/.rubocop.yml b/.rubocop.yml index 9e3ff21f25..8dc2d1c479 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/Gemfile b/Gemfile index 9a638cd069..f723ce7398 100644 --- a/Gemfile +++ b/Gemfile @@ -10,7 +10,7 @@ gem 'puma', '~> 5.6' gem 'rails', '~> 6.1.6' gem 'sprockets', '~> 3.7.2' gem 'thor', '~> 1.2' -gem 'rack', '~> 2.2.3' +gem 'rack', '~> 2.2.4' gem 'hamlit-rails', '~> 0.2' gem 'pg', '~> 1.4' @@ -40,7 +40,7 @@ end gem 'net-ldap', '~> 0.17' gem 'omniauth-cas', '~> 2.0' gem 'omniauth-saml', '~> 1.10' -gem 'gitlab-omniauth-openid-connect', '~>0.9.1', require: 'omniauth_openid_connect' +gem 'gitlab-omniauth-openid-connect', '~>0.10.0', require: 'omniauth_openid_connect' gem 'omniauth', '~> 1.9' gem 'omniauth-rails_csrf_protection', '~> 0.1' @@ -78,7 +78,7 @@ gem 'rqrcode', '~> 2.1' gem 'ruby-progressbar', '~> 1.11' gem 'sanitize', '~> 6.0' gem 'scenic', '~> 1.6' -gem 'sidekiq', '~> 6.4' +gem 'sidekiq', '~> 6.5' gem 'sidekiq-scheduler', '~> 4.0' gem 'sidekiq-unique-jobs', '~> 7.1' gem 'sidekiq-bulk', '~> 0.2.0' diff --git a/Gemfile.lock b/Gemfile.lock index 6599bb9ce6..e334d5733d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -270,9 +270,9 @@ GEM fuubar (2.5.1) rspec-core (~> 3.0) ruby-progressbar (~> 1.4) - gitlab-omniauth-openid-connect (0.9.1) + gitlab-omniauth-openid-connect (0.10.0) addressable (~> 2.7) - omniauth (~> 1.9) + omniauth (>= 1.9, < 3) openid_connect (~> 1.2) globalid (1.0.0) activesupport (>= 5.0) @@ -415,7 +415,7 @@ GEM concurrent-ruby (~> 1.0, >= 1.0.2) sidekiq (>= 3.5) statsd-ruby (~> 1.4, >= 1.4.0) - oj (3.13.14) + oj (3.13.16) omniauth (1.9.1) hashie (>= 3.4.6) rack (>= 1.6.2, < 3) @@ -477,7 +477,7 @@ GEM activesupport (>= 3.0.0) raabro (1.4.0) racc (1.6.0) - rack (2.2.3.1) + rack (2.2.4) rack-attack (6.6.1) rack (>= 1.0, < 3) rack-cors (1.1.1) @@ -604,7 +604,7 @@ GEM railties (>= 4.0.0) securecompare (1.0.0) semantic_range (3.0.0) - sidekiq (6.4.2) + sidekiq (6.5.1) connection_pool (>= 2.2.2) rack (~> 2.0) redis (>= 4.2.0) @@ -686,7 +686,7 @@ GEM validate_email (0.1.6) activemodel (>= 3.0) mail (>= 2.2.5) - validate_url (1.0.13) + validate_url (1.0.15) activemodel (>= 3.0.0) public_suffix warden (1.2.9) @@ -768,7 +768,7 @@ DEPENDENCIES fog-core (<= 2.1.0) fog-openstack (~> 0.3) fuubar (~> 2.5) - gitlab-omniauth-openid-connect (~> 0.9.1) + gitlab-omniauth-openid-connect (~> 0.10.0) hamlit-rails (~> 0.2) hcaptcha (~> 7.1) hiredis (~> 0.6) @@ -811,7 +811,7 @@ DEPENDENCIES pry-rails (~> 0.3) puma (~> 5.6) pundit (~> 2.2) - rack (~> 2.2.3) + rack (~> 2.2.4) rack-attack (~> 6.6) rack-cors (~> 1.1) rails (~> 6.1.6) @@ -832,7 +832,7 @@ DEPENDENCIES ruby-progressbar (~> 1.11) sanitize (~> 6.0) scenic (~> 1.6) - sidekiq (~> 6.4) + sidekiq (~> 6.5) sidekiq-bulk (~> 0.2.0) sidekiq-scheduler (~> 4.0) sidekiq-unique-jobs (~> 7.1) diff --git a/app/controllers/admin/account_actions_controller.rb b/app/controllers/admin/account_actions_controller.rb index ea56fa0ac7..3f2e28b6ae 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 e0ae71b9f2..46c9aba917 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 2d77620df7..42edec15a3 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 cc6cd51f0b..c645ce12bb 100644 --- a/app/controllers/admin/base_controller.rb +++ b/app/controllers/admin/base_controller.rb @@ -7,9 +7,9 @@ module Admin layout 'admin' - before_action :require_staff! before_action :set_pack 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 47138bf6c1..1fae60f5b0 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 da9c6dd162..924b623ad8 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/domain_blocks_controller.rb b/app/controllers/admin/domain_blocks_controller.rb index 48e9781d60..32f1f9a5d3 100644 --- a/app/controllers/admin/domain_blocks_controller.rb +++ b/app/controllers/admin/domain_blocks_controller.rb @@ -5,6 +5,7 @@ module Admin before_action :set_domain_block, only: [:show, :destroy, :edit, :update] def batch + authorize :domain_block, :create? @form = Form::DomainBlockBatch.new(form_domain_block_batch_params.merge(current_account: current_account, action: action_from_button)) @form.save rescue ActionController::ParameterMissing diff --git a/app/controllers/admin/email_domain_blocks_controller.rb b/app/controllers/admin/email_domain_blocks_controller.rb index a4bbbba5ba..593457b94e 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 e3eac62b36..841e3cc7fb 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 92b8b0d2b8..a87520f4ed 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 085ded21c0..67645f0546 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 13f56e9beb..3e502ccc4d 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 817c0caa90..084921cebb 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 40500ef43f..0000000000 --- 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/tags_controller.rb b/app/controllers/admin/tags_controller.rb index 749e2f144d..4f727c398a 100644 --- a/app/controllers/admin/tags_controller.rb +++ b/app/controllers/admin/tags_controller.rb @@ -16,6 +16,8 @@ module Admin if @tag.update(tag_params.merge(reviewed_at: Time.now.utc)) redirect_to admin_tag_path(@tag.id), notice: I18n.t('admin.tags.updated_msg') else + @time_period = (6.days.ago.to_date...Time.now.utc.to_date) + render :show end end @@ -27,7 +29,7 @@ module Admin end def tag_params - params.require(:tag).permit(:name, :trendable, :usable, :listable) + params.require(:tag).permit(:name, :display_name, :trendable, :usable, :listable) 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 40a466cd63..97dee8eca4 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 434eec5fee..a497eae411 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 7662427387..c538962f99 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 f4d1ec0d1f..98dd6c8ec2 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 0000000000..0db50cee92 --- /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 f7fb7eb8fe..5e3fb2b3cf 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 6c9e04402c..7249797a40 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 65ed69f7ba..0dee02e94f 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 49a5be1c36..4a72ad08be 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 838978ddb3..59aa807d6f 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 229870eee9..de8fd9d089 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 da95d34220..d78d7e10b3 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 865ba3d23c..9dfb181a28 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 98d1a3d813..59d6b83883 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 0a191fe4b2..cc63889806 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 cb145f165c..c39f77363c 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 9c28b0412b..f3c0c4b6b4 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/featured_tags/suggestions_controller.rb b/app/controllers/api/v1/featured_tags/suggestions_controller.rb index 75545d3c7f..76633210a1 100644 --- a/app/controllers/api/v1/featured_tags/suggestions_controller.rb +++ b/app/controllers/api/v1/featured_tags/suggestions_controller.rb @@ -6,7 +6,7 @@ class Api::V1::FeaturedTags::SuggestionsController < Api::BaseController before_action :set_recently_used_tags, only: :index def index - render json: @recently_used_tags, each_serializer: REST::TagSerializer + render json: @recently_used_tags, each_serializer: REST::TagSerializer, relationships: TagRelationshipsPresenter.new(@recently_used_tags, current_user&.account_id) end private diff --git a/app/controllers/api/v1/featured_tags_controller.rb b/app/controllers/api/v1/featured_tags_controller.rb index e4e836c971..c1ead4f540 100644 --- a/app/controllers/api/v1/featured_tags_controller.rb +++ b/app/controllers/api/v1/featured_tags_controller.rb @@ -13,9 +13,7 @@ class Api::V1::FeaturedTagsController < Api::BaseController end def create - @featured_tag = current_account.featured_tags.new(featured_tag_params) - @featured_tag.reset_data - @featured_tag.save! + @featured_tag = current_account.featured_tags.create!(featured_tag_params) render json: @featured_tag, serializer: REST::FeaturedTagSerializer end diff --git a/app/controllers/api/v1/followed_tags_controller.rb b/app/controllers/api/v1/followed_tags_controller.rb new file mode 100644 index 0000000000..f0dfd044cc --- /dev/null +++ b/app/controllers/api/v1/followed_tags_controller.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +class Api::V1::FollowedTagsController < Api::BaseController + TAGS_LIMIT = 100 + + before_action -> { doorkeeper_authorize! :follow, :read, :'read:follows' }, except: :show + before_action :require_user! + before_action :set_results + + after_action :insert_pagination_headers, only: :show + + def index + render json: @results.map(&:tag), each_serializer: REST::TagSerializer, relationships: TagRelationshipsPresenter.new(@results.map(&:tag), current_user&.account_id) + end + + private + + def set_results + @results = TagFollow.where(account: current_account).joins(:tag).eager_load(:tag).to_a_paginated_by_id( + limit_param(TAGS_LIMIT), + params_slice(:max_id, :since_id, :min_id) + ) + end + + def insert_pagination_headers + set_pagination_headers(next_path, prev_path) + end + + def next_path + api_v1_followed_tags_url pagination_params(max_id: pagination_max_id) if records_continue? + end + + def prev_path + api_v1_followed_tags_url pagination_params(since_id: pagination_since_id) unless @results.empty? + end + + def pagination_max_id + @results.last.id + end + + def pagination_since_id + @results.first.id + end + + def records_continue? + @results.size == limit_param(TAG_LIMIT) + end + + def pagination_params(core_params) + params.slice(:limit).permit(:limit).merge(core_params) + end +end diff --git a/app/controllers/api/v1/tags_controller.rb b/app/controllers/api/v1/tags_controller.rb new file mode 100644 index 0000000000..d45015ff5a --- /dev/null +++ b/app/controllers/api/v1/tags_controller.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +class Api::V1::TagsController < Api::BaseController + before_action -> { doorkeeper_authorize! :follow, :write, :'write:follows' }, except: :show + before_action :require_user!, except: :show + before_action :set_or_create_tag + + override_rate_limit_headers :follow, family: :follows + + def show + render json: @tag, serializer: REST::TagSerializer + end + + def follow + TagFollow.create!(tag: @tag, account: current_account, rate_limit: true) + render json: @tag, serializer: REST::TagSerializer + end + + def unfollow + TagFollow.find_by(account: current_account, tag: @tag)&.destroy! + render json: @tag, serializer: REST::TagSerializer + end + + private + + def set_or_create_tag + @tag = Tag.find_normalized(params[:id]) || Tag.new(name: Tag.normalize(params[:id]), display_name: params[:id]) + end +end diff --git a/app/controllers/api/v1/trends/links_controller.rb b/app/controllers/api/v1/trends/links_controller.rb index 2385fe4380..1a9f918f29 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 1f2fff582d..c275d5fc81 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 38003f599a..21adfa2a1f 100644 --- a/app/controllers/api/v1/trends/tags_controller.rb +++ b/app/controllers/api/v1/trends/tags_controller.rb @@ -8,21 +8,29 @@ class Api::V1::Trends::TagsController < Api::BaseController DEFAULT_TAGS_LIMIT = 10 def index - render json: @tags, each_serializer: REST::TagSerializer + render json: @tags, each_serializer: REST::TagSerializer, relationships: TagRelationshipsPresenter.new(@tags, current_user&.account_id) end 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 a89e6835ee..bcc1a07339 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 0f948ff5f8..ee3c5204d8 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -58,14 +58,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 e1dc5eaf6d..9270c467dc 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/controllers/settings/featured_tags_controller.rb b/app/controllers/settings/featured_tags_controller.rb index e805527d07..aadff7c835 100644 --- a/app/controllers/settings/featured_tags_controller.rb +++ b/app/controllers/settings/featured_tags_controller.rb @@ -11,7 +11,6 @@ class Settings::FeaturedTagsController < Settings::BaseController def create @featured_tag = current_account.featured_tags.new(featured_tag_params) - @featured_tag.reset_data if @featured_tag.save redirect_to settings_featured_tags_path diff --git a/app/helpers/accounts_helper.rb b/app/helpers/accounts_helper.rb index d2e1982659..2a17b69e35 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/flavours/glitch/components/status_action_bar.js b/app/javascript/flavours/glitch/components/status_action_bar.js index 1a8e94dac3..d852e00309 100644 --- a/app/javascript/flavours/glitch/components/status_action_bar.js +++ b/app/javascript/flavours/glitch/components/status_action_bar.js @@ -5,10 +5,11 @@ import IconButton from './icon_button'; import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container'; import { defineMessages, injectIntl } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { me, isStaff } from 'flavours/glitch/util/initial_state'; +import { me } from 'flavours/glitch/util/initial_state'; import RelativeTimestamp from './relative_timestamp'; import { accountAdminLink, statusAdminLink } from 'flavours/glitch/util/backend_links'; import classNames from 'classnames'; +import { PERMISSION_MANAGE_USERS } from 'flavours/glitch/permissions'; const messages = defineMessages({ delete: { id: 'status.delete', defaultMessage: 'Delete' }, @@ -47,6 +48,7 @@ class StatusActionBar extends ImmutablePureComponent { static contextTypes = { router: PropTypes.object, + identity: PropTypes.object, }; static propTypes = { @@ -240,7 +242,7 @@ class StatusActionBar extends ImmutablePureComponent { menu.push({ text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick }); menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport }); - if (isStaff && (accountAdminLink || statusAdminLink)) { + if ((this.context.identity.permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS && (accountAdminLink || statusAdminLink)) { menu.push(null); if (accountAdminLink !== undefined) { menu.push({ diff --git a/app/javascript/flavours/glitch/containers/mastodon.js b/app/javascript/flavours/glitch/containers/mastodon.js index 989e37024a..d07b2b3d0e 100644 --- a/app/javascript/flavours/glitch/containers/mastodon.js +++ b/app/javascript/flavours/glitch/containers/mastodon.js @@ -31,6 +31,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/flavours/glitch/features/account/components/header.js b/app/javascript/flavours/glitch/features/account/components/header.js index 45aba53f74..53170b7a6e 100644 --- a/app/javascript/flavours/glitch/features/account/components/header.js +++ b/app/javascript/flavours/glitch/features/account/components/header.js @@ -3,7 +3,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { autoPlayGif, me, isStaff } from 'flavours/glitch/util/initial_state'; +import { autoPlayGif, me } from 'flavours/glitch/util/initial_state'; import { preferencesLink, profileLink, accountAdminLink } from 'flavours/glitch/util/backend_links'; import classNames from 'classnames'; import Icon from 'flavours/glitch/components/icon'; @@ -13,6 +13,7 @@ import Button from 'flavours/glitch/components/button'; import { NavLink } from 'react-router-dom'; import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container'; import AccountNoteContainer from '../containers/account_note_container'; +import { PERMISSION_MANAGE_USERS } from 'flavours/glitch/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, @@ -244,7 +249,7 @@ class Header extends ImmutablePureComponent { } } - if (account.get('id') !== me && isStaff && accountAdminLink) { + if (account.get('id') !== me && (this.context.identity.permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS && accountAdminLink) { menu.push(null); menu.push({ text: intl.formatMessage(messages.admin_account, { name: account.get('username') }), href: accountAdminLink(account.get('id')) }); } diff --git a/app/javascript/flavours/glitch/features/notifications/components/column_settings.js b/app/javascript/flavours/glitch/features/notifications/components/column_settings.js index a8502f5637..42ab9de35b 100644 --- a/app/javascript/flavours/glitch/features/notifications/components/column_settings.js +++ b/app/javascript/flavours/glitch/features/notifications/components/column_settings.js @@ -6,10 +6,14 @@ import ClearColumnButton from './clear_column_button'; import GrantPermissionButton from './grant_permission_button'; import SettingToggle from './setting_toggle'; import PillBarButton from './pill_bar_button'; -import { isStaff } from 'flavours/glitch/util/initial_state'; +import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_REPORTS } from 'flavours/glitch/permissions'; export default class ColumnSettings extends React.PureComponent { + static contextTypes = { + identity: PropTypes.object, + }; + static propTypes = { settings: ImmutablePropTypes.map.isRequired, pushSettings: ImmutablePropTypes.map.isRequired, @@ -167,7 +171,7 @@ export default class ColumnSettings extends React.PureComponent { - {isStaff && ( + {(this.context.identity.permissions & PERMISSION_MANAGE_USERS === PERMISSION_MANAGE_USERS) && (
@@ -180,7 +184,7 @@ export default class ColumnSettings extends React.PureComponent {
)} - {isStaff && ( + {(this.context.identity.permissions & PERMISSION_MANAGE_REPORTS === PERMISSION_MANAGE_REPORTS) && (
diff --git a/app/javascript/flavours/glitch/features/status/components/action_bar.js b/app/javascript/flavours/glitch/features/status/components/action_bar.js index 33ff0ce7e6..31357a4d53 100644 --- a/app/javascript/flavours/glitch/features/status/components/action_bar.js +++ b/app/javascript/flavours/glitch/features/status/components/action_bar.js @@ -4,9 +4,10 @@ import IconButton from 'flavours/glitch/components/icon_button'; import ImmutablePropTypes from 'react-immutable-proptypes'; import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container'; import { defineMessages, injectIntl } from 'react-intl'; -import { me, isStaff } from 'flavours/glitch/util/initial_state'; +import { me } from 'flavours/glitch/util/initial_state'; import { accountAdminLink, statusAdminLink } from 'flavours/glitch/util/backend_links'; import classNames from 'classnames'; +import { PERMISSION_MANAGE_USERS } from 'flavours/glitch/permissions'; const messages = defineMessages({ delete: { id: 'status.delete', defaultMessage: 'Delete' }, @@ -41,6 +42,7 @@ class ActionBar extends React.PureComponent { static contextTypes = { router: PropTypes.object, + identity: PropTypes.object, }; static propTypes = { @@ -182,7 +184,7 @@ class ActionBar extends React.PureComponent { menu.push({ text: intl.formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick }); menu.push({ text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick }); menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport }); - if (isStaff && (accountAdminLink || statusAdminLink)) { + if ((this.context.identity.permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS && (accountAdminLink || statusAdminLink)) { menu.push(null); if (accountAdminLink !== undefined) { menu.push({ diff --git a/app/javascript/flavours/glitch/features/ui/components/link_footer.js b/app/javascript/flavours/glitch/features/ui/components/link_footer.js index 23ae2be82d..acdedaba6b 100644 --- a/app/javascript/flavours/glitch/features/ui/components/link_footer.js +++ b/app/javascript/flavours/glitch/features/ui/components/link_footer.js @@ -3,10 +3,11 @@ import React from 'react'; import PropTypes from 'prop-types'; import { FormattedMessage, defineMessages, injectIntl } from 'react-intl'; import { Link } from 'react-router-dom'; -import { invitesEnabled, limitedFederationMode, version, repository, source_url } from 'flavours/glitch/util/initial_state'; +import { limitedFederationMode, version, repository, source_url } from 'flavours/glitch/util/initial_state'; import { signOutLink, securityLink } from 'flavours/glitch/util/backend_links'; import { logOut } from 'flavours/glitch/util/log_out'; import { openModal } from 'flavours/glitch/actions/modal'; +import { PERMISSION_INVITE_USERS } from 'flavours/glitch/permissions'; const messages = defineMessages({ logoutMessage: { id: 'confirmations.logout.message', defaultMessage: 'Are you sure you want to log out?' }, @@ -28,6 +29,10 @@ export default @injectIntl @connect(null, mapDispatchToProps) class LinkFooter extends React.PureComponent { + static contextTypes = { + identity: PropTypes.object, + }; + static propTypes = { onLogout: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, @@ -46,7 +51,7 @@ class LinkFooter extends React.PureComponent { return (
- {isStaff && ( + {(this.context.identity.permissions & PERMISSION_MANAGE_USERS === PERMISSION_MANAGE_USERS) && (
@@ -179,7 +183,7 @@ export default class ColumnSettings extends React.PureComponent {
)} - {isStaff && ( + {(this.context.identity.permissions & PERMISSION_MANAGE_REPORTS === PERMISSION_MANAGE_REPORTS) && (
diff --git a/app/javascript/mastodon/features/status/components/action_bar.js b/app/javascript/mastodon/features/status/components/action_bar.js index d98b687cb5..be774dfcfe 100644 --- a/app/javascript/mastodon/features/status/components/action_bar.js +++ b/app/javascript/mastodon/features/status/components/action_bar.js @@ -5,8 +5,9 @@ import IconButton from '../../../components/icon_button'; import ImmutablePropTypes from 'react-immutable-proptypes'; import DropdownMenuContainer from '../../../containers/dropdown_menu_container'; import { defineMessages, injectIntl } from 'react-intl'; -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' }, @@ -50,6 +51,7 @@ class ActionBar extends React.PureComponent { static contextTypes = { router: PropTypes.object, + identity: PropTypes.object, }; static propTypes = { @@ -248,7 +250,7 @@ class ActionBar extends React.PureComponent { } } - if (isStaff) { + if ((this.context.identity.permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS) { menu.push(null); menu.push({ text: intl.formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), href: `/admin/accounts/${status.getIn(['account', 'id'])}` }); menu.push({ text: intl.formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses?id=${status.get('id')}` }); diff --git a/app/javascript/mastodon/features/ui/components/link_footer.js b/app/javascript/mastodon/features/ui/components/link_footer.js index edf1104c4e..bbb9b122a3 100644 --- a/app/javascript/mastodon/features/ui/components/link_footer.js +++ b/app/javascript/mastodon/features/ui/components/link_footer.js @@ -3,9 +3,10 @@ import React from 'react'; import PropTypes from 'prop-types'; import { FormattedMessage, defineMessages, injectIntl } from 'react-intl'; import { Link } from 'react-router-dom'; -import { invitesEnabled, limitedFederationMode, version, repository, source_url, profile_directory as profileDirectory } from 'mastodon/initial_state'; +import { limitedFederationMode, version, repository, source_url, profile_directory as profileDirectory } from 'mastodon/initial_state'; import { logOut } from 'mastodon/utils/log_out'; import { openModal } from 'mastodon/actions/modal'; +import { PERMISSION_INVITE_USERS } from 'mastodon/permissions'; const messages = defineMessages({ logoutMessage: { id: 'confirmations.logout.message', defaultMessage: 'Are you sure you want to log out?' }, @@ -27,6 +28,10 @@ export default @injectIntl @connect(null, mapDispatchToProps) class LinkFooter extends React.PureComponent { + static contextTypes = { + identity: PropTypes.object, + }; + static propTypes = { withHotkeys: PropTypes.bool, onLogout: PropTypes.func.isRequired, @@ -48,7 +53,7 @@ class LinkFooter extends React.PureComponent { return (