mirror of
https://github.com/mastodon/mastodon
synced 2024-11-27 22:38:27 +09:00
parent
33144e132d
commit
7696f77245
@ -127,6 +127,7 @@ module Admin
|
|||||||
:by_domain,
|
:by_domain,
|
||||||
:active,
|
:active,
|
||||||
:pending,
|
:pending,
|
||||||
|
:disabled,
|
||||||
:silenced,
|
:silenced,
|
||||||
:suspended,
|
:suspended,
|
||||||
:username,
|
:username,
|
||||||
|
32
app/controllers/api/v1/admin/account_actions_controller.rb
Normal file
32
app/controllers/api/v1/admin/account_actions_controller.rb
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Admin::AccountActionsController < Api::BaseController
|
||||||
|
before_action -> { doorkeeper_authorize! :'admin:write', :'admin:write:accounts' }
|
||||||
|
before_action :require_staff!
|
||||||
|
before_action :set_account
|
||||||
|
|
||||||
|
def create
|
||||||
|
account_action = Admin::AccountAction.new(resource_params)
|
||||||
|
account_action.target_account = @account
|
||||||
|
account_action.current_account = current_account
|
||||||
|
account_action.save!
|
||||||
|
|
||||||
|
render_empty
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_account
|
||||||
|
@account = Account.find(params[:account_id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def resource_params
|
||||||
|
params.permit(
|
||||||
|
:type,
|
||||||
|
:report_id,
|
||||||
|
:warning_preset_id,
|
||||||
|
:text,
|
||||||
|
:send_email_notification
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
128
app/controllers/api/v1/admin/accounts_controller.rb
Normal file
128
app/controllers/api/v1/admin/accounts_controller.rb
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Admin::AccountsController < Api::BaseController
|
||||||
|
include Authorization
|
||||||
|
include AccountableConcern
|
||||||
|
|
||||||
|
LIMIT = 100
|
||||||
|
|
||||||
|
before_action -> { doorkeeper_authorize! :'admin:read', :'admin:read:accounts' }, only: [:index, :show]
|
||||||
|
before_action -> { doorkeeper_authorize! :'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 :insert_pagination_headers, only: :index
|
||||||
|
|
||||||
|
FILTER_PARAMS = %i(
|
||||||
|
local
|
||||||
|
remote
|
||||||
|
by_domain
|
||||||
|
active
|
||||||
|
pending
|
||||||
|
disabled
|
||||||
|
silenced
|
||||||
|
suspended
|
||||||
|
username
|
||||||
|
display_name
|
||||||
|
email
|
||||||
|
ip
|
||||||
|
staff
|
||||||
|
).freeze
|
||||||
|
|
||||||
|
PAGINATION_PARAMS = (%i(limit) + FILTER_PARAMS).freeze
|
||||||
|
|
||||||
|
def index
|
||||||
|
authorize :account, :index?
|
||||||
|
render json: @accounts, each_serializer: REST::Admin::AccountSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
authorize @account, :show?
|
||||||
|
render json: @account, serializer: REST::Admin::AccountSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def enable
|
||||||
|
authorize @account.user, :enable?
|
||||||
|
@account.user.enable!
|
||||||
|
log_action :enable, @account.user
|
||||||
|
render json: @account, serializer: REST::Admin::AccountSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def approve
|
||||||
|
authorize @account.user, :approve?
|
||||||
|
@account.user.approve!
|
||||||
|
render json: @account, serializer: REST::Admin::AccountSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def reject
|
||||||
|
authorize @account.user, :reject?
|
||||||
|
SuspendAccountService.new.call(@account, including_user: true, destroy: true, skip_distribution: true)
|
||||||
|
render json: @account, serializer: REST::Admin::AccountSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def unsilence
|
||||||
|
authorize @account, :unsilence?
|
||||||
|
@account.unsilence!
|
||||||
|
log_action :unsilence, @account
|
||||||
|
render json: @account, serializer: REST::Admin::AccountSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def unsuspend
|
||||||
|
authorize @account, :unsuspend?
|
||||||
|
@account.unsuspend!
|
||||||
|
log_action :unsuspend, @account
|
||||||
|
render json: @account, serializer: REST::Admin::AccountSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_accounts
|
||||||
|
@accounts = filtered_accounts.order(id: :desc).includes(user: [:invite_request, :invite]).paginate_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_account
|
||||||
|
@account = Account.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def filtered_accounts
|
||||||
|
AccountFilter.new(filter_params).results
|
||||||
|
end
|
||||||
|
|
||||||
|
def filter_params
|
||||||
|
params.permit(*FILTER_PARAMS)
|
||||||
|
end
|
||||||
|
|
||||||
|
def insert_pagination_headers
|
||||||
|
set_pagination_headers(next_path, prev_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_path
|
||||||
|
api_v1_admin_accounts_url(pagination_params(max_id: pagination_max_id)) if records_continue?
|
||||||
|
end
|
||||||
|
|
||||||
|
def prev_path
|
||||||
|
api_v1_admin_accounts_url(pagination_params(min_id: pagination_since_id)) unless @accounts.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_max_id
|
||||||
|
@accounts.last.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_since_id
|
||||||
|
@accounts.first.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def records_continue?
|
||||||
|
@accounts.size == limit_param(LIMIT)
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_params(core_params)
|
||||||
|
params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params)
|
||||||
|
end
|
||||||
|
|
||||||
|
def require_local_account!
|
||||||
|
forbidden unless @account.local? && @account.user.present?
|
||||||
|
end
|
||||||
|
end
|
108
app/controllers/api/v1/admin/reports_controller.rb
Normal file
108
app/controllers/api/v1/admin/reports_controller.rb
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Admin::ReportsController < Api::BaseController
|
||||||
|
include Authorization
|
||||||
|
include AccountableConcern
|
||||||
|
|
||||||
|
LIMIT = 100
|
||||||
|
|
||||||
|
before_action -> { doorkeeper_authorize! :'admin:read', :'admin:read:reports' }, only: [:index, :show]
|
||||||
|
before_action -> { doorkeeper_authorize! :'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 :insert_pagination_headers, only: :index
|
||||||
|
|
||||||
|
FILTER_PARAMS = %i(
|
||||||
|
resolved
|
||||||
|
account_id
|
||||||
|
target_account_id
|
||||||
|
).freeze
|
||||||
|
|
||||||
|
PAGINATION_PARAMS = (%i(limit) + FILTER_PARAMS).freeze
|
||||||
|
|
||||||
|
def index
|
||||||
|
authorize :report, :index?
|
||||||
|
render json: @reports, each_serializer: REST::Admin::ReportSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
authorize @report, :show?
|
||||||
|
render json: @report, serializer: REST::Admin::ReportSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def assign_to_self
|
||||||
|
authorize @report, :update?
|
||||||
|
@report.update!(assigned_account_id: current_account.id)
|
||||||
|
log_action :assigned_to_self, @report
|
||||||
|
render json: @report, serializer: REST::Admin::ReportSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def unassign
|
||||||
|
authorize @report, :update?
|
||||||
|
@report.update!(assigned_account_id: nil)
|
||||||
|
log_action :unassigned, @report
|
||||||
|
render json: @report, serializer: REST::Admin::ReportSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def reopen
|
||||||
|
authorize @report, :update?
|
||||||
|
@report.unresolve!
|
||||||
|
log_action :reopen, @report
|
||||||
|
render json: @report, serializer: REST::Admin::ReportSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def resolve
|
||||||
|
authorize @report, :update?
|
||||||
|
@report.resolve!(current_account)
|
||||||
|
log_action :resolve, @report
|
||||||
|
render json: @report, serializer: REST::Admin::ReportSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_reports
|
||||||
|
@reports = filtered_reports.order(id: :desc).with_accounts.paginate_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_report
|
||||||
|
@report = Report.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def filtered_reports
|
||||||
|
ReportFilter.new(filter_params).results
|
||||||
|
end
|
||||||
|
|
||||||
|
def filter_params
|
||||||
|
params.permit(*FILTER_PARAMS)
|
||||||
|
end
|
||||||
|
|
||||||
|
def insert_pagination_headers
|
||||||
|
set_pagination_headers(next_path, prev_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_path
|
||||||
|
api_v1_admin_reports_url(pagination_params(max_id: pagination_max_id)) if records_continue?
|
||||||
|
end
|
||||||
|
|
||||||
|
def prev_path
|
||||||
|
api_v1_admin_reports_url(pagination_params(min_id: pagination_since_id)) unless @reports.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_max_id
|
||||||
|
@reports.last.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_since_id
|
||||||
|
@reports.first.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def records_continue?
|
||||||
|
@reports.size == limit_param(LIMIT)
|
||||||
|
end
|
||||||
|
|
||||||
|
def pagination_params(core_params)
|
||||||
|
params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params)
|
||||||
|
end
|
||||||
|
end
|
@ -106,6 +106,8 @@ class Account < ApplicationRecord
|
|||||||
:confirmed?,
|
:confirmed?,
|
||||||
:approved?,
|
:approved?,
|
||||||
:pending?,
|
:pending?,
|
||||||
|
:disabled?,
|
||||||
|
:role,
|
||||||
:admin?,
|
:admin?,
|
||||||
:moderator?,
|
:moderator?,
|
||||||
:staff?,
|
:staff?,
|
||||||
|
@ -37,6 +37,8 @@ class AccountFilter
|
|||||||
Account.without_suspended
|
Account.without_suspended
|
||||||
when 'pending'
|
when 'pending'
|
||||||
accounts_with_users.merge User.pending
|
accounts_with_users.merge User.pending
|
||||||
|
when 'disabled'
|
||||||
|
accounts_with_users.merge User.disabled
|
||||||
when 'silenced'
|
when 'silenced'
|
||||||
Account.silenced
|
Account.silenced
|
||||||
when 'suspended'
|
when 'suspended'
|
||||||
|
@ -13,6 +13,20 @@ module UserRoles
|
|||||||
admin? || moderator?
|
admin? || moderator?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def role=(value)
|
||||||
|
case value
|
||||||
|
when 'admin'
|
||||||
|
self.admin = true
|
||||||
|
self.moderator = false
|
||||||
|
when 'moderator'
|
||||||
|
self.admin = false
|
||||||
|
self.moderator = true
|
||||||
|
else
|
||||||
|
self.admin = false
|
||||||
|
self.moderator = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def role
|
def role
|
||||||
if admin?
|
if admin?
|
||||||
'admin'
|
'admin'
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
class Report < ApplicationRecord
|
class Report < ApplicationRecord
|
||||||
|
include Paginable
|
||||||
|
|
||||||
belongs_to :account
|
belongs_to :account
|
||||||
belongs_to :target_account, class_name: 'Account'
|
belongs_to :target_account, class_name: 'Account'
|
||||||
belongs_to :action_taken_by_account, class_name: 'Account', optional: true
|
belongs_to :action_taken_by_account, class_name: 'Account', optional: true
|
||||||
@ -26,6 +28,7 @@ class Report < ApplicationRecord
|
|||||||
|
|
||||||
scope :unresolved, -> { where(action_taken: false) }
|
scope :unresolved, -> { where(action_taken: false) }
|
||||||
scope :resolved, -> { where(action_taken: true) }
|
scope :resolved, -> { where(action_taken: true) }
|
||||||
|
scope :with_accounts, -> { includes([:account, :target_account, :action_taken_by_account, :assigned_account].each_with_object({}) { |k, h| h[k] = { user: [:invite_request, :invite] } }) }
|
||||||
|
|
||||||
validates :comment, length: { maximum: 1000 }
|
validates :comment, length: { maximum: 1000 }
|
||||||
|
|
||||||
|
@ -9,9 +9,11 @@ class ReportFilter
|
|||||||
|
|
||||||
def results
|
def results
|
||||||
scope = Report.unresolved
|
scope = Report.unresolved
|
||||||
|
|
||||||
params.each do |key, value|
|
params.each do |key, value|
|
||||||
scope = scope.merge scope_for(key, value)
|
scope = scope.merge scope_for(key, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
scope
|
scope
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -87,6 +87,7 @@ class User < ApplicationRecord
|
|||||||
scope :approved, -> { where(approved: true) }
|
scope :approved, -> { where(approved: true) }
|
||||||
scope :confirmed, -> { where.not(confirmed_at: nil) }
|
scope :confirmed, -> { where.not(confirmed_at: nil) }
|
||||||
scope :enabled, -> { where(disabled: false) }
|
scope :enabled, -> { where(disabled: false) }
|
||||||
|
scope :disabled, -> { where(disabled: true) }
|
||||||
scope :inactive, -> { where(arel_table[:current_sign_in_at].lt(ACTIVE_DURATION.ago)) }
|
scope :inactive, -> { where(arel_table[:current_sign_in_at].lt(ACTIVE_DURATION.ago)) }
|
||||||
scope :active, -> { confirmed.where(arel_table[:current_sign_in_at].gteq(ACTIVE_DURATION.ago)).joins(:account).where(accounts: { suspended_at: nil }) }
|
scope :active, -> { confirmed.where(arel_table[:current_sign_in_at].gteq(ACTIVE_DURATION.ago)).joins(:account).where(accounts: { suspended_at: nil }) }
|
||||||
scope :matches_email, ->(value) { where(arel_table[:email].matches("#{value}%")) }
|
scope :matches_email, ->(value) { where(arel_table[:email].matches("#{value}%")) }
|
||||||
|
77
app/serializers/rest/admin/account_serializer.rb
Normal file
77
app/serializers/rest/admin/account_serializer.rb
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class REST::Admin::AccountSerializer < ActiveModel::Serializer
|
||||||
|
attributes :id, :username, :domain, :created_at,
|
||||||
|
:email, :ip, :role, :confirmed, :suspended,
|
||||||
|
:silenced, :disabled, :approved, :locale,
|
||||||
|
:invite_request
|
||||||
|
|
||||||
|
attribute :created_by_application_id, if: :created_by_application?
|
||||||
|
attribute :invited_by_account_id, if: :invited?
|
||||||
|
|
||||||
|
has_one :account, serializer: REST::AccountSerializer
|
||||||
|
|
||||||
|
def id
|
||||||
|
object.id.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def email
|
||||||
|
object.user_email
|
||||||
|
end
|
||||||
|
|
||||||
|
def ip
|
||||||
|
object.user_current_sign_in_ip.to_s.presence
|
||||||
|
end
|
||||||
|
|
||||||
|
def role
|
||||||
|
object.user_role
|
||||||
|
end
|
||||||
|
|
||||||
|
def suspended
|
||||||
|
object.suspended?
|
||||||
|
end
|
||||||
|
|
||||||
|
def silenced
|
||||||
|
object.silenced?
|
||||||
|
end
|
||||||
|
|
||||||
|
def confirmed
|
||||||
|
object.user_confirmed?
|
||||||
|
end
|
||||||
|
|
||||||
|
def disabled
|
||||||
|
object.user_disabled?
|
||||||
|
end
|
||||||
|
|
||||||
|
def approved
|
||||||
|
object.user_approved?
|
||||||
|
end
|
||||||
|
|
||||||
|
def account
|
||||||
|
object
|
||||||
|
end
|
||||||
|
|
||||||
|
def locale
|
||||||
|
object.user_locale
|
||||||
|
end
|
||||||
|
|
||||||
|
def created_by_application_id
|
||||||
|
object.user&.created_by_application_id&.to_s&.presence
|
||||||
|
end
|
||||||
|
|
||||||
|
def invite_request
|
||||||
|
object.user&.invite_request&.text
|
||||||
|
end
|
||||||
|
|
||||||
|
def invited_by_account_id
|
||||||
|
object.user&.invite&.user&.account_id&.to_s&.presence
|
||||||
|
end
|
||||||
|
|
||||||
|
def invited?
|
||||||
|
object.user&.invited?
|
||||||
|
end
|
||||||
|
|
||||||
|
def created_by_application?
|
||||||
|
object.user&.created_by_application_id&.present?
|
||||||
|
end
|
||||||
|
end
|
16
app/serializers/rest/admin/report_serializer.rb
Normal file
16
app/serializers/rest/admin/report_serializer.rb
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class REST::Admin::ReportSerializer < ActiveModel::Serializer
|
||||||
|
attributes :id, :action_taken, :comment, :created_at, :updated_at
|
||||||
|
|
||||||
|
has_one :account, serializer: REST::Admin::AccountSerializer
|
||||||
|
has_one :target_account, serializer: REST::Admin::AccountSerializer
|
||||||
|
has_one :assigned_account, serializer: REST::Admin::AccountSerializer
|
||||||
|
has_one :action_taken_by_account, serializer: REST::Admin::AccountSerializer
|
||||||
|
|
||||||
|
has_many :statuses, serializer: REST::StatusSerializer
|
||||||
|
|
||||||
|
def id
|
||||||
|
object.id.to_s
|
||||||
|
end
|
||||||
|
end
|
@ -80,7 +80,13 @@ Doorkeeper.configure do
|
|||||||
:'read:search',
|
:'read:search',
|
||||||
:'read:statuses',
|
:'read:statuses',
|
||||||
:follow,
|
:follow,
|
||||||
:push
|
:push,
|
||||||
|
:'admin:read',
|
||||||
|
:'admin:read:accounts',
|
||||||
|
:'admin:read:reports',
|
||||||
|
:'admin:write',
|
||||||
|
:'admin:write:accounts',
|
||||||
|
:'admin:write:reports'
|
||||||
|
|
||||||
# Change the way client credentials are retrieved from the request object.
|
# Change the way client credentials are retrieved from the request object.
|
||||||
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
|
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
|
||||||
|
@ -114,6 +114,12 @@ en:
|
|||||||
application:
|
application:
|
||||||
title: OAuth authorization required
|
title: OAuth authorization required
|
||||||
scopes:
|
scopes:
|
||||||
|
admin:read: read all data on the server
|
||||||
|
admin:read:accounts: read sensitive information of all accounts
|
||||||
|
admin:read:reports: read sensitive information of all reports and reported accounts
|
||||||
|
admin:write: modify all data on the server
|
||||||
|
admin:write:accounts: perform moderation actions on accounts
|
||||||
|
admin:write:reports: perform moderation actions on reports
|
||||||
follow: modify account relationships
|
follow: modify account relationships
|
||||||
push: receive your push notifications
|
push: receive your push notifications
|
||||||
read: read all your account's data
|
read: read all your account's data
|
||||||
|
@ -398,6 +398,29 @@ Rails.application.routes.draw do
|
|||||||
namespace :push do
|
namespace :push do
|
||||||
resource :subscription, only: [:create, :show, :update, :destroy]
|
resource :subscription, only: [:create, :show, :update, :destroy]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
namespace :admin do
|
||||||
|
resources :accounts, only: [:index, :show] do
|
||||||
|
member do
|
||||||
|
post :enable
|
||||||
|
post :unsilence
|
||||||
|
post :unsuspend
|
||||||
|
post :approve
|
||||||
|
post :reject
|
||||||
|
end
|
||||||
|
|
||||||
|
resource :action, only: [:create], controller: 'account_actions'
|
||||||
|
end
|
||||||
|
|
||||||
|
resources :reports, only: [:index, :show] do
|
||||||
|
member do
|
||||||
|
post :assign_to_self
|
||||||
|
post :unassign
|
||||||
|
post :reopen
|
||||||
|
post :resolve
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
namespace :v2 do
|
namespace :v2 do
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe Api::V1::Admin::AccountActionsController, type: :controller do
|
||||||
|
render_views
|
||||||
|
|
||||||
|
let(:role) { 'moderator' }
|
||||||
|
let(:user) { Fabricate(:user, role: role, account: Fabricate(:account, username: 'alice')) }
|
||||||
|
let(:scopes) { 'admin:read admin:write' }
|
||||||
|
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||||
|
let(:account) { Fabricate(:user).account }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(controller).to receive(:doorkeeper_token) { token }
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong scope' do |wrong_scope|
|
||||||
|
let(:scopes) { wrong_scope }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong role' do |wrong_role|
|
||||||
|
let(:role) { wrong_role }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST #create' do
|
||||||
|
before do
|
||||||
|
post :create, params: { account_id: account.id, type: 'disable' }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'user'
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'performs action against account' do
|
||||||
|
expect(account.reload.user_disabled?).to be true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'logs action' do
|
||||||
|
log_item = Admin::ActionLog.last
|
||||||
|
|
||||||
|
expect(log_item).to_not be_nil
|
||||||
|
expect(log_item.action).to eq :disable
|
||||||
|
expect(log_item.account_id).to eq user.account_id
|
||||||
|
expect(log_item.target_id).to eq account.user.id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
147
spec/controllers/api/v1/admin/accounts_controller_spec.rb
Normal file
147
spec/controllers/api/v1/admin/accounts_controller_spec.rb
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe Api::V1::Admin::AccountsController, type: :controller do
|
||||||
|
render_views
|
||||||
|
|
||||||
|
let(:role) { 'moderator' }
|
||||||
|
let(:user) { Fabricate(:user, role: role, account: Fabricate(:account, username: 'alice')) }
|
||||||
|
let(:scopes) { 'admin:read admin:write' }
|
||||||
|
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||||
|
let(:account) { Fabricate(:user).account }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(controller).to receive(:doorkeeper_token) { token }
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong scope' do |wrong_scope|
|
||||||
|
let(:scopes) { wrong_scope }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong role' do |wrong_role|
|
||||||
|
let(:role) { wrong_role }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'GET #index' do
|
||||||
|
before do
|
||||||
|
get :index
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'user'
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'GET #show' do
|
||||||
|
before do
|
||||||
|
get :show, params: { id: account.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'user'
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST #approve' do
|
||||||
|
before do
|
||||||
|
account.user.update(approved: false)
|
||||||
|
post :approve, params: { id: account.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'user'
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'approves user' do
|
||||||
|
expect(account.reload.user_approved?).to be true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST #reject' do
|
||||||
|
before do
|
||||||
|
account.user.update(approved: false)
|
||||||
|
post :reject, params: { id: account.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'user'
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'removes user' do
|
||||||
|
expect(User.where(id: account.user.id).count).to eq 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST #enable' do
|
||||||
|
before do
|
||||||
|
account.user.update(disabled: true)
|
||||||
|
post :enable, params: { id: account.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'user'
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'enables user' do
|
||||||
|
expect(account.reload.user_disabled?).to be false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST #unsuspend' do
|
||||||
|
before do
|
||||||
|
account.touch(:suspended_at)
|
||||||
|
post :unsuspend, params: { id: account.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'user'
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'unsuspends account' do
|
||||||
|
expect(account.reload.suspended?).to be false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST #unsilence' do
|
||||||
|
before do
|
||||||
|
account.touch(:silenced_at)
|
||||||
|
post :unsilence, params: { id: account.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'user'
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'unsilences account' do
|
||||||
|
expect(account.reload.silenced?).to be false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
109
spec/controllers/api/v1/admin/reports_controller_spec.rb
Normal file
109
spec/controllers/api/v1/admin/reports_controller_spec.rb
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe Api::V1::Admin::ReportsController, type: :controller do
|
||||||
|
render_views
|
||||||
|
|
||||||
|
let(:role) { 'moderator' }
|
||||||
|
let(:user) { Fabricate(:user, role: role, account: Fabricate(:account, username: 'alice')) }
|
||||||
|
let(:scopes) { 'admin:read admin:write' }
|
||||||
|
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||||
|
let(:report) { Fabricate(:report) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(controller).to receive(:doorkeeper_token) { token }
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong scope' do |wrong_scope|
|
||||||
|
let(:scopes) { wrong_scope }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'forbidden for wrong role' do |wrong_role|
|
||||||
|
let(:role) { wrong_role }
|
||||||
|
|
||||||
|
it 'returns http forbidden' do
|
||||||
|
expect(response).to have_http_status(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'GET #index' do
|
||||||
|
before do
|
||||||
|
get :index
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'user'
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'GET #show' do
|
||||||
|
before do
|
||||||
|
get :show, params: { id: report.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'user'
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST #resolve' do
|
||||||
|
before do
|
||||||
|
post :resolve, params: { id: report.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'user'
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST #reopen' do
|
||||||
|
before do
|
||||||
|
post :reopen, params: { id: report.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'user'
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST #assign_to_self' do
|
||||||
|
before do
|
||||||
|
post :assign_to_self, params: { id: report.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'user'
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST #unassign' do
|
||||||
|
before do
|
||||||
|
post :unassign, params: { id: report.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'user'
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user