diff --git a/app/controllers/api/v1/admin/accounts/notes_controller.rb b/app/controllers/api/v1/admin/accounts/notes_controller.rb new file mode 100644 index 00000000000..6db0e1fcbc8 --- /dev/null +++ b/app/controllers/api/v1/admin/accounts/notes_controller.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +class Api::V1::Admin::Accounts::NotesController < Api::BaseController + include Authorization + include AccountableConcern + + PERMITTED_PARAMS = %i( + content + ).freeze + + 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 :set_account + before_action :set_account_moderation_note, except: [:index, :create] + + rescue_from ArgumentError do |e| + render json: { error: e.to_s }, status: 422 + end + + def index + authorize @account, :show? + render json: @account.targeted_moderation_notes.chronological.includes(:account), each_serializer: REST::Admin::ModerationNoteSerializer + end + + def show + authorize @account_moderation_note, :show? + render json: @account_moderation_note, serializer: REST::Admin::ModerationNoteSerializer + end + + def create + authorize AccountModerationNote, :create? + + @account_moderation_note = current_account.account_moderation_notes.new(account_note_params.merge(target_account_id: @account.id)) + @account_moderation_note.save! + + render json: @account_moderation_note, serializer: REST::Admin::ModerationNoteSerializer + end + + def destroy + authorize @account_moderation_note, :destroy? + @account_moderation_note.destroy! + render_empty + end + + private + + def set_account + @account = Account.find(params[:account_id]) + end + + def set_account_moderation_note + @account_moderation_note = AccountModerationNote.where(target_account_id: params[:account_id]).find(params[:id]) + end + + def account_note_params + params + .slice(*PERMITTED_PARAMS) + .permit(*PERMITTED_PARAMS) + end +end diff --git a/app/controllers/api/v1/admin/reports/notes_controller.rb b/app/controllers/api/v1/admin/reports/notes_controller.rb new file mode 100644 index 00000000000..1eabd65772b --- /dev/null +++ b/app/controllers/api/v1/admin/reports/notes_controller.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +class Api::V1::Admin::Reports::NotesController < Api::BaseController + include Authorization + include AccountableConcern + + PERMITTED_PARAMS = %i( + content + ).freeze + + 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 :set_report + before_action :set_report_note, except: [:index, :create] + + rescue_from ArgumentError do |e| + render json: { error: e.to_s }, status: 422 + end + + def index + authorize @report, :show? + render json: @report.notes.chronological.includes(:account), each_serializer: REST::Admin::ModerationNoteSerializer + end + + def show + authorize @report_note, :show? + render json: @report_note, serializer: REST::Admin::ModerationNoteSerializer + end + + def create + authorize ReportNote, :create? + authorize @report, :update? if truthy_param?(:resolve_report) || truthy_param?(:unresolve_report) + + @report_note = current_account.report_notes.new(report_note_params.merge(report_id: @report.id)) + + if @report_note.save! + if truthy_param?(:resolve_report) + @report.resolve!(current_account) + log_action :resolve, @report + elsif truthy_param?(:unresolve_report) + @report.unresolve! + log_action :reopen, @report + end + + render json: @report_note, serializer: REST::Admin::ModerationNoteSerializer + end + end + + def destroy + authorize @report_note, :destroy? + @report_note.destroy! + render_empty + end + + private + + def set_report + @report = Report.find(params[:report_id]) + end + + def set_report_note + @report_note = ReportNote.where(report_id: params[:report_id]).find(params[:id]) + end + + def report_note_params + params + .slice(*PERMITTED_PARAMS) + .permit(*PERMITTED_PARAMS) + end +end diff --git a/app/policies/report_note_policy.rb b/app/policies/report_note_policy.rb index dc31416e8ea..dd7e92da036 100644 --- a/app/policies/report_note_policy.rb +++ b/app/policies/report_note_policy.rb @@ -5,6 +5,10 @@ class ReportNotePolicy < ApplicationPolicy role.can?(:manage_reports) end + def show? + role.can?(:manage_reports) + end + def destroy? owner? || (role.can?(:manage_reports) && role.overrides?(record.account.user_role)) end diff --git a/app/serializers/rest/admin/account_minimal_serializer.rb b/app/serializers/rest/admin/account_minimal_serializer.rb new file mode 100644 index 00000000000..f665b607b28 --- /dev/null +++ b/app/serializers/rest/admin/account_minimal_serializer.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +class REST::Admin::AccountMinimalSerializer < ActiveModel::Serializer + include RoutingHelper + + attributes :id, :username, :acct, :display_name, :uri, :url, :avatar, :avatar_static + + def id + object.id.to_s + end + + def acct + object.pretty_acct + end + + def url + ActivityPub::TagManager.instance.url_for(object) + end + + def uri + ActivityPub::TagManager.instance.uri_for(object) + end + + def avatar + full_asset_url(object.unavailable? ? object.avatar.default_url : object.avatar_original_url) + end + + def avatar_static + full_asset_url(object.unavailable? ? object.avatar.default_url : object.avatar_static_url) + end +end diff --git a/app/serializers/rest/admin/moderation_note_serializer.rb b/app/serializers/rest/admin/moderation_note_serializer.rb new file mode 100644 index 00000000000..b381e7114c7 --- /dev/null +++ b/app/serializers/rest/admin/moderation_note_serializer.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +class REST::Admin::ModerationNoteSerializer < ActiveModel::Serializer + include RoutingHelper + + attributes :id, :content, :created_at, :updated_at, :target + belongs_to :account, serializer: REST::Admin::AccountMinimalSerializer + + def id + object.id.to_s + end + + def content + object.content.strip + end + + def target + case object + when ReportNote + { type: 'Report', id: object.report_id.to_s, url: api_v1_admin_report_url(object.report.id) } + when AccountModerationNote + { type: 'Account', id: object.target_account_id.to_s, url: api_v1_admin_account_url(object.target_account.id) } + end + end +end diff --git a/config/routes/api.rb b/config/routes/api.rb index 34b2e255da6..07ee53de003 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -266,6 +266,7 @@ namespace :api, format: false do end resource :action, only: [:create], controller: 'account_actions' + resources :notes, controller: 'accounts/notes', only: [:index, :show, :create, :destroy] end resources :reports, only: [:index, :update, :show] do @@ -275,6 +276,8 @@ namespace :api, format: false do post :reopen post :resolve end + + resources :notes, controller: 'reports/notes', only: [:index, :show, :create, :destroy] end resources :domain_allows, only: [:index, :show, :create, :destroy]