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
get "/admin.json"
expect(response.status).to eq(404)
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
context "when logged in as an admin" do
before { sign_in(admin) }
describe '#index' do
it "succeeds" do
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
describe '#show' do
it "succeeds" do
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
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
describe '#update' do
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
describe "#destroy" do
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
describe "#create" do
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
describe "#revoke and #undo_revoke" do
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(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
expect(key1.revoked_at).to eq(nil)
expect(scopes.keys).to contain_exactly('topics', 'users', 'email', 'posts', 'uploads', 'global', 'badges', 'categories', 'wordpress')
post "/admin/api/keys/#{key1.id}/undo-revoke.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
context "as a moderator" do
before do
sign_in(Fabricate(:moderator))
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
it "doesn't allow access" do
get "/admin/api/keys.json"
expect(response.status).to eq(404)
shared_examples "key scopes inaccessible" do
it "denies key scopes access with a 404 response" do
get "/admin/api/keys/scopes.json"
get "/admin/api/key/#{key1.id}.json"
expect(response.status).to eq(404)
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
post "/admin/api/keys.json", params: {
key: {
description: "master key description"
}
}
expect(response.status).to eq(404)
context "when logged in as a moderator" do
before { sign_in(moderator) }
expect(ApiKey.count).to eq(3)
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

File diff suppressed because it is too large Load Diff

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!(:badge) { Fabricate(:badge) }
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
context "when logged in as an admin" do
before { sign_in(admin) }
describe '#index' do
it 'returns badge index' do
it "returns badge index" do
get "/admin/badges.json"
expect(response.status).to eq(200)
end
end
describe '#preview' do
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
describe '#create' do
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
describe '#save_badge_groupings' do
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
describe '#badge_types' do
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
describe '#destroy' do
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
describe '#update' do
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
describe '#mass_award' do
fab!(:user) { Fabricate(:user, email: 'user1@test.com', username: 'username1') }
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
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,26 +1,23 @@
# 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
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
context "while logged in as an admin" do
fab!(:admin) { Fabricate(:admin) }
let(:valid_params) { { color_scheme: {
name: 'Such Design',
colors: [
{ name: 'primary', hex: 'FFBB00' },
{ name: 'secondary', hex: '888888' }
]
}
} }
let(:valid_params) { { color_scheme: {
name: 'Such Design',
colors: [
{ name: 'primary', hex: 'FFBB00' },
{ name: 'secondary', hex: '888888' }
]
}
} }
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 JSON" do
scheme_name = Fabricate(:color_scheme).name
get "/admin/color_schemes.json"
@ -36,7 +33,32 @@ RSpec.describe Admin::ColorSchemesController do
end
end
describe "#create" do
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,8 +77,38 @@ RSpec.describe Admin::ColorSchemesController do
end
end
describe "#update" do
fab!(:existing) { Fabricate(:color_scheme) }
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
@ -84,8 +136,33 @@ RSpec.describe Admin::ColorSchemesController do
end
end
describe "#destroy" do
fab!(:existing) { Fabricate(:color_scheme) }
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 {
@ -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)
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
}
]
Discourse.redis.set('new_features', MultiJson.dump(sample_features))
end
context 'while logged in as an admin' do
fab!(:admin) { Fabricate(:admin) }
describe '#index' do
shared_examples "version info present" do
it "returns discourse version info" do
get "/admin/dashboard.json"
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 }
]
Discourse.redis.set('new_features', MultiJson.dump(sample_features))
expect(response.status).to eq(200)
expect(response.parsed_body["version_check"]).to be_present
end
end
before do
sign_in(admin)
shared_examples "version info absent" do
before do
SiteSetting.version_checks = false
end
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
end
end
describe '#index' do
context 'when version checking is enabled' do
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
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
end
include_examples "version info present"
end
context 'when version checking is disabled' do
context "when version checking is disabled" do
before do
SiteSetting.version_checks = false
end
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
end
include_examples "version info absent"
end
end
describe '#problems' do
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
describe '#mark_new_features_as_seen' do
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,33 +2,52 @@
RSpec.describe Admin::EmailController do
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
fab!(:email_log) { Fabricate(:email_log) }
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(
username: 'username',
password: 'secret'
)
context "when logged in as an admin" do
before do
sign_in(admin)
Admin::EmailController.any_instance
.expects(:action_mailer_settings)
.returns(
username: 'username',
password: 'secret'
)
end
it 'does not include the password in the response' do
get "/admin/email.json"
mail_settings = response.parsed_body['settings']
expect(
mail_settings.select { |setting| setting['name'] == 'password' }
).to be_empty
end
end
it 'does not include the password in the response' do
get "/admin/email.json"
mail_settings = response.parsed_body['settings']
shared_examples "email settings inaccessible" do
it "denies access with a 404 response" do
get "/admin/email.json"
expect(
mail_settings.select { |setting| setting['name'] == 'password' }
).to be_empty
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
@ -40,40 +59,61 @@ RSpec.describe Admin::EmailController do
Fabricate(:post_reply_key, post: post, user: email_log.user)
end
it "should return the right response" do
email_log
get "/admin/email/sent.json"
context "when logged in as an admin" do
before { sign_in(admin) }
expect(response.status).to eq(200)
log = response.parsed_body.first
expect(log["id"]).to eq(email_log.id)
expect(log["reply_key"]).to eq(nil)
it "should return the right response" do
email_log
get "/admin/email/sent.json"
post_reply_key
expect(response.status).to eq(200)
log = response.parsed_body.first
expect(log["id"]).to eq(email_log.id)
expect(log["reply_key"]).to eq(nil)
get "/admin/email/sent.json"
post_reply_key
expect(response.status).to eq(200)
log = response.parsed_body.first
expect(log["id"]).to eq(email_log.id)
expect(log["reply_key"]).to eq(post_reply_key.reply_key)
end
get "/admin/email/sent.json"
it 'should be able to filter by reply key' do
email_log_2 = Fabricate(:email_log, post: post)
expect(response.status).to eq(200)
log = response.parsed_body.first
expect(log["id"]).to eq(email_log.id)
expect(log["reply_key"]).to eq(post_reply_key.reply_key)
end
post_reply_key_2 = Fabricate(:post_reply_key,
post: post,
user: email_log_2.user,
reply_key: "2d447423-c625-4fb9-8717-ff04ac60eee8"
)
it 'should be able to filter by reply key' do
email_log_2 = Fabricate(:email_log, post: post)
post_reply_key_2 = Fabricate(:post_reply_key,
post: post,
user: email_log_2.user,
reply_key: "2d447423-c625-4fb9-8717-ff04ac60eee8"
)
[
"17ff04",
"2d447423c6254fb98717ff04ac60eee8"
].each do |reply_key|
get "/admin/email/sent.json", params: {
reply_key: reply_key
}
expect(response.status).to eq(200)
logs = response.parsed_body
expect(logs.size).to eq(1)
expect(logs.first["reply_key"]).to eq(post_reply_key_2.reply_key)
end
end
it 'should be able to filter by smtp_transaction_response' do
email_log_2 = Fabricate(:email_log, smtp_transaction_response: <<~RESPONSE)
250 Ok: queued as pYoKuQ1aUG5vdpgh-k2K11qcpF4C1ZQ5qmvmmNW25SM=@mailhog.example
RESPONSE
[
"17ff04",
"2d447423c6254fb98717ff04ac60eee8"
].each do |reply_key|
get "/admin/email/sent.json", params: {
reply_key: reply_key
smtp_transaction_response: "pYoKu"
}
expect(response.status).to eq(200)
@ -81,219 +121,448 @@ RSpec.describe Admin::EmailController do
logs = response.parsed_body
expect(logs.size).to eq(1)
expect(logs.first["reply_key"]).to eq(post_reply_key_2.reply_key)
expect(logs.first["smtp_transaction_response"]).to eq(email_log_2.smtp_transaction_response)
end
end
it 'should be able to filter by smtp_transaction_response' do
email_log_2 = Fabricate(:email_log, smtp_transaction_response: <<~RESPONSE)
250 Ok: queued as pYoKuQ1aUG5vdpgh-k2K11qcpF4C1ZQ5qmvmmNW25SM=@mailhog.example
RESPONSE
shared_examples "sent emails inaccessible" do
it "denies access with a 404 response" do
get "/admin/email/sent.json"
get "/admin/email/sent.json", params: {
smtp_transaction_response: "pYoKu"
}
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
expect(response.status).to eq(200)
context "when logged in as a moderator" do
before { sign_in(moderator) }
logs = response.parsed_body
include_examples "sent emails inaccessible"
end
expect(logs.size).to eq(1)
expect(logs.first["smtp_transaction_response"]).to eq(email_log_2.smtp_transaction_response)
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) }
it "succeeds" do
get "/admin/email/skipped.json"
context "when logged in as an admin" do
before { sign_in(admin) }
expect(response.status).to eq(200)
logs = response.parsed_body
expect(logs.first["id"]).to eq(log2.id)
expect(logs.last["id"]).to eq(log1.id)
end
describe 'when filtered by username' do
it 'should return the right response' do
get "/admin/email/skipped.json", params: {
user: user.username
}
it "succeeds" do
get "/admin/email/skipped.json"
expect(response.status).to eq(200)
logs = response.parsed_body
expect(logs.count).to eq(1)
expect(logs.first["id"]).to eq(log1.id)
expect(logs.first["id"]).to eq(log2.id)
expect(logs.last["id"]).to eq(log1.id)
end
context "when filtered by username" do
it 'should return the right response' do
get "/admin/email/skipped.json", params: {
user: user.username
}
expect(response.status).to eq(200)
logs = response.parsed_body
expect(logs.count).to eq(1)
expect(logs.first["id"]).to eq(log1.id)
end
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
it 'raises an error without the email parameter' do
post "/admin/email/test.json"
expect(response.status).to eq(400)
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)
end
context 'with an email address' do
it 'enqueues a test email job' do
post "/admin/email/test.json", params: { email_address: 'eviltrout@test.domain' }
expect(response.status).to eq(200)
expect(ActionMailer::Base.deliveries.map(&:to).flatten).to include('eviltrout@test.domain')
end
end
context 'with SiteSetting.disable_emails' do
fab!(:eviltrout) { Fabricate(:evil_trout) }
fab!(:admin) { Fabricate(:admin) }
it 'bypasses disable when setting is "yes"' do
SiteSetting.disable_emails = 'yes'
post "/admin/email/test.json", params: { email_address: admin.email }
expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(
admin.email
)
incoming = response.parsed_body
expect(incoming['sent_test_email_message']).to eq(I18n.t("admin.email.sent_test"))
end
it 'bypasses disable when setting is "non-staff"' do
SiteSetting.disable_emails = 'non-staff'
post "/admin/email/test.json", params: { email_address: eviltrout.email }
expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(
eviltrout.email
)
incoming = response.parsed_body
expect(incoming['sent_test_email_message']).to eq(I18n.t("admin.email.sent_test"))
end
it 'works when setting is "no"' do
SiteSetting.disable_emails = 'no'
post "/admin/email/test.json", params: { email_address: eviltrout.email }
expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(
eviltrout.email
)
incoming = response.parsed_body
expect(incoming['sent_test_email_message']).to eq(I18n.t("admin.email.sent_test"))
end
end
end
context 'with an email address' do
it 'enqueues a test email job' do
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(200)
expect(ActionMailer::Base.deliveries.map(&:to).flatten).to include('eviltrout@test.domain')
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
context 'with SiteSetting.disable_emails' do
fab!(:eviltrout) { Fabricate(:evil_trout) }
fab!(:admin) { Fabricate(:admin) }
context "when logged in as a moderator" do
before { sign_in(moderator) }
it 'bypasses disable when setting is "yes"' do
SiteSetting.disable_emails = 'yes'
post "/admin/email/test.json", params: { email_address: admin.email }
include_examples "email tests not allowed"
end
expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(
admin.email
)
context "when logged in as a non-staff user" do
before { sign_in(user) }
incoming = response.parsed_body
expect(incoming['sent_test_email_message']).to eq(I18n.t("admin.email.sent_test"))
end
it 'bypasses disable when setting is "non-staff"' do
SiteSetting.disable_emails = 'non-staff'
post "/admin/email/test.json", params: { email_address: eviltrout.email }
expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(
eviltrout.email
)
incoming = response.parsed_body
expect(incoming['sent_test_email_message']).to eq(I18n.t("admin.email.sent_test"))
end
it 'works when setting is "no"' do
SiteSetting.disable_emails = 'no'
post "/admin/email/test.json", params: { email_address: eviltrout.email }
expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(
eviltrout.email
)
incoming = response.parsed_body
expect(incoming['sent_test_email_message']).to eq(I18n.t("admin.email.sent_test"))
end
include_examples "email tests not allowed"
end
end
describe '#preview_digest' do
it 'raises an error without the last_seen_at parameter' do
get "/admin/email/preview-digest.json"
expect(response.status).to eq(400)
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)
end
it "returns the right response when username is invalid" do
get "/admin/email/preview-digest.json", params: {
last_seen_at: 1.week.ago, username: "somerandomeusername"
}
expect(response.status).to eq(400)
end
it "previews the digest" do
get "/admin/email/preview-digest.json", params: {
last_seen_at: 1.week.ago, username: admin.username
}
expect(response.status).to eq(200)
end
end
it "returns the right response when username is invalid" do
get "/admin/email/preview-digest.json", params: {
last_seen_at: 1.week.ago, username: "somerandomeusername"
}
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(400)
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
it "previews the digest" do
get "/admin/email/preview-digest.json", params: {
last_seen_at: 1.week.ago, username: admin.username
}
expect(response.status).to eq(200)
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
it "returns a bad request if neither email parameter is present" do
post "/admin/email/handle_mail.json"
expect(response.status).to eq(400)
expect(response.body).to include("param is missing")
end
context "when logged in as an admin" do
before { sign_in(admin) }
it 'should enqueue the right job, and show a deprecation warning (email_encoded param should be used)' do
expect_enqueued_with(
job: :process_email,
args: { mail: email('cc'), retry_on_rate_limit: true, source: :handle_mail }
) do
post "/admin/email/handle_mail.json", params: { email: email('cc') }
it "returns a bad request if neither email parameter is present" do
post "/admin/email/handle_mail.json"
expect(response.status).to eq(400)
expect(response.body).to include("param is missing")
end
it 'should enqueue the right job, and show a deprecation warning (email_encoded param should be used)' do
expect_enqueued_with(
job: :process_email,
args: { mail: email('cc'), retry_on_rate_limit: true, source: :handle_mail }
) do
post "/admin/email/handle_mail.json", params: { email: email('cc') }
end
expect(response.status).to eq(200)
expect(response.body).to eq("warning: the email parameter is deprecated. all POST requests to this route should be sent with a base64 strict encoded email_encoded parameter instead. email has been received and is queued for processing")
end
it 'should enqueue the right job, decoding the raw email param' do
expect_enqueued_with(
job: :process_email,
args: { mail: email('cc'), retry_on_rate_limit: true, source: :handle_mail }
) do
post "/admin/email/handle_mail.json", params: { email_encoded: Base64.strict_encode64(email('cc')) }
end
expect(response.status).to eq(200)
expect(response.body).to eq("email has been received and is queued for processing")
end
it "retries enqueueing with forced UTF-8 encoding when encountering Encoding::UndefinedConversionError" do
post "/admin/email/handle_mail.json", params: { email_encoded: Base64.strict_encode64(email('encoding_undefined_conversion')) }
expect(response.status).to eq(200)
expect(response.body).to eq("email has been received and is queued for processing")
end
expect(response.status).to eq(200)
expect(response.body).to eq("warning: the email parameter is deprecated. all POST requests to this route should be sent with a base64 strict encoded email_encoded parameter instead. email has been received and is queued for processing")
end
it 'should enqueue the right job, decoding the raw email param' do
expect_enqueued_with(
job: :process_email,
args: { mail: email('cc'), retry_on_rate_limit: true, source: :handle_mail }
) do
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
expect(response.status).to eq(200)
expect(response.body).to eq("email has been received and is queued for processing")
end
it "retries enqueueing with forced UTF-8 encoding when encountering Encoding::UndefinedConversionError" do
post "/admin/email/handle_mail.json", params: { email_encoded: Base64.strict_encode64(email('encoding_undefined_conversion')) }
expect(response.status).to eq(200)
expect(response.body).to eq("email has been received and is queued for processing")
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
it 'should provide a string for a blank error' do
Fabricate(:incoming_email, error: "")
get "/admin/email/rejected.json"
expect(response.status).to eq(200)
rejected = response.parsed_body
expect(rejected.first['error']).to eq(I18n.t("emails.incoming.unrecognized_error"))
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"
expect(response.status).to eq(200)
rejected = response.parsed_body
expect(rejected.first['error']).to eq(I18n.t("emails.incoming.unrecognized_error"))
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
it 'should provide a string for a blank error' do
incoming_email = Fabricate(:incoming_email, error: "")
get "/admin/email/incoming/#{incoming_email.id}.json"
expect(response.status).to eq(200)
incoming = response.parsed_body
expect(incoming['error']).to eq(I18n.t("emails.incoming.unrecognized_error"))
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"
expect(response.status).to eq(200)
incoming = response.parsed_body
expect(incoming['error']).to eq(I18n.t("emails.incoming.unrecognized_error"))
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
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)
context "when logged in as an admin" do
before { sign_in(admin) }
json = response.parsed_body
expect(json["errors"]).to include("Discourse::InvalidParameters")
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)
json = response.parsed_body
expect(json["errors"]).to include("Discourse::InvalidParameters")
end
it 'raises an error when the email log entry is not marked as bounced' do
get "/admin/email/incoming_from_bounced/#{email_log.id}.json"
expect(response.status).to eq(404)
json = response.parsed_body
expect(json["errors"]).to include("Discourse::InvalidParameters")
end
context 'when bounced email log entry exists' do
fab!(:email_log) { Fabricate(:email_log, bounced: true, bounce_key: SecureRandom.hex) }
let(:error_message) { "Email::Receiver::BouncedEmailError" }
it 'returns an incoming email sent to the reply_by_email_address' do
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(200)
json = response.parsed_body
expect(json["error"]).to eq(error_message)
end
it 'returns an incoming email sent to the notification_email address' do
Fabricate(:incoming_email,
is_bounce: true,
error: error_message,
to_addresses: SiteSetting.notification_email.sub("@", "+verp-#{email_log.bounce_key}@")
)
get "/admin/email/incoming_from_bounced/#{email_log.id}.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["error"]).to eq(error_message)
end
it 'returns an incoming email sent to the notification_email address' do
SiteSetting.reply_by_email_address = "replies+%{reply_key}@subdomain.example.com"
Fabricate(:incoming_email,
is_bounce: true,
error: error_message,
to_addresses: "subdomain+verp-#{email_log.bounce_key}@example.com"
)
get "/admin/email/incoming_from_bounced/#{email_log.id}.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["error"]).to eq(error_message)
end
it 'raises an error if the bounce_key is blank' do
email_log.update(bounce_key: nil)
get "/admin/email/incoming_from_bounced/#{email_log.id}.json"
expect(response.status).to eq(404)
json = response.parsed_body
expect(json["errors"]).to include("Discourse::InvalidParameters")
end
it 'raises an error if there is no incoming email' do
get "/admin/email/incoming_from_bounced/#{email_log.id}.json"
expect(response.status).to eq(404)
json = response.parsed_body
expect(json["errors"]).to include("Discourse::NotFound")
end
end
end
it 'raises an error when the email log entry is not marked as bounced' do
get "/admin/email/incoming_from_bounced/#{email_log.id}.json"
expect(response.status).to eq(404)
json = response.parsed_body
expect(json["errors"]).to include("Discourse::InvalidParameters")
end
context 'when bounced email log entry exists' do
fab!(:email_log) { Fabricate(:email_log, bounced: true, bounce_key: SecureRandom.hex) }
let(:error_message) { "Email::Receiver::BouncedEmailError" }
it 'returns an incoming email sent to the reply_by_email_address' do
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,
@ -303,82 +572,75 @@ RSpec.describe Admin::EmailController do
)
get "/admin/email/incoming_from_bounced/#{email_log.id}.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["error"]).to eq(error_message)
end
it 'returns an incoming email sent to the notification_email address' do
Fabricate(:incoming_email,
is_bounce: true,
error: error_message,
to_addresses: SiteSetting.notification_email.sub("@", "+verp-#{email_log.bounce_key}@")
)
get "/admin/email/incoming_from_bounced/#{email_log.id}.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["error"]).to eq(error_message)
end
it 'returns an incoming email sent to the notification_email address' do
SiteSetting.reply_by_email_address = "replies+%{reply_key}@subdomain.example.com"
Fabricate(:incoming_email,
is_bounce: true,
error: error_message,
to_addresses: "subdomain+verp-#{email_log.bounce_key}@example.com"
)
get "/admin/email/incoming_from_bounced/#{email_log.id}.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["error"]).to eq(error_message)
end
it 'raises an error if the bounce_key is blank' do
email_log.update(bounce_key: nil)
get "/admin/email/incoming_from_bounced/#{email_log.id}.json"
expect(response.status).to eq(404)
json = response.parsed_body
expect(json["errors"]).to include("Discourse::InvalidParameters")
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
it 'raises an error if there is no incoming email' do
get "/admin/email/incoming_from_bounced/#{email_log.id}.json"
expect(response.status).to eq(404)
context "when logged in as a moderator" do
before { sign_in(moderator) }
json = response.parsed_body
expect(json["errors"]).to include("Discourse::NotFound")
end
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
From: "somebody" <somebody@example.com>
To: someone@example.com
Date: Mon, 3 Dec 2018 00:00:00 -0000
Subject: This is some subject
Content-Type: text/plain; charset="UTF-8"
let(:email) do
<<~EMAIL
From: "somebody" <somebody@example.com>
To: someone@example.com
Date: Mon, 3 Dec 2018 00:00:00 -0000
Subject: This is some subject
Content-Type: text/plain; charset="UTF-8"
Hello, this is a test!
Hello, this is a test!
---
---
This part should be elided.
EMAIL
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)
expect(incoming['text']).to eq("Hello, this is a test!")
expect(incoming['elided']).to eq("---\n\nThis part should be elided.")
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)
expect(incoming['text']).to eq("Hello, this is a test!")
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,41 +2,61 @@
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
it 'returns default values' do
get '/admin/customize/email_style.json'
expect(response.status).to eq(200)
context "when logged in as an admin" do
before { sign_in(admin) }
json = response.parsed_body['email_style']
expect(json['html']).to eq(default_html)
expect(json['css']).to eq(default_css)
it 'returns default values' do
get '/admin/customize/email_style.json'
expect(response.status).to eq(200)
json = response.parsed_body['email_style']
expect(json['html']).to eq(default_html)
expect(json['css']).to eq(default_css)
end
it 'returns customized values' do
SiteSetting.email_custom_template = "For you: %{email_content}"
SiteSetting.email_custom_css = ".user-name { font-size: 24px; }"
get '/admin/customize/email_style.json'
expect(response.status).to eq(200)
json = response.parsed_body['email_style']
expect(json['html']).to eq("For you: %{email_content}")
expect(json['css']).to eq(".user-name { font-size: 24px; }")
end
end
it 'returns customized values' do
SiteSetting.email_custom_template = "For you: %{email_content}"
SiteSetting.email_custom_css = ".user-name { font-size: 24px; }"
get '/admin/customize/email_style.json'
expect(response.status).to eq(200)
shared_examples "email styles inaccessible" do
it "denies access with a 404 response" do
get '/admin/customize/email_style.json'
json = response.parsed_body['email_style']
expect(json['html']).to eq("For you: %{email_content}")
expect(json['css']).to eq(".user-name { font-size: 24px; }")
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
@ -48,26 +68,51 @@ RSpec.describe Admin::EmailStylesController do
}
end
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 }
expect(response.status).to eq(200)
expect(SiteSetting.email_custom_template).to eq(valid_params[:html])
expect(SiteSetting.email_custom_css).to eq(valid_params[:css])
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 }
expect(response.status).to eq(200)
expect(SiteSetting.email_custom_template).to eq(valid_params[:html])
expect(SiteSetting.email_custom_css).to eq(valid_params[:css])
end
it 'reports errors' do
put '/admin/customize/email_style.json', params: {
email_style: valid_params.merge(html: 'No email content')
}
expect(response.status).to eq(422)
json = response.parsed_body
expect(json['errors']).to include(
I18n.t(
'email_style.html_missing_placeholder',
placeholder: '%{email_content}'
)
)
end
end
it 'reports errors' do
put '/admin/customize/email_style.json', params: {
email_style: valid_params.merge(html: 'No email content')
}
expect(response.status).to eq(422)
json = response.parsed_body
expect(json['errors']).to include(
I18n.t(
'email_style.html_missing_placeholder',
placeholder: '%{email_content}'
)
)
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,90 +18,70 @@ 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)
context "when logged in as an admin" do
before { sign_in(admin) }
it "should work if you are an admin" do
get '/admin/customize/email_templates.json'
expect(response.status).to eq(200)
json = response.parsed_body
expect(json['email_templates']).to be_present
end
it 'returns overridden = true if subject or body has translation_overrides record' do
put '/admin/customize/email_templates/user_notifications.admin_login', params: {
email_template: { subject: original_subject, body: original_body }
}, headers: headers
expect(response.status).to eq(200)
get '/admin/customize/email_templates.json'
expect(response.status).to eq(200)
templates = response.parsed_body['email_templates']
template = templates.find { |t| t['id'] == 'user_notifications.admin_login' }
expect(template['can_revert']).to eq(true)
TranslationOverride.destroy_all
get '/admin/customize/email_templates.json'
expect(response.status).to eq(200)
templates = response.parsed_body['email_templates']
template = templates.find { |t| t['id'] == 'user_notifications.admin_login' }
expect(template['can_revert']).to eq(false)
end
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)
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
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)
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "email templates inaccessible"
end
it "should work if you are an admin" do
sign_in(admin)
get '/admin/customize/email_templates.json'
context "when logged in as a non-staff user" do
before { sign_in(user) }
expect(response.status).to eq(200)
json = response.parsed_body
expect(json['email_templates']).to be_present
include_examples "email templates inaccessible"
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
expect(response.status).to eq(200)
get '/admin/customize/email_templates.json'
expect(response.status).to eq(200)
templates = response.parsed_body['email_templates']
template = templates.find { |t| t['id'] == 'user_notifications.admin_login' }
expect(template['can_revert']).to eq(true)
TranslationOverride.destroy_all
get '/admin/customize/email_templates.json'
expect(response.status).to eq(200)
templates = response.parsed_body['email_templates']
template = templates.find { |t| t['id'] == 'user_notifications.admin_login' }
expect(template['can_revert']).to eq(false)
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
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
fab!(:embeddable_host) { Fabricate(:embeddable_host) }
context 'while logged in as an admin' do
fab!(:admin) { Fabricate(:admin) }
fab!(:embeddable_host) { Fabricate(:embeddable_host) }
describe '#create' do
context "when logged in as an admin" do
before { sign_in(admin) }
before do
sign_in(admin)
end
describe '#create' do
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
describe '#update' do
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
describe '#destroy' do
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,139 +2,219 @@
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
it "returns a list of custom emojis" do
CustomEmoji.create!(name: 'osama-test-emoji', upload: upload)
Emoji.clear_cache
context "when logged in as an admin" do
before { sign_in(admin) }
get "/admin/customize/emojis.json"
expect(response.status).to eq(200)
it "returns a list of custom emojis" do
CustomEmoji.create!(name: 'osama-test-emoji', upload: upload)
Emoji.clear_cache
json = response.parsed_body
expect(json[0]["name"]).to eq("osama-test-emoji")
expect(json[0]["url"]).to eq(upload.url)
get "/admin/customize/emojis.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json[0]["name"]).to eq("osama-test-emoji")
expect(json[0]["url"]).to eq(upload.url)
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
it 'should publish the right error' do
context "when logged in as an admin" do
before { sign_in(admin) }
post "/admin/customize/emojis.json", params: {
name: 'test',
file: fixture_file_upload("#{Rails.root}/spec/fixtures/images/fake.jpg")
}
context 'when upload is invalid' do
it 'should publish the right error' do
expect(response.status).to eq(422)
parsed = response.parsed_body
expect(parsed["errors"]).to eq([I18n.t('upload.images.size_not_found')])
post "/admin/customize/emojis.json", params: {
name: 'test',
file: fixture_file_upload("#{Rails.root}/spec/fixtures/images/fake.jpg")
}
expect(response.status).to eq(422)
parsed = response.parsed_body
expect(parsed["errors"]).to eq([I18n.t('upload.images.size_not_found')])
end
end
end
describe 'when emoji name already exists' do
it 'should publish the right error' do
CustomEmoji.create!(name: 'test', upload: upload)
context 'when emoji name already exists' do
it 'should publish the right error' do
CustomEmoji.create!(name: 'test', upload: upload)
post "/admin/customize/emojis.json", params: {
name: 'test',
file: fixture_file_upload("#{Rails.root}/spec/fixtures/images/logo.png")
}
expect(response.status).to eq(422)
parsed = response.parsed_body
expect(parsed["errors"]).to eq([
"Name #{I18n.t('activerecord.errors.models.custom_emoji.attributes.name.taken')}"
])
end
end
it 'should allow an admin to add a custom emoji' do
Emoji.expects(:clear_cache)
post "/admin/customize/emojis.json", params: {
name: 'test',
file: fixture_file_upload("#{Rails.root}/spec/fixtures/images/logo.png")
}
expect(response.status).to eq(422)
parsed = response.parsed_body
expect(parsed["errors"]).to eq([
"Name #{I18n.t('activerecord.errors.models.custom_emoji.attributes.name.taken')}"
])
custom_emoji = CustomEmoji.last
upload = custom_emoji.upload
expect(upload.original_filename).to eq('logo.png')
data = response.parsed_body
expect(response.status).to eq(200)
expect(data["errors"]).to eq(nil)
expect(data["name"]).to eq(custom_emoji.name)
expect(data["url"]).to eq(upload.url)
expect(custom_emoji.group).to eq(nil)
end
it 'should allow an admin to add a custom emoji with a custom group' do
Emoji.expects(:clear_cache)
post "/admin/customize/emojis.json", params: {
name: 'test',
group: 'Foo',
file: fixture_file_upload("#{Rails.root}/spec/fixtures/images/logo.png")
}
custom_emoji = CustomEmoji.last
data = response.parsed_body
expect(response.status).to eq(200)
expect(custom_emoji.group).to eq("foo")
end
it 'should fix up the emoji name' do
Emoji.expects(:clear_cache).times(3)
post "/admin/customize/emojis.json", params: {
name: 'test.png',
file: fixture_file_upload("#{Rails.root}/spec/fixtures/images/logo.png")
}
custom_emoji = CustomEmoji.last
upload = custom_emoji.upload
expect(upload.original_filename).to eq('logo.png')
expect(custom_emoji.name).to eq("test")
expect(response.status).to eq(200)
post "/admin/customize/emojis.json", params: {
name: 'st&#* onk$',
file: fixture_file_upload("#{Rails.root}/spec/fixtures/images/logo.png")
}
custom_emoji = CustomEmoji.last
expect(custom_emoji.name).to eq("st_onk_")
expect(response.status).to eq(200)
post "/admin/customize/emojis.json", params: {
name: 'PaRTYpaRrot',
file: fixture_file_upload("#{Rails.root}/spec/fixtures/images/logo.png")
}
custom_emoji = CustomEmoji.last
expect(custom_emoji.name).to eq("partyparrot")
expect(response.status).to eq(200)
end
end
it 'should allow an admin to add a custom emoji' do
Emoji.expects(:clear_cache)
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")
}
post "/admin/customize/emojis.json", params: {
name: 'test',
file: fixture_file_upload("#{Rails.root}/spec/fixtures/images/logo.png")
}
custom_emoji = CustomEmoji.last
upload = custom_emoji.upload
expect(upload.original_filename).to eq('logo.png')
data = response.parsed_body
expect(response.status).to eq(200)
expect(data["errors"]).to eq(nil)
expect(data["name"]).to eq(custom_emoji.name)
expect(data["url"]).to eq(upload.url)
expect(custom_emoji.group).to eq(nil)
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
it 'should allow an admin to add a custom emoji with a custom group' do
Emoji.expects(:clear_cache)
context "when logged in as a moderator" do
before { sign_in(moderator) }
post "/admin/customize/emojis.json", params: {
name: 'test',
group: 'Foo',
file: fixture_file_upload("#{Rails.root}/spec/fixtures/images/logo.png")
}
custom_emoji = CustomEmoji.last
data = response.parsed_body
expect(response.status).to eq(200)
expect(custom_emoji.group).to eq("foo")
include_examples "custom emoji creation not allowed"
end
it 'should fix up the emoji name' do
Emoji.expects(:clear_cache).times(3)
context "when logged in as a non-staff user" do
before { sign_in(user) }
post "/admin/customize/emojis.json", params: {
name: 'test.png',
file: fixture_file_upload("#{Rails.root}/spec/fixtures/images/logo.png")
}
custom_emoji = CustomEmoji.last
upload = custom_emoji.upload
expect(upload.original_filename).to eq('logo.png')
expect(custom_emoji.name).to eq("test")
expect(response.status).to eq(200)
post "/admin/customize/emojis.json", params: {
name: 'st&#* onk$',
file: fixture_file_upload("#{Rails.root}/spec/fixtures/images/logo.png")
}
custom_emoji = CustomEmoji.last
expect(custom_emoji.name).to eq("st_onk_")
expect(response.status).to eq(200)
post "/admin/customize/emojis.json", params: {
name: 'PaRTYpaRrot',
file: fixture_file_upload("#{Rails.root}/spec/fixtures/images/logo.png")
}
custom_emoji = CustomEmoji.last
expect(custom_emoji.name).to eq("partyparrot")
expect(response.status).to eq(200)
include_examples "custom emoji creation not allowed"
end
end
describe '#destroy' do
it 'should allow an admin to delete a custom emoji' do
custom_emoji = CustomEmoji.create!(name: 'test', upload: upload)
Emoji.clear_cache
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
expect do
delete "/admin/customize/emojis/#{custom_emoji.name}.json",
params: { name: 'test' }
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
expect do
delete "/admin/customize/emojis/#{custom_emoji.name}.json",
params: { name: 'test' }
end.to change { CustomEmoji.count }.by(-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 "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

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +1,48 @@
# frozen_string_literal: true
RSpec.describe Admin::ImpersonateController do
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
fab!(:another_admin) { Fabricate(:admin) }
it "is a subclass of AdminController" do
expect(Admin::ImpersonateController < Admin::AdminController).to eq(true)
end
describe '#index' do
context "when logged in as an admin" do
before { sign_in(admin) }
context 'while logged in as an admin' do
fab!(:admin) { Fabricate(:admin) }
fab!(:user) { Fabricate(:user) }
fab!(:another_admin) { Fabricate(:admin) }
before do
sign_in(admin)
end
describe '#index' do
it 'returns success' do
get "/admin/impersonate.json"
expect(response.status).to eq(200)
end
end
describe '#create' do
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,109 +1,160 @@
# 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
it 'filters url' do
Fabricate(:permalink, url: "/forum/23")
Fabricate(:permalink, url: "/forum/98")
Fabricate(:permalink, url: "/discuss/topic/45")
Fabricate(:permalink, url: "/discuss/topic/76")
context "when logged in as an admin" do
before { sign_in(admin) }
get "/admin/permalinks.json", params: { filter: "topic" }
it 'filters url' do
Fabricate(:permalink, url: "/forum/23")
Fabricate(:permalink, url: "/forum/98")
Fabricate(:permalink, url: "/discuss/topic/45")
Fabricate(:permalink, url: "/discuss/topic/76")
expect(response.status).to eq(200)
result = response.parsed_body
expect(result.length).to eq(2)
get "/admin/permalinks.json", params: { filter: "topic" }
expect(response.status).to eq(200)
result = response.parsed_body
expect(result.length).to eq(2)
end
it 'filters external url' do
Fabricate(:permalink, external_url: "http://google.com")
Fabricate(:permalink, external_url: "http://wikipedia.org")
Fabricate(:permalink, external_url: "http://www.discourse.org")
Fabricate(:permalink, external_url: "http://try.discourse.org")
get "/admin/permalinks.json", params: { filter: "discourse" }
expect(response.status).to eq(200)
result = response.parsed_body
expect(result.length).to eq(2)
end
it 'filters url and external url both' do
Fabricate(:permalink, url: "/forum/23", external_url: "http://google.com")
Fabricate(:permalink, url: "/discourse/98", external_url: "http://wikipedia.org")
Fabricate(:permalink, url: "/discuss/topic/45", external_url: "http://discourse.org")
Fabricate(:permalink, url: "/discuss/topic/76", external_url: "http://try.discourse.org")
get "/admin/permalinks.json", params: { filter: "discourse" }
expect(response.status).to eq(200)
result = response.parsed_body
expect(result.length).to eq(3)
end
end
it 'filters external url' do
Fabricate(:permalink, external_url: "http://google.com")
Fabricate(:permalink, external_url: "http://wikipedia.org")
Fabricate(:permalink, external_url: "http://www.discourse.org")
Fabricate(:permalink, external_url: "http://try.discourse.org")
shared_examples "permalinks inaccessible" do
it "denies access with a 404 response" do
get "/admin/permalinks.json", params: { filter: "topic" }
get "/admin/permalinks.json", params: { filter: "discourse" }
expect(response.status).to eq(200)
result = response.parsed_body
expect(result.length).to eq(2)
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
it 'filters url and external url both' do
Fabricate(:permalink, url: "/forum/23", external_url: "http://google.com")
Fabricate(:permalink, url: "/discourse/98", external_url: "http://wikipedia.org")
Fabricate(:permalink, url: "/discuss/topic/45", external_url: "http://discourse.org")
Fabricate(:permalink, url: "/discuss/topic/76", external_url: "http://try.discourse.org")
context "when logged in as a moderator" do
before { sign_in(moderator) }
get "/admin/permalinks.json", params: { filter: "discourse" }
include_examples "permalinks inaccessible"
end
expect(response.status).to eq(200)
result = response.parsed_body
expect(result.length).to eq(3)
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "permalinks inaccessible"
end
end
describe "#create" do
it "works for topics" do
topic = Fabricate(:topic)
context "when logged in as an admin" do
before { sign_in(admin) }
post "/admin/permalinks.json", params: {
url: "/topics/771",
permalink_type: "topic_id",
permalink_type_value: topic.id
}
it "works for topics" do
topic = Fabricate(:topic)
expect(response.status).to eq(200)
expect(Permalink.last).to have_attributes(url: "topics/771", topic_id: topic.id, post_id: nil, category_id: nil, tag_id: nil)
post "/admin/permalinks.json", params: {
url: "/topics/771",
permalink_type: "topic_id",
permalink_type_value: topic.id
}
expect(response.status).to eq(200)
expect(Permalink.last).to have_attributes(url: "topics/771", topic_id: topic.id, post_id: nil, category_id: nil, tag_id: nil)
end
it "works for posts" do
some_post = Fabricate(:post)
post "/admin/permalinks.json", params: {
url: "/topics/771/8291",
permalink_type: "post_id",
permalink_type_value: some_post.id
}
expect(response.status).to eq(200)
expect(Permalink.last).to have_attributes(url: "topics/771/8291", topic_id: nil, post_id: some_post.id, category_id: nil, tag_id: nil)
end
it "works for categories" do
category = Fabricate(:category)
post "/admin/permalinks.json", params: {
url: "/forums/11",
permalink_type: "category_id",
permalink_type_value: category.id
}
expect(response.status).to eq(200)
expect(Permalink.last).to have_attributes(url: "forums/11", topic_id: nil, post_id: nil, category_id: category.id, tag_id: nil)
end
it "works for tags" do
tag = Fabricate(:tag)
post "/admin/permalinks.json", params: {
url: "/forums/12",
permalink_type: "tag_name",
permalink_type_value: tag.name
}
expect(response.status).to eq(200)
expect(Permalink.last).to have_attributes(url: "forums/12", topic_id: nil, post_id: nil, category_id: nil, tag_id: tag.id)
end
end
it "works for posts" do
some_post = Fabricate(:post)
shared_examples "permalink creation not allowed" do
it "prevents creation with a 404 response" do
topic = Fabricate(:topic)
post "/admin/permalinks.json", params: {
url: "/topics/771/8291",
permalink_type: "post_id",
permalink_type_value: some_post.id
}
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(200)
expect(Permalink.last).to have_attributes(url: "topics/771/8291", topic_id: nil, post_id: some_post.id, category_id: nil, tag_id: nil)
expect(response.status).to eq(404)
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
end
end
it "works for categories" do
category = Fabricate(:category)
context "when logged in as a moderator" do
before { sign_in(moderator) }
post "/admin/permalinks.json", params: {
url: "/forums/11",
permalink_type: "category_id",
permalink_type_value: category.id
}
expect(response.status).to eq(200)
expect(Permalink.last).to have_attributes(url: "forums/11", topic_id: nil, post_id: nil, category_id: category.id, tag_id: nil)
include_examples "permalink creation not allowed"
end
it "works for tags" do
tag = Fabricate(:tag)
context "when logged in as a non-staff user" do
before { sign_in(user) }
post "/admin/permalinks.json", params: {
url: "/forums/12",
permalink_type: "tag_name",
permalink_type_value: tag.name
}
expect(response.status).to eq(200)
expect(Permalink.last).to have_attributes(url: "forums/12", topic_id: nil, post_id: nil, category_id: nil, tag_id: tag.id)
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 { sign_in(admin) }
context "while logged in as an admin" do
before do
sign_in(Fabricate(:admin))
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
it 'should return JSON' do
get "/admin/plugins.json"
expect(response.status).to eq(200)
expect(response.parsed_body.has_key?('plugins')).to eq(true)
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
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
context 'while logged in as an admin' do
fab!(:admin) { Fabricate(:admin) }
fab!(:user) { Fabricate(:user) }
describe '#bulk' do
context "when logged in as an admin" do
before { sign_in(admin) }
before do
sign_in(admin)
end
describe '#bulk' do
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
describe '#show' do
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,31 +1,123 @@
# 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
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
get "/admin/customize/robots.json"
expect(response.status).to eq(404)
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["robots_txt"]).to be_present
expect(json["overridden"]).to eq(false)
end
it "can't perform #update" do
put "/admin/customize/robots.json", params: { robots_txt: "adasdasd" }
it "returns overridden content if there are overrides" do
SiteSetting.overridden_robots_txt = "something"
get "/admin/customize/robots.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["robots_txt"]).to eq("something")
expect(json["overridden"]).to eq(true)
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
put "/admin/customize/robots.json", params: { robots_txt: "new_content" }
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["robots_txt"]).to eq("new_content")
expect(json["overridden"]).to eq(true)
expect(SiteSetting.overridden_robots_txt).to eq("new_content")
get "/robots.txt"
expect(response.body).to include("new_content")
end
it "requires `robots_txt` param to be present" do
SiteSetting.overridden_robots_txt = "overridden_content"
put "/admin/customize/robots.json", params: { robots_txt: "" }
expect(response.status).to eq(400)
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
it "can't perform #reset" do
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
SiteSetting.overridden_robots_txt = "overridden_content"
delete "/admin/customize/robots.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["robots_txt"]).not_to include("overridden_content")
expect(json["overridden"]).to eq(false)
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
@ -33,70 +125,13 @@ RSpec.describe Admin::RobotsTxtController do
context "when logged in as a moderator" do
before { sign_in(moderator) }
include_examples "access_forbidden"
include_examples "robot.txt reset not allowed"
end
context "when logged in as non-staff user" do
before { sign_in(user) }
context "when logged in as a non-staff user" do
before { sign_in(user) }
include_examples "access_forbidden"
end
end
describe "#show" do
before { sign_in(admin) }
it "returns default content if there are no overrides" do
get "/admin/customize/robots.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["robots_txt"]).to be_present
expect(json["overridden"]).to eq(false)
end
it "returns overridden content if there are overrides" do
SiteSetting.overridden_robots_txt = "something"
get "/admin/customize/robots.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["robots_txt"]).to eq("something")
expect(json["overridden"]).to eq(true)
end
end
describe "#update" do
before { sign_in(admin) }
it "overrides the site's default robots.txt" do
put "/admin/customize/robots.json", params: { robots_txt: "new_content" }
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["robots_txt"]).to eq("new_content")
expect(json["overridden"]).to eq(true)
expect(SiteSetting.overridden_robots_txt).to eq("new_content")
get "/robots.txt"
expect(response.body).to include("new_content")
end
it "requires `robots_txt` param to be present" do
SiteSetting.overridden_robots_txt = "overridden_content"
put "/admin/customize/robots.json", params: { robots_txt: "" }
expect(response.status).to eq(400)
end
end
describe "#reset" do
before { sign_in(admin) }
it "resets robots.txt file to the default version" do
SiteSetting.overridden_robots_txt = "overridden_content"
delete "/admin/customize/robots.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["robots_txt"]).not_to include("overridden_content")
expect(json["overridden"]).to eq(false)
expect(SiteSetting.overridden_robots_txt).to eq("")
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))
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
it 'returns JSON' do
Fabricate(:screened_email)
get "/admin/logs/screened_emails.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json.size).to eq(1)
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,47 +1,65 @@
# 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
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")
Fabricate(:screened_ip_address, ip_address: "1.2.3.6")
Fabricate(:screened_ip_address, ip_address: "4.5.6.7")
Fabricate(:screened_ip_address, ip_address: "5.0.0.0/8")
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")
Fabricate(:screened_ip_address, ip_address: "1.2.3.6")
Fabricate(:screened_ip_address, ip_address: "4.5.6.7")
Fabricate(:screened_ip_address, ip_address: "5.0.0.0/8")
get "/admin/logs/screened_ip_addresses.json", params: { filter: "1.2.*" }
get "/admin/logs/screened_ip_addresses.json", params: { filter: "1.2.*" }
expect(response.status).to eq(200)
expect(response.parsed_body.map { |record| record["ip_address"] })
.to contain_exactly("1.2.3.4", "1.2.3.5", "1.2.3.6")
expect(response.status).to eq(200)
expect(response.parsed_body.map { |record| record["ip_address"] })
.to contain_exactly("1.2.3.4", "1.2.3.5", "1.2.3.6")
get "/admin/logs/screened_ip_addresses.json", params: { filter: "4.5.6.7" }
get "/admin/logs/screened_ip_addresses.json", params: { filter: "4.5.6.7" }
expect(response.status).to eq(200)
expect(response.parsed_body.map { |record| record["ip_address"] })
.to contain_exactly("4.5.6.7")
expect(response.status).to eq(200)
expect(response.parsed_body.map { |record| record["ip_address"] })
.to contain_exactly("4.5.6.7")
get "/admin/logs/screened_ip_addresses.json", params: { filter: "5.0.0.1" }
get "/admin/logs/screened_ip_addresses.json", params: { filter: "5.0.0.1" }
expect(response.status).to eq(200)
expect(response.parsed_body.map { |record| record["ip_address"] })
.to contain_exactly("5.0.0.0/8")
expect(response.status).to eq(200)
expect(response.parsed_body.map { |record| record["ip_address"] })
.to contain_exactly("5.0.0.0/8")
get "/admin/logs/screened_ip_addresses.json", params: { filter: "6.0.0.1" }
get "/admin/logs/screened_ip_addresses.json", params: { filter: "6.0.0.1" }
expect(response.status).to eq(200)
expect(response.parsed_body).to be_blank
expect(response.status).to eq(200)
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))
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
it 'returns JSON' do
Fabricate(:screened_url)
get "/admin/logs/screened_urls.json"
expect(response.status).to eq(200)
json = response.parsed_body
expect(json.size).to eq(1)
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,99 +6,89 @@ 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
get '/admin/logs/search_logs.json'
expect(response.status).to eq(404)
shared_examples "search logs accessible" do
it "returns search logs" do
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
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)
context "when logged in as an admin" do
before { sign_in(admin) }
include_examples "search logs accessible"
end
it "should work if you are an admin" do
sign_in(admin)
get '/admin/logs/search_logs.json'
context "when logged in as a moderator" do
before { sign_in(moderator) }
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)
include_examples "search logs accessible"
end
it "should work if you are a moderator" do
sign_in(moderator)
get "/admin/logs/search_logs.json"
context "when logged in as a non-staff user" do
before { sign_in(user) }
expect(response.status).to eq(200)
it "denies access with a 404 response" do
get "/admin/logs/search_logs.json"
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)
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"
}
shared_examples "search log term accessible" do
it "returns search log term" do
get '/admin/logs/search_logs/term.json', params: {
term: "ruby"
}
expect(response.status).to eq(404)
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
end
end
it "raises an error if you aren't an admin" do
sign_in(user)
context "when logged in as an admin" do
before { sign_in(admin) }
get '/admin/logs/search_logs/term.json', params: {
term: "ruby"
}
expect(response.status).to eq(404)
include_examples "search log term accessible"
end
it "should work if you are an admin" do
sign_in(admin)
context "when logged in as a moderator" do
before { sign_in(moderator) }
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
include_examples "search log term accessible"
end
it "should work if you are a moderator" do
sign_in(moderator)
context "when logged in as a non-staff user" do
before { sign_in(user) }
get "/admin/logs/search_logs/term.json", params: {
term: "ruby"
}
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
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
it "is a subclass of AdminController" do
expect(Admin::SiteSettingsController < Admin::AdminController).to eq(true)
end
describe "#index" do
context "when logged in as an admin" do
before { sign_in(admin) }
context 'while logged in as an admin' do
fab!(:admin) { Fabricate(:admin) }
before do
sign_in(admin)
end
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,12 +24,205 @@ RSpec.describe Admin::SiteSettingsController do
end
end
describe '#update' do
before do
SiteSetting.setting(:test_setting, "default")
SiteSetting.setting(:test_upload, "", type: :upload)
SiteSetting.refresh!
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
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
put "/admin/site_settings/default_categories_watching/user_count.json", params: {
default_categories_watching: category_id
}
expect(response.parsed_body["user_count"]).to eq(User.real.where(staged: false).count)
CategoryUser.create!(category_id: category_id, notification_level: tracking, user: user)
put "/admin/site_settings/default_categories_watching/user_count.json", params: {
default_categories_watching: category_id
}
expect(response.parsed_body["user_count"]).to eq(User.real.where(staged: false).count - 1)
SiteSetting.setting(:default_categories_watching, "")
end
it 'should return correct user count for default tags change' do
tag = Fabricate(:tag)
put "/admin/site_settings/default_tags_watching/user_count.json", params: {
default_tags_watching: tag.name
}
expect(response.parsed_body["user_count"]).to eq(User.real.where(staged: false).count)
TagUser.create!(tag_id: tag.id, notification_level: tracking, user: user)
put "/admin/site_settings/default_tags_watching/user_count.json", params: {
default_tags_watching: tag.name
}
expect(response.parsed_body["user_count"]).to eq(User.real.where(staged: false).count - 1)
SiteSetting.setting(:default_tags_watching, "")
end
context "for sidebar defaults" do
it 'returns the right count for the default_sidebar_categories site setting' do
category = Fabricate(:category)
put "/admin/site_settings/default_sidebar_categories/user_count.json", params: {
default_sidebar_categories: "#{category.id}"
}
expect(response.status).to eq(200)
expect(response.parsed_body["user_count"]).to eq(User.real.not_staged.count)
end
it 'returns the right count for the default_sidebar_tags site setting' do
tag = Fabricate(:tag)
put "/admin/site_settings/default_sidebar_tags/user_count.json", params: {
default_sidebar_tags: "#{tag.name}"
}
expect(response.status).to eq(200)
expect(response.parsed_body["user_count"]).to eq(User.real.not_staged.count)
end
end
context "with user options" do
def expect_user_count(site_setting_name:, user_setting_name:, current_site_setting_value:, new_site_setting_value:,
current_user_setting_value: nil, new_user_setting_value: nil)
current_user_setting_value ||= current_site_setting_value
new_user_setting_value ||= new_site_setting_value
SiteSetting.public_send("#{site_setting_name}=", current_site_setting_value)
UserOption.human_users.update_all(user_setting_name => current_user_setting_value)
user_count = User.human_users.count
# Correctly counts users when all of them have default value
put "/admin/site_settings/#{site_setting_name}/user_count.json", params: {
site_setting_name => new_site_setting_value
}
expect(response.parsed_body["user_count"]).to eq(user_count)
# Correctly counts users when one of them already has new value
user.user_option.update!(user_setting_name => new_user_setting_value)
put "/admin/site_settings/#{site_setting_name}/user_count.json", params: {
site_setting_name => new_site_setting_value
}
expect(response.parsed_body["user_count"]).to eq(user_count - 1)
# Correctly counts users when site setting value has been changed
SiteSetting.public_send("#{site_setting_name}=", new_site_setting_value)
put "/admin/site_settings/#{site_setting_name}/user_count.json", params: {
site_setting_name => current_site_setting_value
}
expect(response.parsed_body["user_count"]).to eq(1)
end
it "should return correct user count for boolean setting" do
expect_user_count(
site_setting_name: "default_other_external_links_in_new_tab",
user_setting_name: "external_links_in_new_tab",
current_site_setting_value: false,
new_site_setting_value: true
)
end
it "should return correct user count for 'text_size_key'" do
expect_user_count(
site_setting_name: "default_text_size",
user_setting_name: "text_size_key",
current_site_setting_value: "normal",
new_site_setting_value: "larger",
current_user_setting_value: UserOption.text_sizes[:normal],
new_user_setting_value: UserOption.text_sizes[:larger]
)
end
it "should return correct user count for 'title_count_mode_key'" do
expect_user_count(
site_setting_name: "default_title_count_mode",
user_setting_name: "title_count_mode_key",
current_site_setting_value: "notifications",
new_site_setting_value: "contextual",
current_user_setting_value: UserOption.title_count_modes[:notifications],
new_user_setting_value: UserOption.title_count_modes[:contextual]
)
end
end
end
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: {
@ -70,7 +259,7 @@ RSpec.describe Admin::SiteSettingsController do
expect(SiteSetting.test_setting).to eq('')
end
describe 'default user options' do
context "with default user options" do
let!(:user1) { Fabricate(:user) }
let!(:user2) { Fabricate(:user) }
@ -154,7 +343,7 @@ RSpec.describe Admin::SiteSettingsController do
end
end
describe 'default categories' do
context "with default categories" do
fab!(:user1) { Fabricate(:user) }
fab!(:user2) { Fabricate(:user) }
fab!(:staged_user) { Fabricate(:staged) }
@ -219,7 +408,7 @@ RSpec.describe Admin::SiteSettingsController do
end
end
describe 'default tags' do
context "with default tags" do
fab!(:user1) { Fabricate(:user) }
fab!(:user2) { Fabricate(:user) }
fab!(:staged_user) { Fabricate(:staged) }
@ -258,141 +447,7 @@ RSpec.describe Admin::SiteSettingsController do
end
end
describe '#user_count' do
fab!(:user) { Fabricate(:user) }
fab!(:staged_user) { Fabricate(:staged) }
let(:tracking) { NotificationLevels.all[:tracking] }
it 'should return correct user count for default categories change' do
category_id = Fabricate(:category).id
put "/admin/site_settings/default_categories_watching/user_count.json", params: {
default_categories_watching: category_id
}
expect(response.parsed_body["user_count"]).to eq(User.real.where(staged: false).count)
CategoryUser.create!(category_id: category_id, notification_level: tracking, user: user)
put "/admin/site_settings/default_categories_watching/user_count.json", params: {
default_categories_watching: category_id
}
expect(response.parsed_body["user_count"]).to eq(User.real.where(staged: false).count - 1)
SiteSetting.setting(:default_categories_watching, "")
end
it 'should return correct user count for default tags change' do
tag = Fabricate(:tag)
put "/admin/site_settings/default_tags_watching/user_count.json", params: {
default_tags_watching: tag.name
}
expect(response.parsed_body["user_count"]).to eq(User.real.where(staged: false).count)
TagUser.create!(tag_id: tag.id, notification_level: tracking, user: user)
put "/admin/site_settings/default_tags_watching/user_count.json", params: {
default_tags_watching: tag.name
}
expect(response.parsed_body["user_count"]).to eq(User.real.where(staged: false).count - 1)
SiteSetting.setting(:default_tags_watching, "")
end
context "for sidebar defaults" do
it 'returns the right count for the default_sidebar_categories site setting' do
category = Fabricate(:category)
put "/admin/site_settings/default_sidebar_categories/user_count.json", params: {
default_sidebar_categories: "#{category.id}"
}
expect(response.status).to eq(200)
expect(response.parsed_body["user_count"]).to eq(User.real.not_staged.count)
end
it 'returns the right count for the default_sidebar_tags site setting' do
tag = Fabricate(:tag)
put "/admin/site_settings/default_sidebar_tags/user_count.json", params: {
default_sidebar_tags: "#{tag.name}"
}
expect(response.status).to eq(200)
expect(response.parsed_body["user_count"]).to eq(User.real.not_staged.count)
end
end
context "with user options" do
def expect_user_count(site_setting_name:, user_setting_name:, current_site_setting_value:, new_site_setting_value:,
current_user_setting_value: nil, new_user_setting_value: nil)
current_user_setting_value ||= current_site_setting_value
new_user_setting_value ||= new_site_setting_value
SiteSetting.public_send("#{site_setting_name}=", current_site_setting_value)
UserOption.human_users.update_all(user_setting_name => current_user_setting_value)
user_count = User.human_users.count
# Correctly counts users when all of them have default value
put "/admin/site_settings/#{site_setting_name}/user_count.json", params: {
site_setting_name => new_site_setting_value
}
expect(response.parsed_body["user_count"]).to eq(user_count)
# Correctly counts users when one of them already has new value
user.user_option.update!(user_setting_name => new_user_setting_value)
put "/admin/site_settings/#{site_setting_name}/user_count.json", params: {
site_setting_name => new_site_setting_value
}
expect(response.parsed_body["user_count"]).to eq(user_count - 1)
# Correctly counts users when site setting value has been changed
SiteSetting.public_send("#{site_setting_name}=", new_site_setting_value)
put "/admin/site_settings/#{site_setting_name}/user_count.json", params: {
site_setting_name => current_site_setting_value
}
expect(response.parsed_body["user_count"]).to eq(1)
end
it "should return correct user count for boolean setting" do
expect_user_count(
site_setting_name: "default_other_external_links_in_new_tab",
user_setting_name: "external_links_in_new_tab",
current_site_setting_value: false,
new_site_setting_value: true
)
end
it "should return correct user count for 'text_size_key'" do
expect_user_count(
site_setting_name: "default_text_size",
user_setting_name: "text_size_key",
current_site_setting_value: "normal",
new_site_setting_value: "larger",
current_user_setting_value: UserOption.text_sizes[:normal],
new_user_setting_value: UserOption.text_sizes[:larger]
)
end
it "should return correct user count for 'title_count_mode_key'" do
expect_user_count(
site_setting_name: "default_title_count_mode",
user_setting_name: "title_count_mode_key",
current_site_setting_value: "notifications",
new_site_setting_value: "contextual",
current_user_setting_value: UserOption.title_count_modes[:notifications],
new_user_setting_value: UserOption.title_count_modes[:contextual]
)
end
end
end
describe 'upload site settings' do
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
describe '#index' do
context "when logged in as an admin" do
before { sign_in(admin) }
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
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
describe '#show' do
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
describe '#update & #revert' do
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,26 +572,53 @@ RSpec.describe Admin::SiteTextsController do
end
end
context "when reseeding" do
before do
staff_category = Fabricate(
:category,
name: "Staff EN",
user: Discourse.system_user
)
SiteSetting.staff_category_id = staff_category.id
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 }
}
guidelines_topic = Fabricate(
:topic,
title: "The English Guidelines",
category: @staff_category,
user: Discourse.system_user
)
Fabricate(:post, topic: guidelines_topic, user: Discourse.system_user)
SiteSetting.guidelines_topic_id = 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 "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(
:category,
name: "Staff EN",
user: Discourse.system_user
)
SiteSetting.staff_category_id = staff_category.id
guidelines_topic = Fabricate(
:topic,
title: "The English Guidelines",
category: @staff_category,
user: Discourse.system_user
)
Fabricate(:post, topic: guidelines_topic, user: Discourse.system_user)
SiteSetting.guidelines_topic_id = guidelines_topic.id
end
describe '#get_reseed_options' do
context "when logged in as an admin" do
before { sign_in(admin) }
describe '#get_reseed_options' do
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
describe '#reseed' do
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,99 +1,146 @@
# 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
topic = Fabricate(:topic)
StaffActionLogger.new(Discourse.system_user).log_topic_delete_recover(topic, "delete_topic")
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")
get "/admin/logs/staff_action_logs.json", params: { action_id: UserHistory.actions[:delete_topic] }
json = response.parsed_body
expect(response.status).to eq(200)
expect(json["staff_action_logs"].length).to eq(1)
expect(json["staff_action_logs"][0]["action_name"]).to eq("delete_topic")
expect(json["extras"]["user_history_actions"]).to include(
"id" => 'delete_topic', "action_id" => UserHistory.actions[:delete_topic]
)
end
it 'generates logs with pages' do
1.upto(4).each do |idx|
StaffActionLogger.new(Discourse.system_user).log_site_setting_change("title", "value #{idx - 1}", "value #{idx}")
end
get "/admin/logs/staff_action_logs.json", params: { limit: 3 }
json = response.parsed_body
expect(response.status).to eq(200)
expect(json["staff_action_logs"].length).to eq(3)
expect(json["staff_action_logs"][0]["new_value"]).to eq("value 4")
get "/admin/logs/staff_action_logs.json", params: { limit: 3, page: 1 }
json = response.parsed_body
expect(response.status).to eq(200)
expect(json["staff_action_logs"].length).to eq(1)
expect(json["staff_action_logs"][0]["new_value"]).to eq("value 1")
end
context 'when staff actions are extended' do
let(:plugin_extended_action) { :confirmed_ham }
before { UserHistory.stubs(:staff_actions).returns([plugin_extended_action]) }
after { UserHistory.unstub(:staff_actions) }
it 'Uses the custom_staff id' do
get "/admin/logs/staff_action_logs.json", params: {}
get "/admin/logs/staff_action_logs.json", params: { action_id: UserHistory.actions[:delete_topic] }
json = response.parsed_body
action = json['extras']['user_history_actions'].first
expect(response.status).to eq(200)
expect(action['id']).to eq plugin_extended_action.to_s
expect(action['action_id']).to eq UserHistory.actions[:custom_staff]
expect(json["staff_action_logs"].length).to eq(1)
expect(json["staff_action_logs"][0]["action_name"]).to eq("delete_topic")
expect(json["extras"]["user_history_actions"]).to include(
"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|
StaffActionLogger.new(Discourse.system_user).log_site_setting_change("title", "value #{idx - 1}", "value #{idx}")
end
get "/admin/logs/staff_action_logs.json", params: { limit: 3 }
json = response.parsed_body
expect(response.status).to eq(200)
expect(json["staff_action_logs"].length).to eq(3)
expect(json["staff_action_logs"][0]["new_value"]).to eq("value 4")
get "/admin/logs/staff_action_logs.json", params: { limit: 3, page: 1 }
json = response.parsed_body
expect(response.status).to eq(200)
expect(json["staff_action_logs"].length).to eq(1)
expect(json["staff_action_logs"][0]["new_value"]).to eq("value 1")
end
context 'when staff actions are extended' do
let(:plugin_extended_action) { :confirmed_ham }
before { UserHistory.stubs(:staff_actions).returns([plugin_extended_action]) }
after { UserHistory.unstub(:staff_actions) }
it 'Uses the custom_staff id' do
get "/admin/logs/staff_action_logs.json", params: {}
json = response.parsed_body
action = json['extras']['user_history_actions'].first
expect(action['id']).to eq plugin_extended_action.to_s
expect(action['action_id']).to eq UserHistory.actions[:custom_staff]
end
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
theme = Fabricate(:theme)
theme.set_field(target: :mobile, name: :scss, value: 'body {.up}')
theme.set_field(target: :common, name: :scss, value: 'omit-dupe')
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')
original_json = ThemeSerializer.new(theme, root: false).to_json
original_json = ThemeSerializer.new(theme, root: false).to_json
theme.set_field(target: :mobile, name: :scss, value: 'body {.down}')
theme.set_field(target: :mobile, name: :scss, value: 'body {.down}')
record = StaffActionLogger.new(Discourse.system_user)
.log_theme_change(original_json, theme)
record = StaffActionLogger.new(Discourse.system_user)
.log_theme_change(original_json, theme)
get "/admin/logs/staff_action_logs/#{record.id}/diff.json"
expect(response.status).to eq(200)
get "/admin/logs/staff_action_logs/#{record.id}/diff.json"
expect(response.status).to eq(200)
parsed = response.parsed_body
expect(parsed["side_by_side"]).to include("up")
expect(parsed["side_by_side"]).to include("down")
parsed = response.parsed_body
expect(parsed["side_by_side"]).to include("up")
expect(parsed["side_by_side"]).to include("down")
expect(parsed["side_by_side"]).not_to include("omit-dupe")
expect(parsed["side_by_side"]).not_to include("omit-dupe")
end
end
it 'is not erroring when current value is empty' 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(200)
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)
StaffActionLogger.new(admin).log_theme_destroy(theme)
get "/admin/logs/staff_action_logs/#{UserHistory.last.id}/diff.json"
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

File diff suppressed because it is too large Load Diff

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
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
context "when logged in" do
fab!(:admin) { Fabricate(:admin) }
describe '#create' do
context "when logged in as an admin" do
before { sign_in(admin) }
before do
sign_in(admin)
end
describe '#create' do
it "creates a user field" do
expect {
post "/admin/customize/user_fields.json", params: {
@ -41,8 +37,37 @@ RSpec.describe Admin::UserFieldsController do
end
end
describe '#index' do
fab!(:user_field) { Fabricate(:user_field) }
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"
@ -52,8 +77,34 @@ RSpec.describe Admin::UserFieldsController do
end
end
describe '#destroy' do
fab!(:user_field) { Fabricate(:user_field) }
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 {
@ -63,8 +114,35 @@ RSpec.describe Admin::UserFieldsController do
end
end
describe '#update' do
fab!(:user_field) { Fabricate(:user_field) }
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: {
@ -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
fab!(:web_hook) { Fabricate(:web_hook) }
fab!(:admin) { Fabricate(:admin) }
fab!(:moderator) { Fabricate(:moderator) }
fab!(:user) { Fabricate(:user) }
it 'is a subclass of AdminController' do
expect(Admin::WebHooksController < Admin::AdminController).to eq(true)
end
describe '#create' do
context "when logged in as admin" do
before { sign_in(admin) }
context 'while logged in as an admin' do
fab!(:web_hook) { Fabricate(:web_hook) }
fab!(:admin) { Fabricate(:admin) }
before do
sign_in(admin)
end
describe '#create' do
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
describe '#update' do
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
describe '#destroy' do
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
describe '#ping' do
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,62 +184,87 @@ RSpec.describe Admin::WebHooksController do
end
end
describe '#redeliver_event' do
let!(:web_hook_event) do
WebHookEvent.create!(
web_hook: web_hook,
payload: "abc",
headers: JSON.dump(aa: "1", bb: "2"),
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!(
web_hook: web_hook,
payload: "abc",
headers: JSON.dump(aa: "1", bb: "2"),
)
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 })
.to_return(
status: 402,
body: "efg",
headers: { "Content-Type" => "application/json", "yoo" => "man" }
)
end
post "/admin/api/web_hooks/#{web_hook.id}/events/#{web_hook_event.id}/redeliver.json"
expect(response.status).to eq(200)
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 })
.to_return(
status: 402,
body: "efg",
headers: { "Content-Type" => "application/json", "yoo" => "man" }
)
parsed_event = response.parsed_body["web_hook_event"]
expect(parsed_event["id"]).to eq(web_hook_event.id)
expect(parsed_event["status"]).to eq(402)
expect(JSON.parse(parsed_event["headers"])).to eq({ "aa" => "1", "bb" => "2" })
expect(parsed_event["payload"]).to eq("abc")
expect(JSON.parse(parsed_event["response_headers"])).to eq({ "content-type" => "application/json", "yoo" => "man" })
expect(parsed_event["response_body"]).to eq("efg")
end
it "doesn't emit the web hook if the payload URL resolves to an internal IP" do
FinalDestination::TestHelper.stub_to_fail do
post "/admin/api/web_hooks/#{web_hook.id}/events/#{web_hook_event.id}/redeliver.json"
expect(response.status).to eq(200)
parsed_event = response.parsed_body["web_hook_event"]
expect(parsed_event["id"]).to eq(web_hook_event.id)
expect(parsed_event["status"]).to eq(402)
expect(JSON.parse(parsed_event["headers"])).to eq({ "aa" => "1", "bb" => "2" })
expect(parsed_event["payload"]).to eq("abc")
expect(JSON.parse(parsed_event["response_headers"])).to eq({ "content-type" => "application/json", "yoo" => "man" })
expect(parsed_event["response_body"]).to eq("efg")
end
expect(response.status).to eq(200)
it "doesn't emit the web hook if the payload URL resolves to an internal IP" do
FinalDestination::TestHelper.stub_to_fail do
post "/admin/api/web_hooks/#{web_hook.id}/events/#{web_hook_event.id}/redeliver.json"
end
expect(response.status).to eq(200)
parsed_event = response.parsed_body["web_hook_event"]
expect(parsed_event["id"]).to eq(web_hook_event.id)
expect(parsed_event["response_headers"]).to eq({ error: I18n.t("webhooks.payload_url.blocked_or_internal") }.to_json)
expect(parsed_event["status"]).to eq(-1)
expect(parsed_event["response_body"]).to eq(nil)
end
parsed_event = response.parsed_body["web_hook_event"]
expect(parsed_event["id"]).to eq(web_hook_event.id)
expect(parsed_event["response_headers"]).to eq({ error: I18n.t("webhooks.payload_url.blocked_or_internal") }.to_json)
expect(parsed_event["status"]).to eq(-1)
expect(parsed_event["response_body"]).to eq(nil)
it "doesn't emit the web hook if the payload URL resolves to a blocked IP" do
FinalDestination::TestHelper.stub_to_fail do
post "/admin/api/web_hooks/#{web_hook.id}/events/#{web_hook_event.id}/redeliver.json"
end
expect(response.status).to eq(200)
it "doesn't emit the web hook if the payload URL resolves to a blocked IP" do
FinalDestination::TestHelper.stub_to_fail do
post "/admin/api/web_hooks/#{web_hook.id}/events/#{web_hook_event.id}/redeliver.json"
end
expect(response.status).to eq(200)
parsed_event = response.parsed_body["web_hook_event"]
expect(parsed_event["id"]).to eq(web_hook_event.id)
expect(parsed_event["response_headers"]).to eq({ error: I18n.t("webhooks.payload_url.blocked_or_internal") }.to_json)
expect(parsed_event["status"]).to eq(-1)
expect(parsed_event["response_body"]).to eq(nil)
end
parsed_event = response.parsed_body["web_hook_event"]
expect(parsed_event["id"]).to eq(web_hook_event.id)
expect(parsed_event["response_headers"]).to eq({ error: I18n.t("webhooks.payload_url.blocked_or_internal") }.to_json)
expect(parsed_event["status"]).to eq(-1)
expect(parsed_event["response_body"]).to eq(nil)
end
end
end