DEV: Extend specs coverage for non-admin access to admin endpoints (#18833)

Replace base controller class inheritance specs with explicit specs
for non-staff and moderator access to admin resources
This commit is contained in:
Selase Krakani 2022-11-03 03:42:44 +00:00 committed by GitHub
parent 612ab8710a
commit 52be5b3782
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 7047 additions and 3433 deletions

View File

@ -1,19 +1,65 @@
# frozen_string_literal: true
RSpec.describe Admin::AdminController do
describe '#index' do
it "needs you to be logged in" do
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
describe "#index" do
context "when unauthenticated" do
it "denies access with a 404 response" do
get "/admin.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
it "should return the right response if user isn't a staff" do
sign_in(Fabricate(:user))
get "/admin", params: { api_key: 'asdiasiduga' }
expect(response.status).to eq(404)
context "when authenticated" do
context "as an admin" do
it "permits access with a 200 response" do
sign_in(admin)
get "/admin.json"
get "/admin"
expect(response.status).to eq(404)
expect(response.status).to eq(200)
end
end
context "as a non-admin" do
it "denies access with a 403 response" do
sign_in(moderator)
get "/admin.json"
expect(response.status).to eq(403)
expect(response.parsed_body["errors"]).to include(I18n.t("invalid_access"))
end
end
context "when user is admin with api key" do
it "permits access with a 200 response" do
api_key = Fabricate(:api_key, user: admin)
get "/admin.json", headers: {
HTTP_API_KEY: api_key.key,
HTTP_API_USERNAME: admin.username
}
expect(response.status).to eq(200)
end
end
context "when user is a non-admin with api key" do
it "denies access with a 403 response" do
api_key = Fabricate(:api_key, user: moderator)
get "/admin.json", headers: {
HTTP_API_KEY: api_key.key,
HTTP_API_USERNAME: moderator.username
}
expect(response.status).to eq(403)
expect(response.parsed_body["errors"]).to include(I18n.t("invalid_access"))
end
end
end
end
end

View File

@ -1,47 +1,73 @@
# frozen_string_literal: true
RSpec.describe Admin::ApiController do
it "is a subclass of AdminController" do
expect(Admin::ApiController < Admin::AdminController).to eq(true)
end
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
fab!(:key1, refind: false) { Fabricate(:api_key, description: "my key") }
fab!(:key2, refind: false) { Fabricate(:api_key, user: admin) }
fab!(:key3, refind: false) { Fabricate(:api_key, user: admin) }
context "as an admin" do
before do
sign_in(admin)
end
describe '#index' do
it "succeeds" do
context "when logged in as an admin" do
before { sign_in(admin) }
it "returns keys successfully" do
get "/admin/api/keys.json"
expect(response.status).to eq(200)
expect(response.parsed_body["keys"].length).to eq(3)
end
it "can paginate results" do
get "/admin/api/keys.json?offset=0&limit=2"
expect(response.status).to eq(200)
expect(response.parsed_body["keys"].map { |x| x["id"] }).to contain_exactly(key3.id, key2.id)
get "/admin/api/keys.json?offset=1&limit=2"
expect(response.status).to eq(200)
expect(response.parsed_body["keys"].map { |x| x["id"] }).to contain_exactly(key2.id, key1.id)
get "/admin/api/keys.json?offset=2&limit=2"
expect(response.status).to eq(200)
expect(response.parsed_body["keys"].map { |x| x["id"] }).to contain_exactly(key1.id)
end
end
shared_examples "keys inaccessible" do
it "denies keys access with a 404 response" do
get "/admin/api/keys.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(response.parsed_body["keys"]).to be_nil
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "keys inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "keys inaccessible"
end
end
describe '#show' do
it "succeeds" do
context "when logged in as an admin" do
before { sign_in(admin) }
it "returns key successfully" do
get "/admin/api/keys/#{key1.id}.json"
expect(response.status).to eq(200)
data = response.parsed_body["key"]
expect(data["id"]).to eq(key1.id)
@ -51,7 +77,33 @@ RSpec.describe Admin::ApiController do
end
end
shared_examples "key inaccessible" do
it "denies key access with a 404 response" do
get "/admin/api/keys/#{key1.id}.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(response.parsed_body["key"]).to be_nil
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "key inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "key inaccessible"
end
end
describe '#update' do
context "when logged in as an admin" do
before { sign_in(admin) }
it "allows updating the description" do
original_key = key1.key
@ -82,7 +134,44 @@ RSpec.describe Admin::ApiController do
end
end
shared_examples "key update not allowed" do
it "prevents key updates with a 404 response" do
key1.reload
original_key = key1.key
original_description = key1.description
put "/admin/api/keys/#{key1.id}.json", params: {
key: {
description: "my new description",
key: "overridekey"
}
}
key1.reload
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(key1.description).to eq(original_description)
expect(key1.key).to eq(original_key)
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "key update not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "key update not allowed"
end
end
describe "#destroy" do
context "when logged in as an admin" do
before { sign_in(admin) }
it "works" do
expect(ApiKey.exists?(key1.id)).to eq(true)
@ -96,7 +185,35 @@ RSpec.describe Admin::ApiController do
end
end
shared_examples "key deletion not allowed" do
it "prevents key deletion with a 404 response" do
expect(ApiKey.exists?(key1.id)).to eq(true)
delete "/admin/api/keys/#{key1.id}.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(ApiKey.exists?(key1.id)).to eq(true)
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "key deletion not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "key deletion not allowed"
end
end
describe "#create" do
context "when logged in as an admin" do
before { sign_in(admin) }
it "can create a master key" do
post "/admin/api/keys.json", params: {
key: {
@ -207,7 +324,37 @@ RSpec.describe Admin::ApiController do
end
end
shared_examples "key creation not allowed" do
it "prevents key creation with a 404 response" do
post "/admin/api/keys.json", params: {
key: {
description: "master key description"
}
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(response.parsed_body["key"]).to be_nil
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "key creation not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "key creation not allowed"
end
end
describe "#revoke and #undo_revoke" do
context "when logged in as an admin" do
before { sign_in(admin) }
it "works correctly" do
post "/admin/api/keys/#{key1.id}/revoke.json"
expect(response.status).to eq 200
@ -229,37 +376,79 @@ RSpec.describe Admin::ApiController do
end
end
describe '#scopes' do
it 'includes scopes' do
get '/admin/api/keys/scopes.json'
shared_examples "key revocation/revocation undoing not allowed" do
it "prevents revoking/un-revoking key with a 404 response" do
key1.reload
post "/admin/api/keys/#{key1.id}/revoke.json"
scopes = response.parsed_body['scopes']
expect(scopes.keys).to contain_exactly('topics', 'users', 'email', 'posts', 'uploads', 'global', 'badges', 'categories', 'wordpress')
end
end
end
context "as a moderator" do
before do
sign_in(Fabricate(:moderator))
end
it "doesn't allow access" do
get "/admin/api/keys.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(key1.revoked_at).to eq(nil)
post "/admin/api/keys/#{key1.id}/undo-revoke.json"
get "/admin/api/key/#{key1.id}.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(key1.revoked_at).to eq(nil)
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "key revocation/revocation undoing not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "key revocation/revocation undoing not allowed"
end
end
describe "#scopes" do
context "when logged in as an admin" do
before { sign_in(admin) }
it "includes scopes" do
get "/admin/api/keys/scopes.json"
scopes = response.parsed_body["scopes"]
expect(scopes.keys).to contain_exactly(
"topics",
"users",
"email",
"posts",
"uploads",
"global",
"badges",
"categories",
"wordpress"
)
end
end
shared_examples "key scopes inaccessible" do
it "denies key scopes access with a 404 response" do
get "/admin/api/keys/scopes.json"
post "/admin/api/keys.json", params: {
key: {
description: "master key description"
}
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(response.parsed_body["scopes"]).to be_nil
end
end
expect(ApiKey.count).to eq(3)
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "key scopes inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "key scopes inaccessible"
end
end
end

View File

@ -2,6 +2,9 @@
RSpec.describe Admin::BackupsController do
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
let(:backup_filename) { "2014-02-10-065935.tar.gz" }
let(:backup_filename2) { "2014-02-11-065935.tar.gz" }
@ -23,12 +26,7 @@ RSpec.describe Admin::BackupsController do
end.to_h
end
it "is a subclass of AdminController" do
expect(Admin::BackupsController < Admin::AdminController).to eq(true)
end
before do
sign_in(admin)
SiteSetting.backup_location = BackupLocationSiteSetting::LOCAL
end
@ -40,6 +38,9 @@ RSpec.describe Admin::BackupsController do
end
describe "#index" do
context "when logged in as an admin" do
before { sign_in(admin) }
it "raises an error when backups are disabled" do
SiteSetting.enable_backups = false
get "/admin/backups.json"
@ -73,7 +74,36 @@ RSpec.describe Admin::BackupsController do
end
end
shared_examples "backups inaccessible" do
it "denies access with a 404 response" do
get "/admin/backups.html"
expect(response.status).to eq(404)
get "/admin/backups.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "backups inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "backups inaccessible"
end
end
describe '#status' do
context "when logged in as an admin" do
before { sign_in(admin) }
it "returns the current backups status" do
get "/admin/backups/status.json"
expect(response.body).to eq(BackupRestore.operations_status.to_json)
@ -81,7 +111,32 @@ RSpec.describe Admin::BackupsController do
end
end
shared_examples "status inaccessible" do
it "denies access with a 404 response" do
get "/admin/backups/status.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "status inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "status inaccessible"
end
end
describe '#create' do
context "when logged in as an admin" do
before { sign_in(admin) }
it "starts a backup" do
BackupRestore.expects(:backup!).with(admin.id, { publish_to_message_bus: true, with_uploads: false, client_id: "foo" })
@ -93,7 +148,35 @@ RSpec.describe Admin::BackupsController do
end
end
shared_examples "backups creation not allowed" do
it "prevents backups creation with a 404 response" do
post "/admin/backups.json", params: {
with_uploads: false,
client_id: "foo"
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "backups creation not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "backups creation not allowed"
end
end
describe '#show' do
context "when logged in as an admin" do
before { sign_in(admin) }
it "uses send_file to transmit the backup" do
begin
token = EmailBackupToken.set(admin.id)
@ -126,7 +209,40 @@ RSpec.describe Admin::BackupsController do
end
end
shared_examples "backup inaccessible" do
it "denies access with a 404 response" do
begin
token = EmailBackupToken.set(admin.id)
create_backup_files(backup_filename)
expect do
get "/admin/backups/#{backup_filename}.json", params: { token: token }
end.not_to change { UserHistory.where(action: UserHistory.actions[:backup_download]).count }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(response.headers['Content-Disposition']).not_to match(/attachment; filename/)
end
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "backup inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "backup inaccessible"
end
end
describe '#destroy' do
context "when logged in as an admin" do
before { sign_in(admin) }
it "removes the backup if found" do
begin
path = backup_path(backup_filename)
@ -148,7 +264,41 @@ RSpec.describe Admin::BackupsController do
end
end
shared_examples "backup deletion not allowed" do
it "prevents deletion with a 404 response" do
begin
path = backup_path(backup_filename)
create_backup_files(backup_filename)
expect(File.exist?(path)).to eq(true)
expect do
delete "/admin/backups/#{backup_filename}.json"
end.not_to change { UserHistory.where(action: UserHistory.actions[:backup_destroy]).count }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(File.exist?(path)).to eq(true)
end
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "backup deletion not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "backup deletion not allowed"
end
end
describe '#logs' do
context "when logged in as an admin" do
before { sign_in(admin) }
it "preloads important data" do
get "/admin/backups/logs.html"
expect(response.status).to eq(200)
@ -160,7 +310,31 @@ RSpec.describe Admin::BackupsController do
end
end
shared_examples "backup logs inaccessible" do
it "denies access with a 404 response" do
get "/admin/backups/logs.html"
expect(response.status).to eq(404)
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "backup logs inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "backup logs inaccessible"
end
end
describe '#restore' do
context "when logged in as an admin" do
before { sign_in(admin) }
it "starts a restore" do
BackupRestore.expects(:restore!).with(admin.id, { filename: backup_filename, publish_to_message_bus: true, client_id: "foo" })
@ -170,7 +344,32 @@ RSpec.describe Admin::BackupsController do
end
end
shared_examples "backup restoration not allowed" do
it "prevents restoration with a 404 response" do
post "/admin/backups/#{backup_filename}/restore.json", params: { client_id: "foo" }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "backup restoration not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "backup restoration not allowed"
end
end
describe '#readonly' do
context "when logged in as an admin" do
before { sign_in(admin) }
it "enables readonly mode" do
expect(Discourse.readonly_mode?).to eq(false)
@ -193,7 +392,37 @@ RSpec.describe Admin::BackupsController do
end
end
shared_examples "enabling readonly mode not allowed" do
it "prevents enabling readonly mode with a 404 response" do
expect(Discourse.readonly_mode?).to eq(false)
expect do
put "/admin/backups/readonly.json", params: { enable: true }
end.not_to change { UserHistory.where(action: UserHistory.actions[:change_readonly_mode], new_value: "t").count }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(Discourse.readonly_mode?).to eq(false)
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "enabling readonly mode not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "enabling readonly mode not allowed"
end
end
describe "#upload_backup_chunk" do
context "when logged in as an admin" do
before { sign_in(admin) }
describe "when filename contains invalid characters" do
it "should raise an error" do
['灰色.tar.gz', '; echo \'haha\'.tar.gz'].each do |invalid_filename|
@ -344,14 +573,54 @@ RSpec.describe Admin::BackupsController do
end
end
shared_examples "uploading backup chunk not allowed" do
it "prevents uploading of backup chunk with a 404 response" do
freeze_time
filename = 'test_Site-0123456789.tar.gz'
post "/admin/backups/upload.json", params: {
resumableFilename: filename,
resumableTotalSize: 1,
resumableIdentifier: 'test',
resumableChunkNumber: '1',
resumableChunkSize: '1',
resumableCurrentChunkSize: '1',
file: fixture_file_upload(Tempfile.new)
}
expect_not_enqueued_with(job: :backup_chunks_merger, args: {
filename: filename, identifier: 'test', chunks: 1
}, at: 5.seconds.from_now)
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "uploading backup chunk not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "uploading backup chunk not allowed"
end
end
describe "#check_backup_chunk" do
context "when logged in as an admin" do
before { sign_in(admin) }
describe "when resumableIdentifier is invalid" do
it "should raise an error" do
get "/admin/backups/upload", params: {
resumableIdentifier: "../some_file",
resumableFilename: "test_site-0123456789.tar.gz",
resumableChunkNumber: '1',
resumableCurrentChunkSize: '1'
resumableidentifier: "../some_file",
resumablefilename: "test_site-0123456789.tar.gz",
resumablechunknumber: '1',
resumablecurrentchunksize: '1'
}
expect(response.status).to eq(400)
@ -359,7 +628,36 @@ RSpec.describe Admin::BackupsController do
end
end
shared_examples "checking backup chunk not allowed" do
it "denies access with a 404 response" do
get "/admin/backups/upload", params: {
resumableidentifier: "../some_file",
resumablefilename: "test_site-0123456789.tar.gz",
resumablechunknumber: '1',
resumablecurrentchunksize: '1'
}
expect(response.status).to eq(404)
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "checking backup chunk not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "checking backup chunk not allowed"
end
end
describe '#rollback' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'should rollback the restore' do
BackupRestore.expects(:rollback!)
@ -374,7 +672,32 @@ RSpec.describe Admin::BackupsController do
end
end
shared_examples "backup rollback not allowed" do
it "prevents rollbacks with a 404 response" do
post "/admin/backups/rollback.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "backup rollback not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "backup rollback not allowed"
end
end
describe '#cancel' do
context "when logged in as an admin" do
before { sign_in(admin) }
it "should cancel an backup" do
BackupRestore.expects(:cancel!)
@ -389,7 +712,32 @@ RSpec.describe Admin::BackupsController do
end
end
shared_examples "backup cancellation not allowed" do
it "prevents cancellation with a 404 response" do
delete "/admin/backups/cancel.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "backup cancellation not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "backup cancellation not allowed"
end
end
describe "#email" do
context "when logged in as an admin" do
before { sign_in(admin) }
it "enqueues email job" do
# might as well test this here if we really want www.example.com
@ -415,6 +763,33 @@ RSpec.describe Admin::BackupsController do
end
end
shared_examples "backup emails not allowed" do
it "prevents sending backup emails with a 404 response" do
SiteSetting.force_hostname = "www.example.com"
create_backup_files(backup_filename)
expect do
put "/admin/backups/#{backup_filename}.json"
end.not_to change { Jobs::DownloadBackupEmail.jobs.size }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "backup emails not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "backup emails not allowed"
end
end
describe "S3 multipart uploads" do
let(:upload_type) { "backup" }
let(:test_bucket_prefix) { "test_#{ENV['TEST_ENV_NUMBER'].presence || '0'}" }
@ -432,12 +807,8 @@ RSpec.describe Admin::BackupsController do
)
end
context "when the user is not admin" do
before do
admin.update(admin: false)
end
it "errors with invalid access error" do
shared_examples "multipart uploads not allowed" do
it "prevents multipart uploads with a 404 response" do
post "/admin/backups/create-multipart.json", params: {
file_name: "test.tar.gz",
upload_type: upload_type,
@ -447,7 +818,21 @@ RSpec.describe Admin::BackupsController do
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "multipart uploads not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "multipart uploads not allowed"
end
context "when the user is admin" do
before { sign_in(admin) }
def stub_create_multipart_backup_request
BackupRestore::S3BackupStore.any_instance.stubs(:temporary_upload_path).returns(
"temp/default/#{test_bucket_prefix}/28fccf8259bbe75b873a2bd2564b778c/2u98j832nx93272x947823.gz"

View File

@ -1,22 +1,47 @@
# frozen_string_literal: true
RSpec.describe Admin::BadgesController do
context "while logged in as an admin" do
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user, email: 'user1@test.com', username: 'username1') }
fab!(:badge) { Fabricate(:badge) }
before do
sign_in(admin)
end
describe '#index' do
it 'returns badge index' do
context "when logged in as an admin" do
before { sign_in(admin) }
it "returns badge index" do
get "/admin/badges.json"
expect(response.status).to eq(200)
end
end
shared_examples "badges inaccessible" do
it "denies access to badges with a 404 response" do
get "/admin/badges.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "badges inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "badges inaccessible"
end
end
describe '#preview' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'allows preview enable_badge_sql is enabled' do
SiteSetting.enable_badge_sql = true
@ -39,7 +64,36 @@ RSpec.describe Admin::BadgesController do
end
end
shared_examples "badge preview inaccessible" do
it "denies access to badge preview with a 404 response" do
SiteSetting.enable_badge_sql = true
post "/admin/badges/preview.json", params: {
sql: 'select id as user_id, created_at granted_at from users'
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "badge preview inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "badge preview inaccessible"
end
end
describe '#create' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'can create badges correctly' do
SiteSetting.enable_badge_sql = true
@ -56,7 +110,36 @@ RSpec.describe Admin::BadgesController do
end
end
shared_examples "badge creation not allowed" do
it "prevents badge creation with a 404 response" do
SiteSetting.enable_badge_sql = true
post "/admin/badges.json", params: {
name: 'test', query: 'select 1 as user_id, null as granted_at', badge_type_id: 1
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "badge creation not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "badge creation not allowed"
end
end
describe '#save_badge_groupings' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'can save badge groupings' do
groupings = BadgeGrouping.all.order(:position).to_a
groupings << BadgeGrouping.new(name: 'Test 1')
@ -78,7 +161,41 @@ RSpec.describe Admin::BadgesController do
end
end
shared_examples "badge grouping creation not allowed" do
it "prevents creation of badge groupings with a 404 response" do
groupings = BadgeGrouping.all.order(:position).to_a
groupings << BadgeGrouping.new(name: "Test 1")
groupings << BadgeGrouping.new(name: "Test 2")
groupings.shuffle!
names = groupings.map { |g| g.name }
ids = groupings.map { |g| g.id.to_s }
post "/admin/badges/badge_groupings.json", params: { ids: ids, names: names }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "badge grouping creation not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "badge grouping creation not allowed"
end
end
describe '#badge_types' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'returns JSON' do
get "/admin/badges/types.json"
@ -87,7 +204,32 @@ RSpec.describe Admin::BadgesController do
end
end
shared_examples "badge types inaccessible" do
it "denies access to badge types with a 404 response" do
get "/admin/badges/types.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "badge types inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "badge types inaccessible"
end
end
describe '#destroy' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'deletes the badge' do
delete "/admin/badges/#{badge.id}.json"
expect(response.status).to eq(200)
@ -96,7 +238,33 @@ RSpec.describe Admin::BadgesController do
end
end
shared_examples "badge deletion not allowed" do
it "prevents deletion of badges with a 404 response" do
delete "/admin/badges/#{badge.id}.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(Badge.where(id: badge.id).exists?).to eq(true)
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "badge deletion not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "badge deletion not allowed"
end
end
describe '#update' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'does not update the name of system badges' do
editor_badge = Badge.find(Badge::Editor)
editor_badge_name = editor_badge.name
@ -180,8 +348,49 @@ RSpec.describe Admin::BadgesController do
end
end
shared_examples "badge update not allowed" do
it "prevents badge update with a 404 response" do
SiteSetting.enable_badge_sql = true
sql = "select id user_id, created_at granted_at from users"
image = Fabricate(:upload)
put "/admin/badges/#{badge.id}.json", params: {
name: "123456",
query: sql,
badge_type_id: badge.badge_type_id,
allow_title: false,
multiple_grant: false,
enabled: true,
image_upload_id: image.id,
icon: "fa-rocket",
}
badge.reload
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(badge.name).not_to eq('123456')
expect(badge.query).not_to eq(sql)
expect(badge.icon).not_to eq("fa-rocket")
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "badge update not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "badge update not allowed"
end
end
describe '#mass_award' do
fab!(:user) { Fabricate(:user, email: 'user1@test.com', username: 'username1') }
context "when logged in as an admin" do
before { sign_in(admin) }
it 'does nothing when there is no file' do
post "/admin/badges/award/#{badge.id}.json", params: { file: '' }
@ -359,5 +568,29 @@ RSpec.describe Admin::BadgesController do
end
end
end
shared_examples "mass badge award not allowed" do
it "prevents mass badge award with a 404 response" do
file = file_from_fixtures('user_emails.csv', 'csv')
post "/admin/badges/award/#{badge.id}.json", params: { file: fixture_file_upload(file) }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(UserBadge.where(user: user, badge: badge).count).to eq(0)
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "mass badge award not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "mass badge award not allowed"
end
end
end

View File

@ -1,12 +1,10 @@
# frozen_string_literal: true
RSpec.describe Admin::ColorSchemesController do
it "is a subclass of AdminController" do
expect(described_class < Admin::AdminController).to eq(true)
end
context "while logged in as an admin" do
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
let(:valid_params) { { color_scheme: {
name: 'Such Design',
colors: [
@ -16,11 +14,10 @@ RSpec.describe Admin::ColorSchemesController do
}
} }
before do
sign_in(admin)
end
describe "#index" do
context "when logged in as an admin" do
before { sign_in(admin) }
it "returns JSON" do
scheme_name = Fabricate(:color_scheme).name
get "/admin/color_schemes.json"
@ -36,7 +33,32 @@ RSpec.describe Admin::ColorSchemesController do
end
end
shared_examples "color schemes inaccessible" do
it "denies access with a 404 response" do
get "/admin/color_schemes.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "color schemes inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "color schemes inaccessible"
end
end
describe "#create" do
context "when logged in as an admin" do
before { sign_in(admin) }
it "returns JSON" do
post "/admin/color_schemes.json", params: valid_params
@ -55,9 +77,39 @@ RSpec.describe Admin::ColorSchemesController do
end
end
shared_examples "color scheme creation not allowed" do
it "prevents creation with a 404 response" do
params = valid_params
params[:color_scheme][:colors][0][:hex] = 'cool color please'
expect do
post "/admin/color_schemes.json", params: valid_params
end.not_to change { ColorScheme.count }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "color scheme creation not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "color scheme creation not allowed"
end
end
describe "#update" do
fab!(:existing) { Fabricate(:color_scheme) }
context "when logged in as an admin" do
before { sign_in(admin) }
it "returns success" do
put "/admin/color_schemes/#{existing.id}.json", params: valid_params
expect(response.status).to eq(200)
@ -84,9 +136,34 @@ RSpec.describe Admin::ColorSchemesController do
end
end
shared_examples "color scheme update not allowed" do
it "prevents update with a 404 response" do
put "/admin/color_schemes/#{existing.id}.json", params: valid_params
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "color scheme update not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "color scheme update not allowed"
end
end
describe "#destroy" do
fab!(:existing) { Fabricate(:color_scheme) }
context "when logged in as an admin" do
before { sign_in(admin) }
it "returns success" do
expect {
delete "/admin/color_schemes/#{existing.id}.json"
@ -94,5 +171,26 @@ RSpec.describe Admin::ColorSchemesController do
expect(response.status).to eq(200)
end
end
shared_examples "color scheme deletion not allowed" do
it "prevents deletion with a 404 response" do
delete "/admin/color_schemes/#{existing.id}.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "color scheme deletion not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "color scheme deletion not allowed"
end
end
end

View File

@ -1,60 +1,116 @@
# frozen_string_literal: true
RSpec.describe Admin::DashboardController do
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
before do
AdminDashboardData.stubs(:fetch_cached_stats).returns(reports: [])
Jobs::VersionCheck.any_instance.stubs(:execute).returns(true)
end
it "is a subclass of StaffController" do
expect(Admin::DashboardController < Admin::StaffController).to eq(true)
end
context 'while logged in as an admin' do
fab!(:admin) { Fabricate(:admin) }
def populate_new_features
sample_features = [
{ "id" => "1", "emoji" => "🤾", "title" => "Cool Beans", "description" => "Now beans are included", "created_at" => Time.zone.now - 40.minutes },
{ "id" => "2", "emoji" => "🙈", "title" => "Fancy Legumes", "description" => "Legumes too!", "created_at" => Time.zone.now - 20.minutes }
{
"id" => "1",
"emoji" => "🤾",
"title" => "Cool Beans",
"description" => "Now beans are included",
"created_at" => Time.zone.now - 40.minutes
},
{
"id" => "2",
"emoji" => "🙈",
"title" => "Fancy Legumes",
"description" => "Legumes too!",
"created_at" => Time.zone.now - 20.minutes
}
]
Discourse.redis.set('new_features', MultiJson.dump(sample_features))
end
before do
sign_in(admin)
end
describe '#index' do
context 'when version checking is enabled' do
before do
SiteSetting.version_checks = true
end
it 'returns discourse version info' do
shared_examples "version info present" do
it "returns discourse version info" do
get "/admin/dashboard.json"
expect(response.status).to eq(200)
expect(response.parsed_body['version_check']).to be_present
expect(response.parsed_body["version_check"]).to be_present
end
end
context 'when version checking is disabled' do
shared_examples "version info absent" do
before do
SiteSetting.version_checks = false
end
it 'does not return discourse version info' do
it "does not return discourse version info" do
get "/admin/dashboard.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json['version_check']).not_to be_present
expect(json["version_check"]).not_to be_present
end
end
context "when logged in as an admin" do
before { sign_in(admin) }
context "when version checking is enabled" do
before do
SiteSetting.version_checks = true
end
include_examples "version info present"
end
context "when version checking is disabled" do
before do
SiteSetting.version_checks = false
end
include_examples "version info absent"
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
context "when version checking is enabled" do
before do
SiteSetting.version_checks = true
end
include_examples "version info present"
end
context "when version checking is disabled" do
before do
SiteSetting.version_checks = false
end
include_examples "version info absent"
end
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "denies access with a 404 response" do
get "/admin/dashboard.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
end
describe '#problems' do
context "when logged in as an admin" do
before { sign_in(admin) }
context 'when there are no problems' do
before do
AdminDashboardData.stubs(:fetch_problems).returns([])
@ -85,8 +141,40 @@ RSpec.describe Admin::DashboardController do
end
end
describe '#new_features' do
context "when logged in as a moderator" do
before do
sign_in(moderator)
AdminDashboardData
.stubs(:fetch_problems)
.returns(['Not enough awesome', 'Too much sass'])
end
it 'returns a list of problems' do
get "/admin/dashboard/problems.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json['problems'].size).to eq(2)
expect(json['problems']).to contain_exactly('Not enough awesome', 'Too much sass')
end
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "denies access with a 404 response" do
get "/admin/dashboard/problems.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
end
describe '#new_features' do
context "when logged in as an admin" do
before do
sign_in(admin)
Discourse.redis.del "new_features_last_seen_user_#{admin.id}"
Discourse.redis.del "new_features"
end
@ -131,7 +219,39 @@ RSpec.describe Admin::DashboardController do
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
it 'includes new features when available' do
populate_new_features
get "/admin/dashboard/new-features.json"
json = response.parsed_body
expect(json['new_features'].length).to eq(2)
expect(json['new_features'][0]["emoji"]).to eq("🙈")
expect(json['new_features'][0]["title"]).to eq("Fancy Legumes")
expect(json['has_unseen_features']).to eq(true)
end
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "denies access with a 404 response" do
get "/admin/dashboard/new-features.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
end
describe '#mark_new_features_as_seen' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'resets last seen for a given user' do
populate_new_features
put "/admin/dashboard/mark-new-features-as-seen.json"
@ -141,5 +261,30 @@ RSpec.describe Admin::DashboardController do
expect(DiscourseUpdates.has_unseen_features?(admin.id)).to eq(false)
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
it "resets last seen for moderator" do
populate_new_features
put "/admin/dashboard/mark-new-features-as-seen.json"
expect(response.status).to eq(200)
expect(DiscourseUpdates.new_features_last_seen(moderator.id)).not_to eq(nil)
expect(DiscourseUpdates.has_unseen_features?(moderator.id)).to eq(false)
end
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "prevents marking new feature as seen with a 404 response" do
put "/admin/dashboard/mark-new-features-as-seen.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
end
end

View File

@ -2,18 +2,14 @@
RSpec.describe Admin::EmailController do
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
fab!(:email_log) { Fabricate(:email_log) }
describe '#index' do
context "when logged in as an admin" do
before do
sign_in(admin)
end
it "is a subclass of AdminController" do
expect(Admin::EmailController < Admin::AdminController).to eq(true)
end
describe '#index' do
before do
Admin::EmailController.any_instance
.expects(:action_mailer_settings)
.returns(
@ -32,6 +28,29 @@ RSpec.describe Admin::EmailController do
end
end
shared_examples "email settings inaccessible" do
it "denies access with a 404 response" do
get "/admin/email.json"
expect(response.status).to eq(404)
expect(response.parsed_body["settings"]).to be_nil
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "email settings inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "email settings inaccessible"
end
end
describe '#sent' do
fab!(:post) { Fabricate(:post) }
fab!(:email_log) { Fabricate(:email_log, post: post) }
@ -40,6 +59,9 @@ RSpec.describe Admin::EmailController do
Fabricate(:post_reply_key, post: post, user: email_log.user)
end
context "when logged in as an admin" do
before { sign_in(admin) }
it "should return the right response" do
email_log
get "/admin/email/sent.json"
@ -103,11 +125,36 @@ RSpec.describe Admin::EmailController do
end
end
shared_examples "sent emails inaccessible" do
it "denies access with a 404 response" do
get "/admin/email/sent.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "sent emails inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "sent emails inaccessible"
end
end
describe '#skipped' do
fab!(:user) { Fabricate(:user) }
# fab!(:user) { Fabricate(:user) }
fab!(:log1) { Fabricate(:skipped_email_log, user: user, created_at: 20.minutes.ago) }
fab!(:log2) { Fabricate(:skipped_email_log, created_at: 10.minutes.ago) }
context "when logged in as an admin" do
before { sign_in(admin) }
it "succeeds" do
get "/admin/email/skipped.json"
@ -119,7 +166,7 @@ RSpec.describe Admin::EmailController do
expect(logs.last["id"]).to eq(log1.id)
end
describe 'when filtered by username' do
context "when filtered by username" do
it 'should return the right response' do
get "/admin/email/skipped.json", params: {
user: user.username
@ -135,7 +182,32 @@ RSpec.describe Admin::EmailController do
end
end
shared_examples "skipped emails inaccessible" do
it "denies access with a 404 response" do
get "/admin/email/skipped.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "skipped emails inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "skipped emails inaccessible"
end
end
describe '#test' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'raises an error without the email parameter' do
post "/admin/email/test.json"
expect(response.status).to eq(400)
@ -194,7 +266,32 @@ RSpec.describe Admin::EmailController do
end
end
shared_examples "email tests not allowed" do
it "prevents email tests with a 404 response" do
post "/admin/email/test.json", params: { email_address: 'eviltrout@test.domain' }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "email tests not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "email tests not allowed"
end
end
describe '#preview_digest' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'raises an error without the last_seen_at parameter' do
get "/admin/email/preview-digest.json"
expect(response.status).to eq(400)
@ -216,7 +313,34 @@ RSpec.describe Admin::EmailController do
end
end
shared_examples "preview digest inaccessible" do
it "denies access with a 404 response" do
get "/admin/email/preview-digest.json", params: {
last_seen_at: 1.week.ago, username: moderator.username
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "preview digest inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "preview digest inaccessible"
end
end
describe '#handle_mail' do
context "when logged in as an admin" do
before { sign_in(admin) }
it "returns a bad request if neither email parameter is present" do
post "/admin/email/handle_mail.json"
expect(response.status).to eq(400)
@ -252,7 +376,32 @@ RSpec.describe Admin::EmailController do
end
end
shared_examples "email handling not allowed" do
it "prevents email handling with a 404 response" do
post "/admin/email/handle_mail.json", params: { email_encoded: Base64.strict_encode64(email('cc')) }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "email handling not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "email handling not allowed"
end
end
describe '#rejected' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'should provide a string for a blank error' do
Fabricate(:incoming_email, error: "")
get "/admin/email/rejected.json"
@ -262,7 +411,32 @@ RSpec.describe Admin::EmailController do
end
end
shared_examples "rejected emails inaccessible" do
it "denies access with a 404 response" do
get "/admin/email/rejected.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "rejected emails inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "rejected emails inaccessible"
end
end
describe '#incoming' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'should provide a string for a blank error' do
incoming_email = Fabricate(:incoming_email, error: "")
get "/admin/email/incoming/#{incoming_email.id}.json"
@ -272,7 +446,34 @@ RSpec.describe Admin::EmailController do
end
end
shared_examples "incoming emails inaccessible" do
it "denies access with a 404 response" do
incoming_email = Fabricate(:incoming_email, error: "")
get "/admin/email/incoming/#{incoming_email.id}.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "incoming emails inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "incoming emails inaccessible"
end
end
describe '#incoming_from_bounced' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'raises an error when the email log entry does not exist' do
get "/admin/email/incoming_from_bounced/12345.json"
expect(response.status).to eq(404)
@ -358,9 +559,41 @@ RSpec.describe Admin::EmailController do
end
end
shared_examples "bounced incoming emails inaccessible" do
it "denies access with a 404 response" do
email_log = Fabricate(:email_log, bounced: true, bounce_key: SecureRandom.hex)
error_message = "Email::Receiver::BouncedEmailError"
SiteSetting.reply_by_email_address = "replies+%{reply_key}@example.com"
Fabricate(:incoming_email,
is_bounce: true,
error: error_message,
to_addresses: Email::Sender.bounce_address(email_log.bounce_key)
)
get "/admin/email/incoming_from_bounced/#{email_log.id}.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "bounced incoming emails inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "bounced incoming emails inaccessible"
end
end
describe '#advanced_test' do
it 'should ...' do
email = <<~EMAIL
let(:email) do
<<~EMAIL
From: "somebody" <somebody@example.com>
To: someone@example.com
Date: Mon, 3 Dec 2018 00:00:00 -0000
@ -373,7 +606,14 @@ RSpec.describe Admin::EmailController do
This part should be elided.
EMAIL
end
context "when logged in as an admin" do
before { sign_in(admin) }
it 'should ...' do
post "/admin/email/advanced-test.json", params: { email: email }
expect(response.status).to eq(200)
incoming = response.parsed_body
expect(incoming['format']).to eq(1)
@ -381,4 +621,26 @@ RSpec.describe Admin::EmailController do
expect(incoming['elided']).to eq("---\n\nThis part should be elided.")
end
end
shared_examples "advanced email tests not allowed" do
it "prevents advanced email tests with a 404 response" do
post "/admin/email/advanced-test.json", params: { email: email }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "advanced email tests not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "advanced email tests not allowed"
end
end
end

View File

@ -2,23 +2,21 @@
RSpec.describe Admin::EmailStylesController do
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
let(:default_html) { File.read("#{Rails.root}/app/views/email/default_template.html") }
let(:default_css) { "" }
before do
sign_in(admin)
end
after do
SiteSetting.remove_override!(:email_custom_template)
SiteSetting.remove_override!(:email_custom_css)
end
it "is a subclass of AdminController" do
expect(Admin::EmailStylesController < Admin::AdminController).to eq(true)
end
describe 'show' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'returns default values' do
get '/admin/customize/email_style.json'
expect(response.status).to eq(200)
@ -40,6 +38,28 @@ RSpec.describe Admin::EmailStylesController do
end
end
shared_examples "email styles inaccessible" do
it "denies access with a 404 response" do
get '/admin/customize/email_style.json'
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "email styles inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "email styles inaccessible"
end
end
describe 'update' do
let(:valid_params) do
{
@ -48,6 +68,9 @@ RSpec.describe Admin::EmailStylesController do
}
end
context "when logged in as an admin" do
before { sign_in(admin) }
it 'changes the settings' do
SiteSetting.email_custom_css = ".user-name { font-size: 24px; }"
put '/admin/customize/email_style.json', params: { email_style: valid_params }
@ -70,4 +93,26 @@ RSpec.describe Admin::EmailStylesController do
)
end
end
shared_examples "email style update not allowed" do
it "denies access with a 404 response" do
put '/admin/customize/email_style.json', params: { email_style: valid_params }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "email style update not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "email style update not allowed"
end
end
end

View File

@ -18,30 +18,11 @@ RSpec.describe Admin::EmailTemplatesController do
I18n.reload!
end
it "is a subclass of AdminController" do
expect(Admin::EmailTemplatesController < Admin::AdminController).to eq(true)
end
describe "#index" do
it "raises an error if you aren't logged in" do
get '/admin/customize/email_templates.json'
expect(response.status).to eq(404)
end
it "raises an error if you aren't an admin" do
sign_in(user)
get '/admin/customize/email_templates.json'
expect(response.status).to eq(404)
end
it "raises an error if you are a moderator" do
sign_in(moderator)
get "/admin/customize/email_templates.json"
expect(response.status).to eq(404)
end
context "when logged in as an admin" do
before { sign_in(admin) }
it "should work if you are an admin" do
sign_in(admin)
get '/admin/customize/email_templates.json'
expect(response.status).to eq(200)
@ -51,8 +32,6 @@ RSpec.describe Admin::EmailTemplatesController do
end
it 'returns overridden = true if subject or body has translation_overrides record' do
sign_in(admin)
put '/admin/customize/email_templates/user_notifications.admin_login', params: {
email_template: { subject: original_subject, body: original_body }
}, headers: headers
@ -74,34 +53,35 @@ RSpec.describe Admin::EmailTemplatesController do
end
end
shared_examples "email templates inaccessible" do
it "denies access with a 404 response" do
get "/admin/customize/email_templates.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "email templates inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "email templates inaccessible"
end
context "when not logged in" do
include_examples "email templates inaccessible"
end
end
describe "#update" do
it "raises an error if you aren't logged in" do
put '/admin/customize/email_templates/some_id', params: {
email_template: { subject: 'Subject', body: 'Body' }
}, headers: headers
expect(response.status).to eq(404)
end
it "raises an error if you aren't an admin" do
sign_in(user)
put '/admin/customize/email_templates/some_id', params: {
email_template: { subject: 'Subject', body: 'Body' }
}, headers: headers
expect(response.status).to eq(404)
end
it "raises an error if you are a moderator" do
sign_in(moderator)
put "/admin/customize/email_templates/some_id", params: {
email_template: { subject: "Subject", body: "Body" }
}, headers: headers
expect(response.status).to eq(404)
end
context "when logged in as admin" do
before do
sign_in(admin)
end
context "when logged in as an admin" do
before { sign_in(admin) }
it "returns 'not found' when an unknown email template id is used" do
put '/admin/customize/email_templates/non_existent_template', params: {
@ -273,30 +253,37 @@ RSpec.describe Admin::EmailTemplatesController do
end
end
shared_examples "email template update not allowed" do
it "prevents updates with a 404 response" do
put "/admin/customize/email_templates/some_id", params: {
email_template: { subject: 'Subject', body: 'Body' }
}, headers: headers
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "email template update not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "email template update not allowed"
end
context "when not logged in" do
include_examples "email template update not allowed"
end
end
describe "#revert" do
it "raises an error if you aren't logged in" do
delete '/admin/customize/email_templates/some_id', headers: headers
expect(response.status).to eq(404)
end
it "raises an error if you aren't an admin" do
sign_in(user)
delete '/admin/customize/email_templates/some_id', headers: headers
expect(response.status).to eq(404)
end
it "raises an error if you are a moderator" do
sign_in(moderator)
delete "/admin/customize/email_templates/some_id", headers: headers
expect(response.status).to eq(404)
end
context "when logged in as admin" do
before do
sign_in(admin)
end
context "when logged in as an admin" do
before { sign_in(admin) }
it "returns 'not found' when an unknown email template id is used" do
delete '/admin/customize/email_templates/non_existent_template', headers: headers
@ -364,6 +351,30 @@ RSpec.describe Admin::EmailTemplatesController do
end
end
shared_examples "email template reversal not allowed" do
it "prevents reversals with a 404 response" do
delete "/admin/customize/email_templates/some_id", headers: headers
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "email template reversal not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "email template reversal not allowed"
end
context "when not logged in" do
include_examples "email template reversal not allowed"
end
end
it "uses only existing email templates" do

View File

@ -1,19 +1,15 @@
# frozen_string_literal: true
RSpec.describe Admin::EmbeddableHostsController do
it "is a subclass of AdminController" do
expect(Admin::EmbeddableHostsController < Admin::AdminController).to eq(true)
end
context 'while logged in as an admin' do
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
fab!(:embeddable_host) { Fabricate(:embeddable_host) }
before do
sign_in(admin)
end
describe '#create' do
context "when logged in as an admin" do
before { sign_in(admin) }
it "logs embeddable host create" do
post "/admin/embeddable_hosts.json", params: {
embeddable_host: { host: "test.com" }
@ -25,7 +21,34 @@ RSpec.describe Admin::EmbeddableHostsController do
end
end
shared_examples "embeddable host creation not allowed" do
it "prevents embeddable host creation with a 404 response" do
post "/admin/embeddable_hosts.json", params: {
embeddable_host: { host: "test.com" }
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "embeddable host creation not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "embeddable host creation not allowed"
end
end
describe '#update' do
context "when logged in as an admin" do
before { sign_in(admin) }
it "logs embeddable host update" do
category = Fabricate(:category)
@ -41,11 +64,39 @@ RSpec.describe Admin::EmbeddableHostsController do
new_value: "category_id: #{category.id}, class_name: test-class, host: test.com").exists?
expect(history_exists).to eq(true)
end
end
shared_examples "embeddable host update not allowed" do
it "prevents updates with a 404 response" do
category = Fabricate(:category)
put "/admin/embeddable_hosts/#{embeddable_host.id}.json", params: {
embeddable_host: { host: "test.com", class_name: "test-class", category_id: category.id }
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "embeddable host update not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "embeddable host update not allowed"
end
end
describe '#destroy' do
context "when logged in as an admin" do
before { sign_in(admin) }
it "logs embeddable host destroy" do
delete "/admin/embeddable_hosts/#{embeddable_host.id}.json", params: {}
@ -53,5 +104,26 @@ RSpec.describe Admin::EmbeddableHostsController do
expect(UserHistory.where(acting_user_id: admin.id, action: UserHistory.actions[:embeddable_host_destroy]).exists?).to eq(true)
end
end
shared_examples "embeddable host deletion not allowed" do
it "prevents deletion with a 404 response" do
delete "/admin/embeddable_hosts/#{embeddable_host.id}.json", params: {}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "embeddable host deletion not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "embeddable host deletion not allowed"
end
end
end

View File

@ -1,7 +1,87 @@
# frozen_string_literal: true
RSpec.describe Admin::EmbeddingController do
it "is a subclass of AdminController" do
expect(Admin::EmbeddingController < Admin::AdminController).to eq(true)
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
describe "#show" do
context 'when logged in as an admin' do
before { sign_in(admin) }
it "returns embedding" do
get "/admin/customize/embedding.json"
expect(response.status).to eq(200)
expect(response.parsed_body["embedding"]).to be_present
end
end
shared_examples "embedding accessible" do
it "returns embedding" do
get "/admin/customize/embedding.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "embedding accessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "embedding accessible"
end
end
describe "#update" do
context 'when logged in as an admin' do
before { sign_in(admin) }
it "updates embedding" do
put "/admin/customize/embedding.json", params: {
embedding: {
embed_by_username: "system",
embed_post_limit: 200
}
}
expect(response.status).to eq(200)
expect(response.parsed_body["embedding"]["embed_by_username"]).to eq("system")
expect(response.parsed_body["embedding"]["embed_post_limit"]).to eq(200)
end
end
shared_examples "embedding updates not allowed" do
it "prevents updates with a 404 response" do
put "/admin/customize/embedding.json", params: {
embedding: {
embed_by_username: "system",
embed_post_limit: 200
}
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(response.parsed_body["embedding"]).to be_nil
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "embedding updates not allowed"
end
context "when logged in as a moderator" do
before { sign_in(user) }
include_examples "embedding updates not allowed"
end
end
end

View File

@ -2,13 +2,14 @@
RSpec.describe Admin::EmojisController do
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
fab!(:upload) { Fabricate(:upload) }
before do
sign_in(admin)
end
describe '#index' do
context "when logged in as an admin" do
before { sign_in(admin) }
it "returns a list of custom emojis" do
CustomEmoji.create!(name: 'osama-test-emoji', upload: upload)
Emoji.clear_cache
@ -22,8 +23,33 @@ RSpec.describe Admin::EmojisController do
end
end
shared_examples "custom emojis inaccessible" do
it "denies access with a 404 response" do
get "/admin/customize/emojis.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "custom emojis inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "custom emojis inaccessible"
end
end
describe "#create" do
describe 'when upload is invalid' do
context "when logged in as an admin" do
before { sign_in(admin) }
context 'when upload is invalid' do
it 'should publish the right error' do
post "/admin/customize/emojis.json", params: {
@ -37,7 +63,7 @@ RSpec.describe Admin::EmojisController do
end
end
describe 'when emoji name already exists' do
context 'when emoji name already exists' do
it 'should publish the right error' do
CustomEmoji.create!(name: 'test', upload: upload)
@ -126,7 +152,35 @@ RSpec.describe Admin::EmojisController do
end
end
shared_examples "custom emoji creation not allowed" do
it "prevents creation with a 404 response" do
post "/admin/customize/emojis.json", params: {
name: 'test',
file: fixture_file_upload("#{Rails.root}/spec/fixtures/images/logo.png")
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "custom emoji creation not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "custom emoji creation not allowed"
end
end
describe '#destroy' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'should allow an admin to delete a custom emoji' do
custom_emoji = CustomEmoji.create!(name: 'test', upload: upload)
Emoji.clear_cache
@ -137,4 +191,30 @@ RSpec.describe Admin::EmojisController do
end.to change { CustomEmoji.count }.by(-1)
end
end
shared_examples "custom emoji deletion not allowed" do
it "prevents deletion with a 404 response" do
custom_emoji = CustomEmoji.create!(name: 'test', upload: upload)
Emoji.clear_cache
delete "/admin/customize/emojis/#{custom_emoji.name}.json",
params: { name: 'test' }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "custom emoji deletion not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "custom emoji deletion not allowed"
end
end
end

View File

@ -2,17 +2,10 @@
RSpec.describe Admin::GroupsController do
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
fab!(:group) { Fabricate(:group) }
it 'is a subclass of StaffController' do
expect(Admin::UsersController < Admin::StaffController).to eq(true)
end
before do
sign_in(admin)
end
describe '#create' do
let(:group_params) do
{
@ -27,6 +20,9 @@ RSpec.describe Admin::GroupsController do
}
end
context "when logged in as an admin" do
before { sign_in(admin) }
it 'should work' do
post "/admin/groups.json", params: group_params
@ -105,7 +101,65 @@ RSpec.describe Admin::GroupsController do
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
context "with moderators_manage_categories_and_groups enabled" do
before do
SiteSetting.moderators_manage_categories_and_groups = true
end
it "creates group" do
expect do
post "/admin/groups.json", params: group_params
end.to change { Group.count }.by(1)
expect(response.status).to eq(200)
group = Group.last
expect(group.name).to eq('testing')
expect(group.users).to contain_exactly(admin, user)
expect(group.allow_membership_requests).to eq(true)
expect(group.membership_request_template).to eq('Testing')
expect(group.members_visibility_level).to eq(Group.visibility_levels[:staff])
end
end
context "with moderators_manage_categories_and_groups disabled" do
before do
SiteSetting.moderators_manage_categories_and_groups = false
end
it "prevents creation with a 403 response" do
expect do
post "/admin/groups.json", params: group_params
end.to_not change { Group.count }
expect(response.status).to eq(403)
expect(response.parsed_body["errors"]).to include(I18n.t("invalid_access"))
end
end
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "prevents creation with a 404 response" do
expect do
post "/admin/groups.json", params: group_params
end.to_not change { Group.count }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
end
describe '#add_owners' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'should work' do
put "/admin/groups/#{group.id}/owners.json", params: {
group: {
@ -183,10 +237,79 @@ RSpec.describe Admin::GroupsController do
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
context "with moderators_manage_categories_and_groups enabled" do
before do
SiteSetting.moderators_manage_categories_and_groups = true
end
it "adds owners" do
put "/admin/groups/#{group.id}/owners.json", params: {
group: {
usernames: [user.username, admin.username, moderator.username].join(",")
}
}
response_body = response.parsed_body
expect(response.status).to eq(200)
expect(response_body["usernames"]).to contain_exactly(
user.username,
admin.username,
moderator.username
)
expect(group.group_users.where(owner: true).map(&:user))
.to contain_exactly(user, admin, moderator)
end
end
context "with moderators_manage_categories_and_groups disabled" do
before do
SiteSetting.moderators_manage_categories_and_groups = false
end
it "prevents adding of owners with a 403 response" do
put "/admin/groups/#{group.id}/owners.json", params: {
group: {
usernames: [user.username, admin.username, moderator.username].join(",")
}
}
expect(response.status).to eq(403)
expect(response.parsed_body["errors"]).to include(I18n.t("invalid_access"))
expect(group.group_users.where(owner: true).map(&:user))
.to be_empty
end
end
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "prevents adding of owners with a 404 response" do
put "/admin/groups/#{group.id}/owners.json", params: {
group: {
usernames: [user.username, admin.username].join(",")
}
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(group.group_users.where(owner: true).map(&:user))
.to be_empty
end
end
end
describe '#remove_owner' do
let(:user2) { Fabricate(:user) }
let(:user3) { Fabricate(:user) }
context "when logged in as an admin" do
before { sign_in(admin) }
it 'should work' do
group.add_owner(user)
@ -234,10 +357,69 @@ RSpec.describe Admin::GroupsController do
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
context "with moderators_manage_categories_and_groups enabled" do
before do
SiteSetting.moderators_manage_categories_and_groups = true
end
it "removes owner" do
group.add_owner(user)
delete "/admin/groups/#{group.id}/owners.json", params: {
user_id: user.id
}
expect(response.status).to eq(200)
expect(group.group_users.where(owner: true)).to eq([])
end
end
context "with moderators_manage_categories_and_groups disabled" do
before do
SiteSetting.moderators_manage_categories_and_groups = false
end
it "prevents owner removal with a 403 response" do
group.add_owner(user)
delete "/admin/groups/#{group.id}/owners.json", params: {
user_id: user.id
}
expect(response.status).to eq(403)
expect(response.parsed_body["errors"]).to include(I18n.t("invalid_access"))
expect(group.group_users.where(owner: true).map(&:user)).to contain_exactly(user)
end
end
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "prevents owner removal with a 404 response" do
group.add_owner(user)
delete "/admin/groups/#{group.id}/owners.json", params: {
user_id: user.id
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(group.group_users.where(owner: true).map(&:user)).to contain_exactly(user)
end
end
end
describe "#set_primary" do
let(:user2) { Fabricate(:user) }
let(:user3) { Fabricate(:user) }
context "when logged in as an admin" do
before { sign_in(admin) }
it 'sets with multiple users' do
user2.update!(primary_group_id: group.id)
@ -264,7 +446,68 @@ RSpec.describe Admin::GroupsController do
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
context "with moderators_manage_categories_and_groups enabled" do
before do
SiteSetting.moderators_manage_categories_and_groups = true
end
it "sets multiple primary users" do
user2.update!(primary_group_id: group.id)
put "/admin/groups/#{group.id}/primary.json", params: {
group: { usernames: "#{user.username},#{user2.username},#{user3.username}" },
primary: "true"
}
expect(response.status).to eq(200)
expect(User.where(primary_group_id: group.id).size).to eq(3)
end
end
context "with moderators_manage_categories_and_groups disabled" do
before do
SiteSetting.moderators_manage_categories_and_groups = false
end
it "sets multiple primary users" do
user2.update!(primary_group_id: group.id)
put "/admin/groups/#{group.id}/primary.json", params: {
group: { usernames: "#{user.username},#{user2.username},#{user3.username}" },
primary: "true"
}
expect(response.status).to eq(200)
expect(User.where(primary_group_id: group.id).size).to eq(3)
end
end
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "prevents setting of primary user with a 404 response" do
user2.update!(primary_group_id: group.id)
put "/admin/groups/#{group.id}/primary.json", params: {
group: { usernames: "#{user.username},#{user2.username},#{user3.username}" },
primary: "true"
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(User.where(primary_group_id: group.id).size).to eq(1)
end
end
end
describe "#destroy" do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'should return the right response for an invalid group_id' do
max_id = Group.maximum(:id).to_i
delete "/admin/groups/#{max_id + 1}.json"
@ -293,7 +536,7 @@ RSpec.describe Admin::GroupsController do
expect(history.details).to include("name: #{group.name}")
end
describe 'when group is automatic' do
context "when group is automatic" do
it "returns the right response" do
group.update!(automatic: true)
@ -304,7 +547,7 @@ RSpec.describe Admin::GroupsController do
end
end
describe 'for a non automatic group' do
context "when group is not automatic" do
it "returns the right response" do
delete "/admin/groups/#{group.id}.json"
@ -314,7 +557,48 @@ RSpec.describe Admin::GroupsController do
end
end
shared_examples "group deletion not allowed" do
it "prevents deletion with a 404 response" do
expect do
delete "/admin/groups/#{group.id}.json"
end.not_to change { Group.count }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
context "with moderators_manage_categories_and_groups enabled" do
before do
SiteSetting.moderators_manage_categories_and_groups = true
end
include_examples "group deletion not allowed"
end
context "with moderators_manage_categories_and_groups disabled" do
before do
SiteSetting.moderators_manage_categories_and_groups = false
end
include_examples "group deletion not allowed"
end
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "group deletion not allowed"
end
end
describe '#automatic_membership_count' do
context "when logged in as admin" do
before { sign_in(admin) }
it 'returns count of users whose emails match the domain' do
Fabricate(:user, email: 'user1@somedomain.org')
Fabricate(:user, email: 'user1@somedomain.com')
@ -341,104 +625,42 @@ RSpec.describe Admin::GroupsController do
end
end
context "when moderators_manage_categories_and_groups is enabled" do
let(:group_params) do
{
group: {
name: 'testing-as-moderator',
usernames: [admin.username, user.username].join(","),
owner_usernames: [user.username].join(","),
allow_membership_requests: true,
membership_request_template: 'Testing',
members_visibility_level: Group.visibility_levels[:staff]
}
shared_examples "automatic membership count inaccessible" do
it "denies access with a 404 response" do
put "/admin/groups/automatic_membership_count.json", params: {
automatic_membership_email_domains: 'somedomain.org|somedomain.com',
id: group.id
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
context "with moderators_manage_categories_and_groups enabled" do
before do
SiteSetting.moderators_manage_categories_and_groups = true
end
context "when the user is a moderator" do
include_examples "automatic membership count inaccessible"
end
context "with moderators_manage_categories_and_groups disabled" do
before do
user.update!(moderator: true)
sign_in(user)
SiteSetting.moderators_manage_categories_and_groups = false
end
it 'should allow groups to be created' do
post "/admin/groups.json", params: group_params
expect(response.status).to eq(200)
group = Group.last
expect(group.name).to eq('testing-as-moderator')
expect(group.users).to contain_exactly(admin, user)
expect(group.allow_membership_requests).to eq(true)
expect(group.membership_request_template).to eq('Testing')
expect(group.members_visibility_level).to eq(Group.visibility_levels[:staff])
end
it 'should allow group owners to be added' do
put "/admin/groups/#{group.id}/owners.json", params: {
group: {
usernames: [user.username, admin.username].join(",")
}
}
expect(response.status).to eq(200)
response_body = response.parsed_body
expect(response_body["usernames"]).to contain_exactly(user.username, admin.username)
expect(group.group_users.where(owner: true).map(&:user))
.to contain_exactly(user, admin)
end
it 'should allow groups owners to be removed' do
group.add_owner(user)
delete "/admin/groups/#{group.id}/owners.json", params: {
user_id: user.id
}
expect(response.status).to eq(200)
expect(group.group_users.where(owner: true)).to eq([])
include_examples "automatic membership count inaccessible"
end
end
context "when the user is not a moderator or admin" do
before do
user.update!(moderator: false, admin: false)
sign_in(user)
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it 'should not allow groups to be created' do
post "/admin/groups.json", params: group_params
expect(response.status).to eq(404)
end
it 'should not allow group owners to be added' do
put "/admin/groups/#{group.id}/owners.json", params: {
group: {
usernames: [user.username, admin.username].join(",")
}
}
expect(response.status).to eq(404)
end
it 'should not allow groups owners to be removed' do
group.add_owner(user)
delete "/admin/groups/#{group.id}/owners.json", params: {
user_id: user.id
}
expect(response.status).to eq(404)
end
include_examples "automatic membership count inaccessible"
end
end
end

View File

@ -1,28 +1,48 @@
# frozen_string_literal: true
RSpec.describe Admin::ImpersonateController do
it "is a subclass of AdminController" do
expect(Admin::ImpersonateController < Admin::AdminController).to eq(true)
end
context 'while logged in as an admin' do
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
fab!(:another_admin) { Fabricate(:admin) }
before do
sign_in(admin)
end
describe '#index' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'returns success' do
get "/admin/impersonate.json"
expect(response.status).to eq(200)
end
end
shared_examples "impersonation inaccessible" do
it "denies access with a 404 response" do
get "/admin/impersonate.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "impersonation inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "impersonation inaccessible"
end
end
describe '#create' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'requires a username_or_email parameter' do
post "/admin/impersonate.json"
expect(response.status).to eq(400)
@ -58,5 +78,32 @@ RSpec.describe Admin::ImpersonateController do
end
end
end
shared_examples "impersonation not allowed" do
it "prevents impersonation with a with 404 response" do
expect do
post "/admin/impersonate.json", params: { username_or_email: user.username }
end.not_to change { UserHistory.where(action: UserHistory.actions[:impersonate]).count }
expect(response.status).to eq(404)
expect(session[:current_user_id]).to eq(current_user.id)
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "impersonation not allowed" do
let(:current_user) { moderator }
end
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "impersonation not allowed" do
let(:current_user) { user }
end
end
end
end

View File

@ -1,18 +1,14 @@
# frozen_string_literal: true
RSpec.describe Admin::PermalinksController do
it "is a subclass of AdminController" do
expect(Admin::PermalinksController < Admin::AdminController).to eq(true)
end
fab!(:admin) { Fabricate(:admin) }
before do
sign_in(admin)
end
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
describe '#index' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'filters url' do
Fabricate(:permalink, url: "/forum/23")
Fabricate(:permalink, url: "/forum/98")
@ -53,7 +49,32 @@ RSpec.describe Admin::PermalinksController do
end
end
shared_examples "permalinks inaccessible" do
it "denies access with a 404 response" do
get "/admin/permalinks.json", params: { filter: "topic" }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "permalinks inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "permalinks inaccessible"
end
end
describe "#create" do
context "when logged in as an admin" do
before { sign_in(admin) }
it "works for topics" do
topic = Fabricate(:topic)
@ -106,4 +127,34 @@ RSpec.describe Admin::PermalinksController do
expect(Permalink.last).to have_attributes(url: "forums/12", topic_id: nil, post_id: nil, category_id: nil, tag_id: tag.id)
end
end
shared_examples "permalink creation not allowed" do
it "prevents creation with a 404 response" do
topic = Fabricate(:topic)
expect do
post "/admin/permalinks.json", params: {
url: "/topics/771",
permalink_type: "topic_id",
permalink_type_value: topic.id
}
end.not_to change { Permalink.count }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "permalink creation not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "permalink creation not allowed"
end
end
end

View File

@ -1,20 +1,42 @@
# frozen_string_literal: true
RSpec.describe Admin::PluginsController do
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
it "is a subclass of StaffController" do
expect(Admin::PluginsController < Admin::StaffController).to eq(true)
end
describe "#index" do
context "while logged in as an admin" do
before do
sign_in(Fabricate(:admin))
end
before { sign_in(admin) }
it 'should return JSON' do
it "returns plugins" do
get "/admin/plugins.json"
expect(response.status).to eq(200)
expect(response.parsed_body.has_key?('plugins')).to eq(true)
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
it "returns plugins" do
get "/admin/plugins.json"
expect(response.status).to eq(200)
expect(response.parsed_body.has_key?('plugins')).to eq(true)
end
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "denies access with a 404 response" do
get "/admin/plugins.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
end
end

View File

@ -1,19 +1,14 @@
# frozen_string_literal: true
RSpec.describe Admin::ReportsController do
it "is a subclass of StaffController" do
expect(Admin::ReportsController < Admin::StaffController).to eq(true)
end
context 'while logged in as an admin' do
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
before do
sign_in(admin)
end
describe '#bulk' do
context "when logged in as an admin" do
before { sign_in(admin) }
context "with valid params" do
it "renders the reports as JSON" do
Fabricate(:topic)
@ -66,7 +61,45 @@ RSpec.describe Admin::ReportsController do
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
it "returns report" do
Fabricate(:topic)
get "/admin/reports/bulk.json", params: {
reports: {
topics: { limit: 10 },
likes: { limit: 10 }
}
}
expect(response.status).to eq(200)
expect(response.parsed_body["reports"].count).to eq(2)
end
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "denies access with a 404 response" do
get "/admin/reports/bulk.json", params: {
reports: {
topics: { limit: 10 },
not_found: { limit: 10 }
}
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
end
describe '#show' do
context "when logged in as an admin" do
before { sign_in(admin) }
context "with invalid id form" do
let(:invalid_id) { "!!&asdfasdf" }
@ -131,5 +164,29 @@ RSpec.describe Admin::ReportsController do
end
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
it "returns report" do
Fabricate(:topic)
get "/admin/reports/topics.json"
expect(response.status).to eq(200)
expect(response.parsed_body["report"]["total"]).to eq(1)
end
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "denies access with a 404 response" do
get "/admin/reports/topics.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
end
end

View File

@ -1,49 +1,12 @@
# frozen_string_literal: true
RSpec.describe Admin::RobotsTxtController do
it "is a subclass of AdminController" do
expect(described_class < Admin::AdminController).to eq(true)
end
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
context "when logged in as a non-admin user" do
shared_examples "access_forbidden" do
it "can't see #show" do
get "/admin/customize/robots.json"
expect(response.status).to eq(404)
end
it "can't perform #update" do
put "/admin/customize/robots.json", params: { robots_txt: "adasdasd" }
expect(response.status).to eq(404)
expect(SiteSetting.overridden_robots_txt).to eq("")
end
it "can't perform #reset" do
SiteSetting.overridden_robots_txt = "overridden_content"
delete "/admin/customize/robots.json"
expect(response.status).to eq(404)
expect(SiteSetting.overridden_robots_txt).to eq("overridden_content")
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "access_forbidden"
end
context "when logged in as non-staff user" do
before { sign_in(user) }
include_examples "access_forbidden"
end
end
describe "#show" do
context "when logged in as an admin" do
before { sign_in(admin) }
it "returns default content if there are no overrides" do
@ -64,7 +27,30 @@ RSpec.describe Admin::RobotsTxtController do
end
end
shared_examples "robot.txt inaccessible" do
it "denies access with a 404 response" do
get "/admin/customize/robots.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "robot.txt inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "robot.txt inaccessible"
end
end
describe "#update" do
context "when logged in as an admin" do
before { sign_in(admin) }
it "overrides the site's default robots.txt" do
@ -86,7 +72,31 @@ RSpec.describe Admin::RobotsTxtController do
end
end
shared_examples "robot.txt update not allowed" do
it "prevents updates with a 404 response" do
put "/admin/customize/robots.json", params: { robots_txt: "adasdasd" }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(SiteSetting.overridden_robots_txt).to eq("")
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "robot.txt update not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "robot.txt update not allowed"
end
end
describe "#reset" do
context "when logged in as an admin" do
before { sign_in(admin) }
it "resets robots.txt file to the default version" do
@ -99,4 +109,29 @@ RSpec.describe Admin::RobotsTxtController do
expect(SiteSetting.overridden_robots_txt).to eq("")
end
end
shared_examples "robot.txt reset not allowed" do
it "prevents resets with a 404 response" do
SiteSetting.overridden_robots_txt = "overridden_content"
delete "/admin/customize/robots.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(SiteSetting.overridden_robots_txt).to eq("overridden_content")
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "robot.txt reset not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "robot.txt reset not allowed"
end
end
end

View File

@ -1,21 +1,78 @@
# frozen_string_literal: true
RSpec.describe Admin::ScreenedEmailsController do
it "is a subclass of StaffController" do
expect(Admin::ScreenedEmailsController < Admin::StaffController).to eq(true)
end
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
fab!(:screened_email) { Fabricate(:screened_email) }
describe '#index' do
before do
sign_in(Fabricate(:admin))
end
it 'returns JSON' do
Fabricate(:screened_email)
shared_examples "screened emails accessible" do
it "returns screened emails" do
get "/admin/logs/screened_emails.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json.size).to eq(1)
end
end
context "when logged in as an admin" do
before { sign_in(admin) }
include_examples "screened emails accessible"
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "screened emails accessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "denies access with a 404 response" do
get "/admin/logs/screened_emails.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
end
describe "#destroy" do
shared_examples "screened email deletion possible" do
it "deletes screened email" do
expect do
delete "/admin/logs/screened_emails/#{screened_email.id}.json"
end.to change { ScreenedEmail.count }.by(-1)
expect(response.status).to eq(200)
end
end
context "when logged in as an admin" do
before { sign_in(admin) }
include_examples "screened email deletion possible"
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "screened email deletion possible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "prevents deletion with a 404 response" do
delete "/admin/logs/screened_emails/#{screened_email.id}.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
end
end

View File

@ -1,18 +1,12 @@
# frozen_string_literal: true
RSpec.describe Admin::ScreenedIpAddressesController do
it "is a subclass of StaffController" do
expect(Admin::ScreenedIpAddressesController < Admin::StaffController).to eq(true)
end
fab!(:admin) { Fabricate(:admin) }
before do
sign_in(admin)
end
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
describe '#index' do
shared_examples "screened ip addresses accessible" do
it 'filters screened ip addresses' do
Fabricate(:screened_ip_address, ip_address: "1.2.3.4")
Fabricate(:screened_ip_address, ip_address: "1.2.3.5")
@ -44,4 +38,28 @@ RSpec.describe Admin::ScreenedIpAddressesController do
expect(response.parsed_body).to be_blank
end
end
context "when logged in as an admin" do
before { sign_in(admin) }
include_examples "screened ip addresses accessible"
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "screened ip addresses accessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "denies access with a 404 response" do
get "/admin/logs/screened_ip_addresses.json", params: { filter: "1.2.*" }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
end
end

View File

@ -1,21 +1,43 @@
# frozen_string_literal: true
RSpec.describe Admin::ScreenedUrlsController do
it "is a subclass of StaffController" do
expect(Admin::ScreenedUrlsController < Admin::StaffController).to eq(true)
end
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
fab!(:screened_url) { Fabricate(:screened_url) }
describe '#index' do
before do
sign_in(Fabricate(:admin))
end
it 'returns JSON' do
Fabricate(:screened_url)
shared_examples "screened urls accessible" do
it "returns screened urls" do
get "/admin/logs/screened_urls.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json.size).to eq(1)
end
end
context "when logged in as an admin" do
before { sign_in(admin) }
include_examples "screened urls accessible"
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "screened urls accessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "denies access with a 404 response" do
get "/admin/logs/screened_urls.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
end
end

View File

@ -6,44 +6,17 @@ RSpec.describe Admin::SearchLogsController do
fab!(:user) { Fabricate(:user) }
before do
SearchLog.log(term: 'ruby', search_type: :header, ip_address: '127.0.0.1')
SearchLog.log(term: "ruby", search_type: :header, ip_address: "127.0.0.1")
end
after do
SearchLog.clear_debounce_cache!
end
it "is a subclass of StaffController" do
expect(Admin::SearchLogsController < Admin::StaffController).to eq(true)
end
describe "#index" do
it "raises an error if you aren't logged in" do
shared_examples "search logs accessible" do
it "returns search logs" do
get '/admin/logs/search_logs.json'
expect(response.status).to eq(404)
end
it "raises an error if you aren't an admin" do
sign_in(user)
get '/admin/logs/search_logs.json'
expect(response.status).to eq(404)
end
it "should work if you are an admin" do
sign_in(admin)
get '/admin/logs/search_logs.json'
expect(response.status).to eq(200)
json = response.parsed_body
expect(json[0]['term']).to eq('ruby')
expect(json[0]['searches']).to eq(1)
expect(json[0]['ctr']).to eq(0)
end
it "should work if you are a moderator" do
sign_in(moderator)
get "/admin/logs/search_logs.json"
expect(response.status).to eq(200)
@ -54,28 +27,33 @@ RSpec.describe Admin::SearchLogsController do
end
end
context "when logged in as an admin" do
before { sign_in(admin) }
include_examples "search logs accessible"
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "search logs accessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "denies access with a 404 response" do
get "/admin/logs/search_logs.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
end
describe "#term" do
it "raises an error if you aren't logged in" do
get '/admin/logs/search_logs/term.json', params: {
term: "ruby"
}
expect(response.status).to eq(404)
end
it "raises an error if you aren't an admin" do
sign_in(user)
get '/admin/logs/search_logs/term.json', params: {
term: "ruby"
}
expect(response.status).to eq(404)
end
it "should work if you are an admin" do
sign_in(admin)
shared_examples "search log term accessible" do
it "returns search log term" do
get '/admin/logs/search_logs/term.json', params: {
term: "ruby"
}
@ -86,19 +64,31 @@ RSpec.describe Admin::SearchLogsController do
expect(json['term']['type']).to eq('search_log_term')
expect(json['term']['search_result']).to be_present
end
end
it "should work if you are a moderator" do
sign_in(moderator)
context "when logged in as an admin" do
before { sign_in(admin) }
include_examples "search log term accessible"
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "search log term accessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "denies access with a 404 response" do
get "/admin/logs/search_logs/term.json", params: {
term: "ruby"
}
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["term"]["type"]).to eq("search_log_term")
expect(json["term"]["search_result"]).to be_present
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
end
end

View File

@ -1,21 +1,17 @@
# frozen_string_literal: true
RSpec.describe Admin::SiteSettingsController do
it "is a subclass of AdminController" do
expect(Admin::SiteSettingsController < Admin::AdminController).to eq(true)
end
context 'while logged in as an admin' do
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
before do
sign_in(admin)
end
describe "#index" do
context "when logged in as an admin" do
before { sign_in(admin) }
describe '#index' do
it 'returns valid info' do
it "returns valid info" do
get "/admin/site_settings.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["site_settings"].length).to be > 100
@ -28,240 +24,40 @@ RSpec.describe Admin::SiteSettingsController do
end
end
describe '#update' do
shared_examples "site settings inaccessible" do
it "denies access with a 404 response" do
get "/admin/site_settings.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "site settings inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "site settings inaccessible"
end
end
describe "#user_count" do
fab!(:staged_user) { Fabricate(:staged) }
let(:tracking) { NotificationLevels.all[:tracking] }
before do
SiteSetting.setting(:test_setting, "default")
SiteSetting.setting(:test_upload, "", type: :upload)
SiteSetting.refresh!
end
it 'sets the value when the param is present' do
put "/admin/site_settings/test_setting.json", params: {
test_setting: 'hello'
}
expect(response.status).to eq(200)
expect(SiteSetting.test_setting).to eq('hello')
end
it 'works for deprecated settings' do
put "/admin/site_settings/search_tokenize_chinese_japanese_korean.json", params: {
search_tokenize_chinese_japanese_korean: true
}
expect(response.status).to eq(200)
expect(SiteSetting.search_tokenize_chinese).to eq(true)
end
it 'throws an error when trying to change a deprecated setting with override = false' do
SiteSetting.personal_message_enabled_groups = Group::AUTO_GROUPS[:trust_level_4]
put "/admin/site_settings/enable_personal_messages.json", params: {
enable_personal_messages: false
}
expect(response.status).to eq(422)
expect(SiteSetting.personal_message_enabled_groups).to eq(Group::AUTO_GROUPS[:trust_level_4])
end
it 'allows value to be a blank string' do
put "/admin/site_settings/test_setting.json", params: {
test_setting: ''
}
expect(response.status).to eq(200)
expect(SiteSetting.test_setting).to eq('')
end
describe 'default user options' do
let!(:user1) { Fabricate(:user) }
let!(:user2) { Fabricate(:user) }
it 'should update all existing user options' do
SiteSetting.default_email_in_reply_to = true
user2.user_option.email_in_reply_to = true
user2.user_option.save!
put "/admin/site_settings/default_email_in_reply_to.json", params: {
default_email_in_reply_to: false,
update_existing_user: true
}
user2.reload
expect(user2.user_option.email_in_reply_to).to eq(false)
end
it 'should not update existing user options' do
expect {
put "/admin/site_settings/default_email_in_reply_to.json", params: {
default_email_in_reply_to: false
}
}.not_to change { UserOption.where(email_in_reply_to: false).count }
end
it 'should update `email_digests` column in existing user options' do
UserOption.last.update(email_digests: false)
expect {
put "/admin/site_settings/default_email_digest_frequency.json", params: {
default_email_digest_frequency: 30,
update_existing_user: true
}
}.to change { UserOption.where(email_digests: true).count }.by(1)
expect {
put "/admin/site_settings/default_email_digest_frequency.json", params: {
default_email_digest_frequency: 0,
update_existing_user: true
}
}.to change { UserOption.where(email_digests: false).count }.by(User.human_users.count)
end
end
context 'when updating default sidebar categories and tags' do
it 'does not enqueue the backfilling job if update_existing_user param is not present' do
expect_not_enqueued_with(job: :backfill_sidebar_site_settings) do
put "/admin/site_settings/default_sidebar_categories.json", params: {
default_sidebar_categories: "1|2",
}
expect(response.status).to eq(200)
end
end
it 'enqueus the backfilling job if update_existing_user param is present when updating default sidebar tags' do
SiteSetting.default_sidebar_tags = "tag3"
expect_enqueued_with(job: :backfill_sidebar_site_settings, args: { setting_name: 'default_sidebar_tags', new_value: 'tag1|tag2', previous_value: 'tag3' }) do
put "/admin/site_settings/default_sidebar_tags.json", params: {
default_sidebar_tags: "tag1|tag2",
update_existing_user: true
}
expect(response.status).to eq(200)
end
end
it 'enqueus the backfilling job if update_existing_user param is present when updating default sidebar categories' do
SiteSetting.default_sidebar_categories = "3|4"
expect_enqueued_with(job: :backfill_sidebar_site_settings, args: { setting_name: 'default_sidebar_categories', new_value: '1|2', previous_value: '3|4' }) do
put "/admin/site_settings/default_sidebar_categories.json", params: {
default_sidebar_categories: "1|2",
update_existing_user: true
}
expect(response.status).to eq(200)
end
end
end
describe 'default categories' do
fab!(:user1) { Fabricate(:user) }
fab!(:user2) { Fabricate(:user) }
fab!(:staged_user) { Fabricate(:staged) }
let(:watching) { NotificationLevels.all[:watching] }
let(:tracking) { NotificationLevels.all[:tracking] }
let(:category_ids) { 3.times.collect { Fabricate(:category).id } }
before do
SiteSetting.setting(:default_categories_watching, category_ids.first(2).join("|"))
CategoryUser.create!(category_id: category_ids.last, notification_level: tracking, user: user2)
end
after do
SiteSetting.setting(:default_categories_watching, "")
end
it 'should update existing users user preference' do
put "/admin/site_settings/default_categories_watching.json", params: {
default_categories_watching: category_ids.last(2).join("|"),
update_existing_user: true
}
expect(response.status).to eq(200)
expect(CategoryUser.where(category_id: category_ids.first, notification_level: watching).count).to eq(0)
expect(CategoryUser.where(category_id: category_ids.last, notification_level: watching).count).to eq(User.real.where(staged: false).count - 1)
topic = Fabricate(:topic, category_id: category_ids.last)
topic_user1 = Fabricate(:topic_user, topic: topic, notification_level: TopicUser.notification_levels[:watching], notifications_reason_id: TopicUser.notification_reasons[:auto_watch_category])
topic_user2 = Fabricate(:topic_user, topic: topic, notification_level: TopicUser.notification_levels[:watching], notifications_reason_id: TopicUser.notification_reasons[:user_changed])
put "/admin/site_settings/default_categories_watching.json", params: {
default_categories_watching: "",
update_existing_user: true
}
expect(response.status).to eq(200)
expect(CategoryUser.where(category_id: category_ids, notification_level: watching).count).to eq(0)
expect(topic_user1.reload.notification_level).to eq(TopicUser.notification_levels[:regular])
expect(topic_user2.reload.notification_level).to eq(TopicUser.notification_levels[:watching])
end
it 'should not update existing users user preference' do
expect {
put "/admin/site_settings/default_categories_watching.json", params: {
default_categories_watching: category_ids.last(2).join("|")
}
}.not_to change { CategoryUser.where(category_id: category_ids.first, notification_level: watching).count }
expect(response.status).to eq(200)
expect(CategoryUser.where(category_id: category_ids.last, notification_level: watching).count).to eq(0)
topic = Fabricate(:topic, category_id: category_ids.last)
topic_user1 = Fabricate(:topic_user, topic: topic, notification_level: TopicUser.notification_levels[:watching], notifications_reason_id: TopicUser.notification_reasons[:auto_watch_category])
topic_user2 = Fabricate(:topic_user, topic: topic, notification_level: TopicUser.notification_levels[:watching], notifications_reason_id: TopicUser.notification_reasons[:user_changed])
put "/admin/site_settings/default_categories_watching.json", params: {
default_categories_watching: "",
}
expect(response.status).to eq(200)
expect(CategoryUser.where(category_id: category_ids.first, notification_level: watching).count).to eq(0)
expect(topic_user1.reload.notification_level).to eq(TopicUser.notification_levels[:watching])
expect(topic_user2.reload.notification_level).to eq(TopicUser.notification_levels[:watching])
end
end
describe 'default tags' do
fab!(:user1) { Fabricate(:user) }
fab!(:user2) { Fabricate(:user) }
fab!(:staged_user) { Fabricate(:staged) }
let(:watching) { NotificationLevels.all[:watching] }
let(:tracking) { NotificationLevels.all[:tracking] }
let(:tags) { 3.times.collect { Fabricate(:tag) } }
before do
SiteSetting.setting(:default_tags_watching, tags.first(2).pluck(:name).join("|"))
TagUser.create!(tag_id: tags.last.id, notification_level: tracking, user: user2)
end
after do
SiteSetting.setting(:default_tags_watching, "")
end
it 'should update existing users user preference' do
put "/admin/site_settings/default_tags_watching.json", params: {
default_tags_watching: tags.last(2).pluck(:name).join("|"),
update_existing_user: true
}
expect(TagUser.where(tag_id: tags.first.id, notification_level: watching).count).to eq(0)
expect(TagUser.where(tag_id: tags.last.id, notification_level: watching).count).to eq(User.real.where(staged: false).count - 1)
end
it 'should not update existing users user preference' do
expect {
put "/admin/site_settings/default_tags_watching.json", params: {
default_tags_watching: tags.last(2).pluck(:name).join("|")
}
}.not_to change { TagUser.where(tag_id: tags.first.id, notification_level: watching).count }
expect(TagUser.where(tag_id: tags.last.id, notification_level: watching).count).to eq(0)
end
end
describe '#user_count' do
fab!(:user) { Fabricate(:user) }
fab!(:staged_user) { Fabricate(:staged) }
let(:tracking) { NotificationLevels.all[:tracking] }
context "when logged in as an admin" do
before { sign_in(admin) }
it 'should return correct user count for default categories change' do
category_id = Fabricate(:category).id
@ -392,7 +188,266 @@ RSpec.describe Admin::SiteSettingsController do
end
end
describe 'upload site settings' do
shared_examples "user counts inaccessible" do
it "denies access with a 404 response" do
category_id = Fabricate(:category).id
put "/admin/site_settings/default_categories_watching/user_count.json", params: {
default_categories_watching: category_id
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "user counts inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "user counts inaccessible"
end
end
describe '#update' do
before do
SiteSetting.setting(:test_setting, "default")
SiteSetting.setting(:test_upload, "", type: :upload)
SiteSetting.refresh!
end
context "when logged in as an admin" do
before { sign_in(admin) }
it 'sets the value when the param is present' do
put "/admin/site_settings/test_setting.json", params: {
test_setting: 'hello'
}
expect(response.status).to eq(200)
expect(SiteSetting.test_setting).to eq('hello')
end
it 'works for deprecated settings' do
put "/admin/site_settings/search_tokenize_chinese_japanese_korean.json", params: {
search_tokenize_chinese_japanese_korean: true
}
expect(response.status).to eq(200)
expect(SiteSetting.search_tokenize_chinese).to eq(true)
end
it 'throws an error when trying to change a deprecated setting with override = false' do
SiteSetting.personal_message_enabled_groups = Group::AUTO_GROUPS[:trust_level_4]
put "/admin/site_settings/enable_personal_messages.json", params: {
enable_personal_messages: false
}
expect(response.status).to eq(422)
expect(SiteSetting.personal_message_enabled_groups).to eq(Group::AUTO_GROUPS[:trust_level_4])
end
it 'allows value to be a blank string' do
put "/admin/site_settings/test_setting.json", params: {
test_setting: ''
}
expect(response.status).to eq(200)
expect(SiteSetting.test_setting).to eq('')
end
context "with default user options" do
let!(:user1) { Fabricate(:user) }
let!(:user2) { Fabricate(:user) }
it 'should update all existing user options' do
SiteSetting.default_email_in_reply_to = true
user2.user_option.email_in_reply_to = true
user2.user_option.save!
put "/admin/site_settings/default_email_in_reply_to.json", params: {
default_email_in_reply_to: false,
update_existing_user: true
}
user2.reload
expect(user2.user_option.email_in_reply_to).to eq(false)
end
it 'should not update existing user options' do
expect {
put "/admin/site_settings/default_email_in_reply_to.json", params: {
default_email_in_reply_to: false
}
}.not_to change { UserOption.where(email_in_reply_to: false).count }
end
it 'should update `email_digests` column in existing user options' do
UserOption.last.update(email_digests: false)
expect {
put "/admin/site_settings/default_email_digest_frequency.json", params: {
default_email_digest_frequency: 30,
update_existing_user: true
}
}.to change { UserOption.where(email_digests: true).count }.by(1)
expect {
put "/admin/site_settings/default_email_digest_frequency.json", params: {
default_email_digest_frequency: 0,
update_existing_user: true
}
}.to change { UserOption.where(email_digests: false).count }.by(User.human_users.count)
end
end
context 'when updating default sidebar categories and tags' do
it 'does not enqueue the backfilling job if update_existing_user param is not present' do
expect_not_enqueued_with(job: :backfill_sidebar_site_settings) do
put "/admin/site_settings/default_sidebar_categories.json", params: {
default_sidebar_categories: "1|2",
}
expect(response.status).to eq(200)
end
end
it 'enqueus the backfilling job if update_existing_user param is present when updating default sidebar tags' do
SiteSetting.default_sidebar_tags = "tag3"
expect_enqueued_with(job: :backfill_sidebar_site_settings, args: { setting_name: 'default_sidebar_tags', new_value: 'tag1|tag2', previous_value: 'tag3' }) do
put "/admin/site_settings/default_sidebar_tags.json", params: {
default_sidebar_tags: "tag1|tag2",
update_existing_user: true
}
expect(response.status).to eq(200)
end
end
it 'enqueus the backfilling job if update_existing_user param is present when updating default sidebar categories' do
SiteSetting.default_sidebar_categories = "3|4"
expect_enqueued_with(job: :backfill_sidebar_site_settings, args: { setting_name: 'default_sidebar_categories', new_value: '1|2', previous_value: '3|4' }) do
put "/admin/site_settings/default_sidebar_categories.json", params: {
default_sidebar_categories: "1|2",
update_existing_user: true
}
expect(response.status).to eq(200)
end
end
end
context "with default categories" do
fab!(:user1) { Fabricate(:user) }
fab!(:user2) { Fabricate(:user) }
fab!(:staged_user) { Fabricate(:staged) }
let(:watching) { NotificationLevels.all[:watching] }
let(:tracking) { NotificationLevels.all[:tracking] }
let(:category_ids) { 3.times.collect { Fabricate(:category).id } }
before do
SiteSetting.setting(:default_categories_watching, category_ids.first(2).join("|"))
CategoryUser.create!(category_id: category_ids.last, notification_level: tracking, user: user2)
end
after do
SiteSetting.setting(:default_categories_watching, "")
end
it 'should update existing users user preference' do
put "/admin/site_settings/default_categories_watching.json", params: {
default_categories_watching: category_ids.last(2).join("|"),
update_existing_user: true
}
expect(response.status).to eq(200)
expect(CategoryUser.where(category_id: category_ids.first, notification_level: watching).count).to eq(0)
expect(CategoryUser.where(category_id: category_ids.last, notification_level: watching).count).to eq(User.real.where(staged: false).count - 1)
topic = Fabricate(:topic, category_id: category_ids.last)
topic_user1 = Fabricate(:topic_user, topic: topic, notification_level: TopicUser.notification_levels[:watching], notifications_reason_id: TopicUser.notification_reasons[:auto_watch_category])
topic_user2 = Fabricate(:topic_user, topic: topic, notification_level: TopicUser.notification_levels[:watching], notifications_reason_id: TopicUser.notification_reasons[:user_changed])
put "/admin/site_settings/default_categories_watching.json", params: {
default_categories_watching: "",
update_existing_user: true
}
expect(response.status).to eq(200)
expect(CategoryUser.where(category_id: category_ids, notification_level: watching).count).to eq(0)
expect(topic_user1.reload.notification_level).to eq(TopicUser.notification_levels[:regular])
expect(topic_user2.reload.notification_level).to eq(TopicUser.notification_levels[:watching])
end
it 'should not update existing users user preference' do
expect {
put "/admin/site_settings/default_categories_watching.json", params: {
default_categories_watching: category_ids.last(2).join("|")
}
}.not_to change { CategoryUser.where(category_id: category_ids.first, notification_level: watching).count }
expect(response.status).to eq(200)
expect(CategoryUser.where(category_id: category_ids.last, notification_level: watching).count).to eq(0)
topic = Fabricate(:topic, category_id: category_ids.last)
topic_user1 = Fabricate(:topic_user, topic: topic, notification_level: TopicUser.notification_levels[:watching], notifications_reason_id: TopicUser.notification_reasons[:auto_watch_category])
topic_user2 = Fabricate(:topic_user, topic: topic, notification_level: TopicUser.notification_levels[:watching], notifications_reason_id: TopicUser.notification_reasons[:user_changed])
put "/admin/site_settings/default_categories_watching.json", params: {
default_categories_watching: "",
}
expect(response.status).to eq(200)
expect(CategoryUser.where(category_id: category_ids.first, notification_level: watching).count).to eq(0)
expect(topic_user1.reload.notification_level).to eq(TopicUser.notification_levels[:watching])
expect(topic_user2.reload.notification_level).to eq(TopicUser.notification_levels[:watching])
end
end
context "with default tags" do
fab!(:user1) { Fabricate(:user) }
fab!(:user2) { Fabricate(:user) }
fab!(:staged_user) { Fabricate(:staged) }
let(:watching) { NotificationLevels.all[:watching] }
let(:tracking) { NotificationLevels.all[:tracking] }
let(:tags) { 3.times.collect { Fabricate(:tag) } }
before do
SiteSetting.setting(:default_tags_watching, tags.first(2).pluck(:name).join("|"))
TagUser.create!(tag_id: tags.last.id, notification_level: tracking, user: user2)
end
after do
SiteSetting.setting(:default_tags_watching, "")
end
it 'should update existing users user preference' do
put "/admin/site_settings/default_tags_watching.json", params: {
default_tags_watching: tags.last(2).pluck(:name).join("|"),
update_existing_user: true
}
expect(TagUser.where(tag_id: tags.first.id, notification_level: watching).count).to eq(0)
expect(TagUser.where(tag_id: tags.last.id, notification_level: watching).count).to eq(User.real.where(staged: false).count - 1)
end
it 'should not update existing users user preference' do
expect {
put "/admin/site_settings/default_tags_watching.json", params: {
default_tags_watching: tags.last(2).pluck(:name).join("|")
}
}.not_to change { TagUser.where(tag_id: tags.first.id, notification_level: watching).count }
expect(TagUser.where(tag_id: tags.last.id, notification_level: watching).count).to eq(0)
end
end
context "with upload site settings" do
it 'can remove the site setting' do
SiteSetting.test_upload = Fabricate(:upload)
@ -467,5 +522,28 @@ RSpec.describe Admin::SiteSettingsController do
expect(response.status).to eq(422)
end
end
shared_examples "site setting update not allowed" do
it "prevents updates with a 404 response" do
put "/admin/site_settings/test_setting.json", params: {
test_setting: 'hello'
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "site setting update not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "site setting update not allowed"
end
end
end

View File

@ -2,6 +2,7 @@
RSpec.describe Admin::SiteTextsController do
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
let(:default_locale) { I18n.locale }
@ -10,40 +11,10 @@ RSpec.describe Admin::SiteTextsController do
I18n.reload!
end
it "is a subclass of AdminController" do
expect(Admin::SiteTextsController < Admin::AdminController).to eq(true)
end
context "when not logged in as an admin" do
it "raises an error if you aren't logged in" do
put '/admin/customize/site_texts/some_key.json', params: {
site_text: { value: 'foo' }, locale: default_locale
}
expect(response.status).to eq(404)
end
it "raises an error if you aren't an admin" do
sign_in(user)
put "/admin/customize/site_texts/some_key.json", params: {
site_text: { value: 'foo' }, locale: default_locale
}
expect(response.status).to eq(404)
put "/admin/customize/reseed.json", params: {
category_ids: [], topic_ids: []
}
expect(response.status).to eq(404)
end
end
context "when logged in as admin" do
before do
sign_in(admin)
end
describe '#index' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'returns json' do
get "/admin/customize/site_texts.json", params: { q: 'title', locale: default_locale }
expect(response.status).to eq(200)
@ -232,7 +203,32 @@ RSpec.describe Admin::SiteTextsController do
end
end
shared_examples "site texts inaccessible" do
it "denies access with a 404 response" do
get "/admin/customize/site_texts.json", params: { q: 'title', locale: default_locale }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "site texts inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "site texts inaccessible"
end
end
describe '#show' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'returns a site text for a key that exists' do
get "/admin/customize/site_texts/js.topic.list.json", params: { locale: default_locale }
expect(response.status).to eq(200)
@ -373,7 +369,32 @@ RSpec.describe Admin::SiteTextsController do
end
end
shared_examples "site text inaccessible" do
it "denies access with a 404 response" do
get "/admin/customize/site_texts/js.topic.list.json", params: { locale: default_locale }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "site text inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "site text inaccessible"
end
end
describe '#update & #revert' do
context "when logged in as an admin" do
before { sign_in(admin) }
it "returns 'not found' when an unknown key is used" do
put '/admin/customize/site_texts/some_key.json', params: {
site_text: { value: 'foo', locale: default_locale }
@ -551,6 +572,30 @@ RSpec.describe Admin::SiteTextsController do
end
end
shared_examples "site text update not allowed" do
it "prevents updates with a 404 response" do
put "/admin/customize/site_texts/js.emoji_picker.animals_%26_nature.json", params: {
site_text: { value: 'foo', locale: default_locale }
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "site text update not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "site text update not allowed"
end
end
context "when reseeding" do
before do
staff_category = Fabricate(
@ -571,6 +616,9 @@ RSpec.describe Admin::SiteTextsController do
end
describe '#get_reseed_options' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'returns correct json' do
get "/admin/customize/reseed.json"
expect(response.status).to eq(200)
@ -587,7 +635,32 @@ RSpec.describe Admin::SiteTextsController do
end
end
shared_examples "reseed options inaccessible" do
it "denies access with a 404 response" do
get "/admin/customize/reseed.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "reseed options inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "reseed options inaccessible"
end
end
describe '#reseed' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'reseeds categories and topics' do
SiteSetting.default_locale = :de
@ -601,6 +674,30 @@ RSpec.describe Admin::SiteTextsController do
expect(Topic.find(SiteSetting.guidelines_topic_id).title).to eq(I18n.t("guidelines_topic.title", locale: :de))
end
end
shared_examples "reseed not allowed" do
it "prevents reseeds with a 404 response" do
post "/admin/customize/reseed.json", params: {
category_ids: ["staff_category_id"],
topic_ids: ["guidelines_topic_id"]
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "reseed not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "reseed not allowed"
end
end
end
end

View File

@ -1,18 +1,13 @@
# frozen_string_literal: true
RSpec.describe Admin::StaffActionLogsController do
it "is a subclass of StaffController" do
expect(Admin::StaffActionLogsController < Admin::StaffController).to eq(true)
end
fab!(:admin) { Fabricate(:admin) }
before do
sign_in(admin)
end
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
describe '#index' do
it 'generates logs' do
shared_examples "staff action logs accessible" do
it 'returns logs' do
topic = Fabricate(:topic)
StaffActionLogger.new(Discourse.system_user).log_topic_delete_recover(topic, "delete_topic")
@ -28,6 +23,12 @@ RSpec.describe Admin::StaffActionLogsController do
"id" => 'delete_topic', "action_id" => UserHistory.actions[:delete_topic]
)
end
end
context "when logged in as an admin" do
before { sign_in(admin) }
include_examples "staff action logs accessible"
it 'generates logs with pages' do
1.upto(4).each do |idx|
@ -66,8 +67,27 @@ RSpec.describe Admin::StaffActionLogsController do
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "staff action logs accessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "denies access with a 404 response" do
get "/admin/logs/staff_action_logs.json", params: { action_id: UserHistory.actions[:delete_topic] }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
end
describe '#diff' do
it 'can generate diffs for theme changes' do
shared_examples "theme diffs accessible" do
it 'generates diffs for theme changes' do
theme = Fabricate(:theme)
theme.set_field(target: :mobile, name: :scss, value: 'body {.up}')
theme.set_field(target: :common, name: :scss, value: 'omit-dupe')
@ -88,6 +108,12 @@ RSpec.describe Admin::StaffActionLogsController do
expect(parsed["side_by_side"]).not_to include("omit-dupe")
end
end
context "when logged in as an admin" do
before { sign_in(admin) }
include_examples "theme diffs accessible"
it 'is not erroring when current value is empty' do
theme = Fabricate(:theme)
@ -96,4 +122,25 @@ RSpec.describe Admin::StaffActionLogsController do
expect(response.status).to eq(200)
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "theme diffs accessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "denies access with a 404 response" do
theme = Fabricate(:theme)
StaffActionLogger.new(admin).log_theme_destroy(theme)
get "/admin/logs/staff_action_logs/#{UserHistory.last.id}/diff.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
end
end

View File

@ -2,14 +2,8 @@
RSpec.describe Admin::ThemesController do
fab!(:admin) { Fabricate(:admin) }
it "is a subclass of AdminController" do
expect(Admin::ThemesController < Admin::AdminController).to eq(true)
end
before do
sign_in(admin)
end
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
let! :repo do
setup_git_repo(
@ -28,6 +22,9 @@ RSpec.describe Admin::ThemesController do
end
describe '#generate_key_pair' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'can generate key pairs' do
post "/admin/themes/generate_key_pair.json"
expect(response.status).to eq(200)
@ -38,6 +35,28 @@ RSpec.describe Admin::ThemesController do
end
end
shared_examples "key pair generation not allowed" do
it "prevents key pair generation with a 404 response" do
post "/admin/themes/generate_key_pair.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "key pair generation not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "key pair generation not allowed"
end
end
describe '#upload_asset' do
let(:file) { file_from_fixtures("fake.woff2", "woff2") }
let(:filename) { File.basename(file) }
@ -45,6 +64,9 @@ RSpec.describe Admin::ThemesController do
Rack::Test::UploadedFile.new(file)
end
context "when logged in as an admin" do
before { sign_in(admin) }
it 'can create a theme upload' do
post "/admin/themes/upload_asset.json", params: { file: upload }
expect(response.status).to eq(201)
@ -71,7 +93,34 @@ RSpec.describe Admin::ThemesController do
end
end
shared_examples "theme asset upload not allowed" do
it "prevents theme asset upload with a 404 response" do
expect do
post "/admin/themes/upload_asset.json", params: { file: upload }
end.not_to change { Upload.count }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "theme asset upload not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "theme asset upload not allowed"
end
end
describe '#export' do
context "when logged in as an admin" do
before { sign_in(admin) }
it "exports correctly" do
theme = Fabricate(:theme, name: "Awesome Theme")
theme.set_field(target: :common, name: :scss, value: '.body{color: black;}')
@ -101,8 +150,30 @@ RSpec.describe Admin::ThemesController do
end
end
describe '#import' do
shared_examples "theme export not allowed" do
it "prevents theme export with a 404 response" do
theme = Fabricate(:theme, name: "Awesome Theme")
get "/admin/customize/themes/#{theme.id}/export"
expect(response.status).to eq(404)
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "theme export not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "theme export not allowed"
end
end
describe '#import' do
let(:theme_json_file) do
Rack::Test::UploadedFile.new(file_from_fixtures("sam-s-simple-theme.dcstyle.json", "json"), "application/json")
end
@ -115,6 +186,9 @@ RSpec.describe Admin::ThemesController do
file_from_fixtures("logo.png")
end
context "when logged in as an admin" do
before { sign_in(admin) }
context 'when theme allowlist mode is enabled' do
before do
global_setting :allowed_theme_repos, "https://github.com/discourse/discourse-brand-header.git"
@ -127,8 +201,8 @@ RSpec.describe Admin::ThemesController do
remote: ' https://github.com/discourse/discourse-brand-header.git '
}
expect(response.status).to eq(201)
expect(Theme.allowed_remote_theme_ids.length).to eq(1)
expect(response.status).to eq(201)
end
it "prevents adding disallowed themes" do
@ -176,13 +250,6 @@ RSpec.describe Admin::ThemesController do
expect(response.status).to eq(201)
end
it 'should not be able to import a theme by moderator' do
sign_in(Fabricate(:moderator))
post "/admin/themes/import.json", params: { theme: theme_json_file }
expect(response.status).to eq(404)
end
it 'imports a theme' do
post "/admin/themes/import.json", params: { theme: theme_json_file }
expect(response.status).to eq(201)
@ -297,7 +364,32 @@ RSpec.describe Admin::ThemesController do
end
end
shared_examples "theme import not allowed" do
it "prevents theme import with a 404 response" do
post "/admin/themes/import.json", params: { theme: theme_json_file }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "theme import not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "theme import not allowed"
end
end
describe '#index' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'correctly returns themes' do
ColorScheme.destroy_all
Theme.destroy_all
@ -331,7 +423,32 @@ RSpec.describe Admin::ThemesController do
end
end
shared_examples "themes inaccessible" do
it "denies access with a 404 response" do
get "/admin/themes.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "themes inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "themes inaccessible"
end
end
describe '#create' do
context "when logged in as an admin" do
before { sign_in(admin) }
it 'creates a theme' do
post "/admin/themes.json", params: {
theme: {
@ -349,9 +466,41 @@ RSpec.describe Admin::ThemesController do
end
end
shared_examples "theme creation not allowed" do
it "prevents creation with a 404 response" do
expect do
post "/admin/themes.json", params: {
theme: {
name: 'my test name',
theme_fields: [name: 'scss', target: 'common', value: 'body{color: red;}']
}
}
end.not_to change { Theme.count }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "theme creation not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "theme creation not allowed"
end
end
describe '#update' do
let!(:theme) { Fabricate(:theme) }
context "when logged in as an admin" do
before { sign_in(admin) }
it 'returns the right response when an invalid id is given' do
put "/admin/themes/99999.json"
@ -671,9 +820,39 @@ RSpec.describe Admin::ThemesController do
end
end
shared_examples "theme update not allowed" do
it "prevents updates with a 404 response" do
SiteSetting.default_theme_id = -1
put "/admin/themes/#{theme.id}.json", params: {
id: theme.id, theme: { default: true }
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(SiteSetting.default_theme_id).not_to eq(theme.id)
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "theme update not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "theme update not allowed"
end
end
describe '#destroy' do
let!(:theme) { Fabricate(:theme) }
context "when logged in as an admin" do
before { sign_in(admin) }
it 'returns the right response when an invalid id is given' do
delete "/admin/themes/9999.json"
@ -695,7 +874,33 @@ RSpec.describe Admin::ThemesController do
end
end
shared_examples "theme deletion not allowed" do
it "prevent deletion with a 404 response" do
delete "/admin/themes/#{theme.id}.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(theme.reload).to be_present
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "theme deletion not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "theme deletion not allowed"
end
end
describe '#preview' do
context "when logged in as an admin" do
before { sign_in(admin) }
it "should return the right response when an invalid id is given" do
get "/admin/themes/9999/preview.json"
@ -703,6 +908,30 @@ RSpec.describe Admin::ThemesController do
end
end
shared_examples "theme previews inaccessible" do
it "denies access with a 404 response" do
theme = Fabricate(:theme)
get "/admin/themes/#{theme.id}/preview.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "theme previews inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "theme previews inaccessible"
end
end
describe '#update_single_setting' do
let(:theme) { Fabricate(:theme) }
@ -711,6 +940,9 @@ RSpec.describe Admin::ThemesController do
theme.save!
end
context "when logged in as an admin" do
before { sign_in(admin) }
it "should update a theme setting" do
put "/admin/themes/#{theme.id}/setting.json", params: {
name: "bg",
@ -737,4 +969,32 @@ RSpec.describe Admin::ThemesController do
expect(theme.cached_settings[:bg]).to eq("")
end
end
shared_examples "theme update not allowed" do
it "prevents updates with a 404 response" do
put "/admin/themes/#{theme.id}/setting.json", params: {
name: "bg",
value: "green"
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
theme.reload
expect(theme.cached_settings[:bg]).to eq("red")
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "theme update not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "theme update not allowed"
end
end
end

View File

@ -1,18 +1,14 @@
# frozen_string_literal: true
RSpec.describe Admin::UserFieldsController do
it "is a subclass of AdminController" do
expect(Admin::UserFieldsController < Admin::AdminController).to eq(true)
end
context "when logged in" do
fab!(:admin) { Fabricate(:admin) }
before do
sign_in(admin)
end
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
describe '#create' do
context "when logged in as an admin" do
before { sign_in(admin) }
it "creates a user field" do
expect {
post "/admin/customize/user_fields.json", params: {
@ -41,9 +37,38 @@ RSpec.describe Admin::UserFieldsController do
end
end
shared_examples "user field creation not allowed" do
it "prevents creation with a 404 response" do
expect do
post "/admin/customize/user_fields.json", params: {
user_field: { name: 'hello', description: 'hello desc', field_type: 'text' }
}
end.not_to change { UserField.count }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "user field creation not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "user field creation not allowed"
end
end
describe '#index' do
fab!(:user_field) { Fabricate(:user_field) }
context "when logged in as an admin" do
before { sign_in(admin) }
it "returns a list of user fields" do
get "/admin/customize/user_fields.json"
expect(response.status).to eq(200)
@ -52,9 +77,35 @@ RSpec.describe Admin::UserFieldsController do
end
end
shared_examples "user fields inaccessible" do
it "denies access with a 404 response" do
get "/admin/customize/user_fields.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(response.parsed_body['user_fields']).to be_nil
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "user fields inaccessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "user fields inaccessible"
end
end
describe '#destroy' do
fab!(:user_field) { Fabricate(:user_field) }
context "when logged in as an admin" do
before { sign_in(admin) }
it "deletes the user field" do
expect {
delete "/admin/customize/user_fields/#{user_field.id}.json"
@ -63,9 +114,36 @@ RSpec.describe Admin::UserFieldsController do
end
end
shared_examples "user field deletion not allowed" do
it "prevents deletion with a 404 response" do
expect do
delete "/admin/customize/user_fields/#{user_field.id}.json"
end.not_to change { UserField.count }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "user field deletion not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "user field deletion not allowed"
end
end
describe '#update' do
fab!(:user_field) { Fabricate(:user_field) }
context "when logged in as an admin" do
before { sign_in(admin) }
it "updates the user field" do
put "/admin/customize/user_fields/#{user_field.id}.json", params: {
user_field: { name: 'fraggle', field_type: 'confirm', description: 'muppet' }
@ -138,5 +216,34 @@ RSpec.describe Admin::UserFieldsController do
}.to change { DirectoryColumn.count }.by(-1)
end
end
shared_examples "user field update not allowed" do
it "prevents updates with a 404 response" do
user_field.reload
original_name = user_field.name
put "/admin/customize/user_fields/#{user_field.id}.json", params: {
user_field: { name: 'fraggle', field_type: 'confirm', description: 'muppet' }
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
user_field.reload
expect(user_field.name).to eq(original_name)
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "user field update not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "user field update not allowed"
end
end
end

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,9 @@
# frozen_string_literal: true
RSpec.describe Admin::VersionsController do
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
before do
Jobs::VersionCheck.any_instance.stubs(:execute).returns(true)
@ -9,17 +12,8 @@ RSpec.describe Admin::VersionsController do
DiscourseUpdates.stubs(:critical_updates_available?).returns(false)
end
it "is a subclass of StaffController" do
expect(Admin::VersionsController < Admin::StaffController).to eq(true)
end
context 'while logged in as an admin' do
fab!(:admin) { Fabricate(:admin) }
before do
sign_in(admin)
end
describe 'show' do
describe "#show" do
shared_examples "version info accessible" do
it 'should return the currently available version' do
get "/admin/version_check.json"
expect(response.status).to eq(200)
@ -34,5 +28,30 @@ RSpec.describe Admin::VersionsController do
expect(json['installed_version']).to eq(Discourse::VERSION::STRING)
end
end
context 'when logged in as admin' do
before { sign_in(admin) }
include_examples "version info accessible"
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "version info accessible"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
it "denies access with a 404 response" do
get "/admin/version_check.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(response.parsed_body["latest_version"]).to be_nil
expect(response.parsed_body["installed_version"]).to be_nil
end
end
end
end

View File

@ -6,10 +6,6 @@ RSpec.describe Admin::WatchedWordsController do
fab!(:admin) { Fabricate(:admin) }
fab!(:user) { Fabricate(:user) }
it "is a subclass of StaffController" do
expect(Admin::WatchedWordsController < Admin::StaffController).to eq(true)
end
describe '#destroy' do
fab!(:watched_word) { Fabricate(:watched_word) }

View File

@ -1,20 +1,15 @@
# frozen_string_literal: true
RSpec.describe Admin::WebHooksController do
it 'is a subclass of AdminController' do
expect(Admin::WebHooksController < Admin::AdminController).to eq(true)
end
context 'while logged in as an admin' do
fab!(:web_hook) { Fabricate(:web_hook) }
fab!(:admin) { Fabricate(:admin) }
before do
sign_in(admin)
end
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
describe '#create' do
context "when logged in as admin" do
before { sign_in(admin) }
it 'creates a webhook' do
post "/admin/api/web_hooks.json", params: {
web_hook: {
@ -58,7 +53,45 @@ RSpec.describe Admin::WebHooksController do
end
end
shared_examples "webhook creation not allowed" do
it "prevents creation with a 404 response" do
post "/admin/api/web_hooks.json", params: {
web_hook: {
payload_url: 'https://meta.discourse.org/',
content_type: 1,
secret: "a_secret_for_webhooks",
wildcard_web_hook: false,
active: true,
verify_certificate: true,
web_hook_event_type_ids: [1],
group_ids: [],
category_ids: []
}
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(response.parsed_body["web_hook"]).to be_nil
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "webhook creation not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "webhook creation not allowed"
end
end
describe '#update' do
context "when logged in as admin" do
before { sign_in(admin) }
it "logs webhook update" do
put "/admin/api/web_hooks/#{web_hook.id}.json", params: {
web_hook: { active: false, payload_url: "https://test.com" }
@ -71,7 +104,37 @@ RSpec.describe Admin::WebHooksController do
end
end
shared_examples "webhook update not allowed" do
it "prevents updates with a 404 response" do
current_payload_url = web_hook.payload_url
put "/admin/api/web_hooks/#{web_hook.id}.json", params: {
web_hook: { active: false, payload_url: "https://test.com" }
}
web_hook.reload
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(web_hook.payload_url).to eq(current_payload_url)
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "webhook update not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "webhook update not allowed"
end
end
describe '#destroy' do
context "when logged in as admin" do
before { sign_in(admin) }
it "logs webhook destroy" do
delete "/admin/api/web_hooks/#{web_hook.id}.json", params: {
web_hook: { active: false, payload_url: "https://test.com" }
@ -82,7 +145,33 @@ RSpec.describe Admin::WebHooksController do
end
end
shared_examples "webhook deletion not allowed" do
it "prevents deletion with a 404 response" do
delete "/admin/api/web_hooks/#{web_hook.id}.json"
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(web_hook.reload).to be_present
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "webhook deletion not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "webhook deletion not allowed"
end
end
describe '#ping' do
context "when logged in as admin" do
before { sign_in(admin) }
it 'enqueues the ping event' do
expect do
post "/admin/api/web_hooks/#{web_hook.id}/ping.json"
@ -95,6 +184,30 @@ RSpec.describe Admin::WebHooksController do
end
end
shared_examples "webhook ping not allowed" do
it "fails to enqueue a ping with 404 response" do
expect do
post "/admin/api/web_hooks/#{web_hook.id}/ping.json"
end.not_to change { Jobs::EmitWebHookEvent.jobs.size }
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "webhook ping not allowed"
end
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "webhook ping not allowed"
end
end
describe '#redeliver_event' do
let!(:web_hook_event) do
WebHookEvent.create!(
@ -104,6 +217,8 @@ RSpec.describe Admin::WebHooksController do
)
end
before { sign_in(admin) }
it 'emits the web hook and updates the response headers and body' do
stub_request(:post, web_hook.payload_url)
.with(body: "abc", headers: { "aa" => 1, "bb" => 2 })
@ -153,4 +268,3 @@ RSpec.describe Admin::WebHooksController do
end
end
end
end