Fix issue with impersonation
This commit is contained in:
parent
80893cad67
commit
d3462e711c
9 changed files with 192 additions and 69 deletions
|
@ -6,12 +6,6 @@ class Admin::ApplicationController < ApplicationController
|
|||
layout 'admin'
|
||||
|
||||
def authenticate_admin!
|
||||
return render_404 unless current_user.is_admin?
|
||||
end
|
||||
|
||||
def authorize_impersonator!
|
||||
if session[:impersonator_id]
|
||||
User.find_by!(username: session[:impersonator_id]).admin?
|
||||
end
|
||||
render_404 unless current_user.is_admin?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
class Admin::ImpersonationController < Admin::ApplicationController
|
||||
skip_before_action :authenticate_admin!, only: :destroy
|
||||
|
||||
before_action :user
|
||||
before_action :authorize_impersonator!
|
||||
|
||||
def create
|
||||
if @user.blocked?
|
||||
flash[:alert] = "You cannot impersonate a blocked user"
|
||||
|
||||
redirect_to admin_user_path(@user)
|
||||
else
|
||||
session[:impersonator_id] = current_user.username
|
||||
session[:impersonator_return_to] = admin_user_path(@user)
|
||||
|
||||
warden.set_user(user, scope: 'user')
|
||||
|
||||
flash[:alert] = "You are impersonating #{user.username}."
|
||||
|
||||
redirect_to root_path
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
redirect = session[:impersonator_return_to]
|
||||
|
||||
warden.set_user(user, scope: 'user')
|
||||
|
||||
session[:impersonator_return_to] = nil
|
||||
session[:impersonator_id] = nil
|
||||
|
||||
redirect_to redirect || root_path
|
||||
end
|
||||
|
||||
def user
|
||||
@user ||= User.find_by!(username: params[:id] || session[:impersonator_id])
|
||||
end
|
||||
end
|
28
app/controllers/admin/impersonations_controller.rb
Normal file
28
app/controllers/admin/impersonations_controller.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
class Admin::ImpersonationsController < Admin::ApplicationController
|
||||
skip_before_action :authenticate_admin!
|
||||
before_action :authenticate_impersonator!
|
||||
|
||||
def destroy
|
||||
redirect_path = admin_user_path(current_user)
|
||||
|
||||
warden.set_user(impersonator, scope: :user)
|
||||
|
||||
session[:impersonator_id] = nil
|
||||
|
||||
redirect_to redirect_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def user
|
||||
@user ||= User.find(params[:id])
|
||||
end
|
||||
|
||||
def impersonator
|
||||
@impersonator ||= User.find(session[:impersonator_id]) if session[:impersonator_id]
|
||||
end
|
||||
|
||||
def authenticate_impersonator!
|
||||
render_404 unless impersonator && impersonator.is_admin? && !impersonator.blocked?
|
||||
end
|
||||
end
|
|
@ -31,6 +31,22 @@ class Admin::UsersController < Admin::ApplicationController
|
|||
user
|
||||
end
|
||||
|
||||
def impersonate
|
||||
if user.blocked?
|
||||
flash[:alert] = "You cannot impersonate a blocked user"
|
||||
|
||||
redirect_to admin_user_path(user)
|
||||
else
|
||||
session[:impersonator_id] = current_user.id
|
||||
|
||||
warden.set_user(user, scope: :user)
|
||||
|
||||
flash[:alert] = "You are now impersonating #{user.username}"
|
||||
|
||||
redirect_to root_path
|
||||
end
|
||||
end
|
||||
|
||||
def block
|
||||
if user.block
|
||||
redirect_back_or_admin_user(notice: "Successfully blocked")
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
- if current_user
|
||||
- if session[:impersonator_id]
|
||||
%li.impersonation
|
||||
= link_to stop_impersonation_admin_users_path, method: :delete, title: 'Stop Impersonation', data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
|
||||
= link_to admin_impersonation_path, method: :delete, title: 'Stop Impersonation', data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
|
||||
= icon('user-secret fw')
|
||||
- if current_user.is_admin?
|
||||
%li
|
||||
|
|
|
@ -212,8 +212,6 @@ Rails.application.routes.draw do
|
|||
resources :keys, only: [:show, :destroy]
|
||||
resources :identities, except: [:show]
|
||||
|
||||
delete 'stop_impersonation' => 'impersonation#destroy', on: :collection
|
||||
|
||||
member do
|
||||
get :projects
|
||||
get :keys
|
||||
|
@ -223,12 +221,14 @@ Rails.application.routes.draw do
|
|||
put :unblock
|
||||
put :unlock
|
||||
put :confirm
|
||||
post 'impersonate' => 'impersonation#create'
|
||||
post :impersonate
|
||||
patch :disable_two_factor
|
||||
delete 'remove/:email_id', action: 'remove_email', as: 'remove_email'
|
||||
end
|
||||
end
|
||||
|
||||
resource :impersonation, only: :destroy
|
||||
|
||||
resources :abuse_reports, only: [:index, :destroy]
|
||||
resources :spam_logs, only: [:index, :destroy]
|
||||
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Admin::ImpersonationController do
|
||||
let(:admin) { create(:admin) }
|
||||
|
||||
before do
|
||||
sign_in(admin)
|
||||
end
|
||||
|
||||
describe 'CREATE #impersonation when blocked' do
|
||||
let(:blocked_user) { create(:user, state: :blocked) }
|
||||
|
||||
it 'does not allow impersonation' do
|
||||
post :create, id: blocked_user.username
|
||||
|
||||
expect(flash[:alert]).to eq 'You cannot impersonate a blocked user'
|
||||
end
|
||||
end
|
||||
end
|
95
spec/controllers/admin/impersonations_controller_spec.rb
Normal file
95
spec/controllers/admin/impersonations_controller_spec.rb
Normal file
|
@ -0,0 +1,95 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Admin::ImpersonationsController do
|
||||
let(:impersonator) { create(:admin) }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
describe "DELETE destroy" do
|
||||
context "when not signed in" do
|
||||
it "redirects to the sign in page" do
|
||||
delete :destroy
|
||||
|
||||
expect(response).to redirect_to(new_user_session_path)
|
||||
end
|
||||
end
|
||||
|
||||
context "when signed in" do
|
||||
before do
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
context "when not impersonating" do
|
||||
it "responds with status 404" do
|
||||
delete :destroy
|
||||
|
||||
expect(response.status).to eq(404)
|
||||
end
|
||||
|
||||
it "doesn't sign us in" do
|
||||
delete :destroy
|
||||
|
||||
expect(warden.user).to eq(user)
|
||||
end
|
||||
end
|
||||
|
||||
context "when impersonating" do
|
||||
before do
|
||||
session[:impersonator_id] = impersonator.id
|
||||
end
|
||||
|
||||
context "when the impersonator is not impersonator (anymore)" do
|
||||
before do
|
||||
impersonator.admin = false
|
||||
impersonator.save
|
||||
end
|
||||
|
||||
it "responds with status 404" do
|
||||
delete :destroy
|
||||
|
||||
expect(response.status).to eq(404)
|
||||
end
|
||||
|
||||
it "doesn't sign us in as the impersonator" do
|
||||
delete :destroy
|
||||
|
||||
expect(warden.user).to eq(user)
|
||||
end
|
||||
end
|
||||
|
||||
context "when the impersonator is admin" do
|
||||
context "when the impersonator is blocked" do
|
||||
before do
|
||||
impersonator.block!
|
||||
end
|
||||
|
||||
it "responds with status 404" do
|
||||
delete :destroy
|
||||
|
||||
expect(response.status).to eq(404)
|
||||
end
|
||||
|
||||
it "doesn't sign us in as the impersonator" do
|
||||
delete :destroy
|
||||
|
||||
expect(warden.user).to eq(user)
|
||||
end
|
||||
end
|
||||
|
||||
context "when the impersonator is not blocked" do
|
||||
it "redirects to the impersonated user's page" do
|
||||
delete :destroy
|
||||
|
||||
expect(response).to redirect_to(admin_user_path(user))
|
||||
end
|
||||
|
||||
it "signs us in as the impersonator" do
|
||||
delete :destroy
|
||||
|
||||
expect(warden.user).to eq(impersonator)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,9 +2,10 @@ require 'spec_helper'
|
|||
|
||||
describe Admin::UsersController do
|
||||
let(:user) { create(:user) }
|
||||
let(:admin) { create(:admin) }
|
||||
|
||||
before do
|
||||
sign_in(create(:admin))
|
||||
sign_in(admin)
|
||||
end
|
||||
|
||||
describe 'DELETE #user with projects' do
|
||||
|
@ -112,4 +113,50 @@ describe Admin::UsersController do
|
|||
patch :disable_two_factor, id: user.to_param
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST impersonate" do
|
||||
context "when the user is blocked" do
|
||||
before do
|
||||
user.block!
|
||||
end
|
||||
|
||||
it "shows a notice" do
|
||||
post :impersonate, id: user.username
|
||||
|
||||
expect(flash[:alert]).to eq("You cannot impersonate a blocked user")
|
||||
end
|
||||
|
||||
it "doesn't sign us in as the user" do
|
||||
post :impersonate, id: user.username
|
||||
|
||||
expect(warden.user).to eq(admin)
|
||||
end
|
||||
end
|
||||
|
||||
context "when the user is not blocked" do
|
||||
it "stores the impersonator in the session" do
|
||||
post :impersonate, id: user.username
|
||||
|
||||
expect(session[:impersonator_id]).to eq(admin.id)
|
||||
end
|
||||
|
||||
it "signs us in as the user" do
|
||||
post :impersonate, id: user.username
|
||||
|
||||
expect(warden.user).to eq(user)
|
||||
end
|
||||
|
||||
it "redirects to root" do
|
||||
post :impersonate, id: user.username
|
||||
|
||||
expect(response).to redirect_to(root_path)
|
||||
end
|
||||
|
||||
it "shows a notice" do
|
||||
post :impersonate, id: user.username
|
||||
|
||||
expect(flash[:alert]).to eq("You are now impersonating #{user.username}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue