mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-03 20:07:47 +08:00
The current impersonation feature works by signing you in as the user you are impersonating. This has the side effect of invalidating your own session and forcing you to log out and in again. In this experimental implementation you keep your existing session, but DefaultCurrentUserProvider returns the user being impersonated, allowing you to see the site from their perspective.
151 lines
4.5 KiB
Ruby
151 lines
4.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe Admin::ImpersonateController do
|
|
fab!(:admin)
|
|
fab!(:moderator)
|
|
fab!(:user)
|
|
fab!(:another_admin, :admin)
|
|
|
|
describe "#index" do
|
|
context "when logged in as an admin" do
|
|
before { sign_in(admin) }
|
|
|
|
it "returns success" do
|
|
get "/admin/impersonate.json"
|
|
|
|
expect(response.status).to eq(200)
|
|
end
|
|
end
|
|
|
|
shared_examples "impersonation inaccessible" do
|
|
it "denies access with a 404 response" do
|
|
get "/admin/impersonate.json"
|
|
|
|
expect(response.status).to eq(404)
|
|
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
|
|
end
|
|
end
|
|
|
|
context "when logged in as a moderator" do
|
|
before { sign_in(moderator) }
|
|
|
|
include_examples "impersonation inaccessible"
|
|
end
|
|
|
|
context "when logged in as a non-staff user" do
|
|
before { sign_in(user) }
|
|
|
|
include_examples "impersonation inaccessible"
|
|
end
|
|
end
|
|
|
|
describe "#create" do
|
|
context "when logged in as an admin" do
|
|
before { sign_in(admin) }
|
|
|
|
it "requires a username_or_email parameter" do
|
|
post "/admin/impersonate.json"
|
|
expect(response.status).to eq(400)
|
|
expect(session[:current_user_id]).to eq(admin.id)
|
|
end
|
|
|
|
it "returns 404 when that user does not exist" do
|
|
post "/admin/impersonate.json", params: { username_or_email: "hedonismbot" }
|
|
expect(response.status).to eq(404)
|
|
expect(session[:current_user_id]).to eq(admin.id)
|
|
end
|
|
|
|
it "raises an invalid access error if the user can't be impersonated" do
|
|
post "/admin/impersonate.json", params: { username_or_email: another_admin.email }
|
|
expect(response.status).to eq(403)
|
|
expect(session[:current_user_id]).to eq(admin.id)
|
|
end
|
|
|
|
context "when using experimental impersonation feature" do
|
|
it "raises an invalid access error if admin is already impersonating someone" do
|
|
SiteSetting.experimental_impersonation = true
|
|
User.any_instance.stubs(:is_impersonating).returns(true)
|
|
|
|
post "/admin/impersonate.json", params: { username_or_email: user.username }
|
|
|
|
expect(response.status).to eq(403)
|
|
expect(session[:current_user_id]).to eq(admin.id)
|
|
end
|
|
end
|
|
|
|
context "with success" do
|
|
it "succeeds and logs the impersonation" do
|
|
expect do
|
|
post "/admin/impersonate.json", params: { username_or_email: user.username }
|
|
end.to change { UserHistory.where(action: UserHistory.actions[:impersonate]).count }.by(1)
|
|
|
|
expect(response.status).to eq(200)
|
|
expect(session[:current_user_id]).to eq(user.id)
|
|
end
|
|
|
|
it "also works with an email address" do
|
|
post "/admin/impersonate.json", params: { username_or_email: user.email }
|
|
expect(response.status).to eq(200)
|
|
expect(session[:current_user_id]).to eq(user.id)
|
|
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
|
|
|
|
describe "#destroy" do
|
|
before { sign_in(admin) }
|
|
|
|
it "raises a not found error when experimental impersonation is disabled" do
|
|
SiteSetting.experimental_impersonation = false
|
|
|
|
delete "/admin/impersonate.json"
|
|
|
|
expect(response.status).to eq(404)
|
|
end
|
|
|
|
it "does not pass routing constraint when current user is not impersonating" do
|
|
SiteSetting.experimental_impersonation = true
|
|
User.any_instance.stubs(:is_impersonating).returns(false)
|
|
|
|
delete "/admin/impersonate.json"
|
|
|
|
expect(response.status).to eq(404)
|
|
end
|
|
|
|
it "stops impersonating" do
|
|
SiteSetting.experimental_impersonation = true
|
|
User.any_instance.stubs(:is_impersonating).returns(true)
|
|
|
|
delete "/admin/impersonate.json"
|
|
|
|
expect(response.status).to eq(200)
|
|
end
|
|
end
|
|
end
|