Give admins the ability to add spam role to users via the API (#20445)
This commit is contained in:
parent
e0ba90d60a
commit
81b042ee25
6 changed files with 382 additions and 1718 deletions
|
|
@ -5,7 +5,7 @@ module Api
|
|||
|
||||
# 'suspended' is also known as 'suspend' for historical reasons
|
||||
SUSPEND_MODE = %w[suspend suspended].freeze
|
||||
ROLES = (SUSPEND_MODE + %w[limited]).freeze
|
||||
ROLES = (SUSPEND_MODE + %w[limited spam]).freeze
|
||||
|
||||
before_action :check_role
|
||||
before_action :set_target_user
|
||||
|
|
@ -24,7 +24,7 @@ module Api
|
|||
end
|
||||
|
||||
def destroy
|
||||
# This mechanism for removing roles is pretty specific to limited & suspended,
|
||||
# This mechanism for removing roles is pretty specific to limited, suspended and spam,
|
||||
# where they revert to "Good standing" — we would need a different approach,
|
||||
# possibly a whole different service object — to remove *any* roles
|
||||
remove_role_from_target_user
|
||||
|
|
|
|||
|
|
@ -73,11 +73,11 @@ Rails.application.routes.draw do
|
|||
resources :organizations, only: %i[index create update destroy]
|
||||
|
||||
scope("/users/:id") do
|
||||
constraints(role: /suspend|suspended|limited/) do
|
||||
constraints(role: /suspend|suspended|limited|spam/) do
|
||||
put "/:role", to: "user_roles#update", as: "user_add_role"
|
||||
end
|
||||
|
||||
constraints(role: /limited/) do
|
||||
constraints(role: /limited|spam/) do
|
||||
delete "/:role", to: "user_roles#destroy", as: "user_remove_role"
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -126,6 +126,10 @@ FactoryBot.define do
|
|||
after(:build) { |user| user.add_role(:limited) }
|
||||
end
|
||||
|
||||
trait :spam do
|
||||
after(:build) { |user| user.add_role(:spam) }
|
||||
end
|
||||
|
||||
trait :invited do
|
||||
after(:build) do |user|
|
||||
user.registered = false
|
||||
|
|
|
|||
|
|
@ -182,6 +182,117 @@ notify them."
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "PUT /users/:id/spam" do
|
||||
before do
|
||||
user.add_role(:admin)
|
||||
end
|
||||
|
||||
path "/api/users/{id}/spam" do
|
||||
put "Add spam role for a User" do
|
||||
tags "users"
|
||||
description "This endpoint allows the client to add the spam role to a user.
|
||||
|
||||
The user associated with the API key must have any 'admin' or 'moderator' role.
|
||||
|
||||
This specified user will be assigned the 'spam' role. Addding the spam role to a user will stop the
|
||||
user from posting new posts and comments. It doesn't delete any of the user's content, just
|
||||
prevents them from creating new content while having the spam role. Users are not notified of their spaminess
|
||||
in the UI, so if you want them to know about this, you must notify them"
|
||||
operationId "spamUser"
|
||||
produces "application/json"
|
||||
parameter name: :id, in: :path, required: true,
|
||||
description: "The ID of the user to assign the spam role.",
|
||||
schema: {
|
||||
type: :integer,
|
||||
format: :int32,
|
||||
minimum: 1
|
||||
},
|
||||
example: 1
|
||||
|
||||
response "204", "Spam role assigned to the user successfully" do
|
||||
let(:"api-key") { api_secret.secret }
|
||||
let(:id) { banned_user.id }
|
||||
add_examples
|
||||
|
||||
run_test!
|
||||
end
|
||||
|
||||
response "401", "Unauthorized" do
|
||||
let(:regular_user) { create(:user) }
|
||||
let(:low_security_api_secret) { create(:api_secret, user: regular_user) }
|
||||
let(:"api-key") { low_security_api_secret.secret }
|
||||
let(:id) { banned_user.id }
|
||||
add_examples
|
||||
|
||||
run_test!
|
||||
end
|
||||
|
||||
response "404", "Unknown User ID" do
|
||||
let(:"api-key") { api_secret.secret }
|
||||
let(:id) { 10_000 }
|
||||
add_examples
|
||||
|
||||
run_test!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /users/:id/spam" do
|
||||
before do
|
||||
user.add_role(:admin)
|
||||
end
|
||||
|
||||
path "/api/users/{id}/spam" do
|
||||
delete "Remove spam role from a User" do
|
||||
tags "users"
|
||||
description "This endpoint allows the client to remove the spam role for a user.
|
||||
|
||||
The user associated with the API key must have any 'admin' or 'moderator' role.
|
||||
|
||||
This specified user will be restored to 'general' status. Users are not notified
|
||||
of removing their spam role in the UI, so if you want them to know about this, you must
|
||||
notify them."
|
||||
operationId "unSpamUser"
|
||||
produces "application/json"
|
||||
parameter name: :id, in: :path, required: true,
|
||||
description: "The ID of the user to remove the spam role from.",
|
||||
schema: {
|
||||
type: :integer,
|
||||
format: :int32,
|
||||
minimum: 1
|
||||
},
|
||||
example: 1
|
||||
|
||||
response "204", "Successfully removed the spam role from a user" do
|
||||
let(:"api-key") { api_secret.secret }
|
||||
let(:id) { banned_user.id }
|
||||
add_examples
|
||||
|
||||
run_test!
|
||||
end
|
||||
|
||||
response "401", "Unauthorized" do
|
||||
let(:regular_user) { create(:user) }
|
||||
let(:low_security_api_secret) { create(:api_secret, user: regular_user) }
|
||||
let(:"api-key") { low_security_api_secret.secret }
|
||||
let(:id) { banned_user.id }
|
||||
add_examples
|
||||
|
||||
run_test!
|
||||
end
|
||||
|
||||
response "404", "Unknown User ID" do
|
||||
let(:"api-key") { api_secret.secret }
|
||||
let(:id) { 10_000 }
|
||||
add_examples
|
||||
|
||||
run_test!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
# rubocop:enable RSpec/VariableName
|
||||
|
|
|
|||
|
|
@ -178,4 +178,113 @@ RSpec.describe "Api::V1::UserRoles" do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "PUT /api/users/:id/spam", :aggregate_failures do
|
||||
let(:target_user) { create(:user) }
|
||||
|
||||
before { Audit::Subscribe.listen listener }
|
||||
after { Audit::Subscribe.forget listener }
|
||||
|
||||
context "when unauthenticated" do
|
||||
it "returns unauthorized" do
|
||||
put api_user_add_role_path(target_user, "spam"), headers: headers
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context "when unauthorized" do
|
||||
it "returns unauthorized if api key is invalid" do
|
||||
put api_user_add_role_path(target_user, "spam"),
|
||||
headers: headers.merge({ "api-key" => "invalid api key" })
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
|
||||
# Setup via let(:api_secret) creates a user with no admin privileges
|
||||
it "returns unauthorized if api key belongs to non-admin user" do
|
||||
put api_user_add_role_path(target_user, "spam"), headers: auth_headers
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context "when request is authenticated" do
|
||||
before { api_secret.user.add_role(:super_admin) }
|
||||
|
||||
it "is successful in limiting a user", :aggregate_failures do
|
||||
expect do
|
||||
put api_user_add_role_path(target_user, "spam"), headers: auth_headers
|
||||
|
||||
expect(response).to have_http_status(:no_content)
|
||||
expect(target_user.reload.spam?).to be true
|
||||
expect(Note.last.content).to match(/username\d+ updated username\d+/)
|
||||
end.to change(Note, :count).by(1)
|
||||
end
|
||||
|
||||
it "creates an audit log of the action taken" do
|
||||
put api_user_add_role_path(target_user, "spam"), headers: auth_headers
|
||||
|
||||
log = AuditLog.last
|
||||
expect(log.category).to eq(AuditLog::ADMIN_API_AUDIT_LOG_CATEGORY)
|
||||
expect(log.data["action"]).to eq("api_user_spam")
|
||||
expect(log.data["target_user_id"]).to eq(target_user.id)
|
||||
expect(log.user_id).to eq(api_secret.user.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /api/users/:id/spam", :aggregate_failures do
|
||||
let(:target_user) { create(:user, :spam) }
|
||||
|
||||
before { Audit::Subscribe.listen listener }
|
||||
after { Audit::Subscribe.forget listener }
|
||||
|
||||
context "when unauthenticated" do
|
||||
it "returns unauthorized" do
|
||||
delete api_user_remove_role_path(target_user, "spam"), headers: headers
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context "when unauthorized" do
|
||||
it "returns unauthorized if api key is invalid" do
|
||||
delete api_user_remove_role_path(target_user, "spam"),
|
||||
headers: headers.merge({ "api-key" => "invalid api key" })
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
|
||||
# Setup via let(:api_secret) creates a user with no admin privileges
|
||||
it "returns unauthorized if api key belongs to non-admin user" do
|
||||
delete api_user_remove_role_path(target_user, "spam"), headers: auth_headers
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context "when request is authenticated" do
|
||||
before { api_secret.user.add_role(:super_admin) }
|
||||
|
||||
it "is successful in adding the spam role to a user", :aggregate_failures do
|
||||
expect do
|
||||
delete api_user_remove_role_path(target_user, "spam"), headers: auth_headers
|
||||
|
||||
expect(response).to have_http_status(:no_content)
|
||||
expect(target_user.reload.spam?).to be false
|
||||
expect(target_user.roles).to eq([])
|
||||
expect(Note.last.content).to match(/username\d+ updated username\d+/)
|
||||
end.to change(Note, :count).by(1)
|
||||
end
|
||||
|
||||
it "creates an audit log of the action taken" do
|
||||
delete api_user_remove_role_path(target_user, "spam"), headers: auth_headers
|
||||
|
||||
log = AuditLog.last
|
||||
expect(log.category).to eq(AuditLog::ADMIN_API_AUDIT_LOG_CATEGORY)
|
||||
expect(log.data["action"]).to eq("api_user_remove_spam")
|
||||
expect(log.data["target_user_id"]).to eq(target_user.id)
|
||||
expect(log.user_id).to eq(api_secret.user.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue