Rails Devise + Devise-bascamper How to allow superuser to log into any account?

I use devection and devise-basecamper to authenticate with my subdomain based web application.

I would like to allow superusers to access any of the accounts (basically, any subdomain).

I'm not sure how I would do this so that the user can be authenticated in any subdomain, as the user is currently being checked against a specific subdomain.

Any ideas?

+4
source share
6 answers

In the end, I had to remove the unique email index from the user table, which is created by default, and add a new unique index to the users table with the email and account_id columns. This will allow me to create a user (which I call support@example.com ) for each account created.

Here is my migration

 def change remove_index :users, :email add_index :users, [:email, :account_id], :unique => true end 

Here is my after_save callback that I added to my account model.

 class Account < ActiveRecord::Base after_save :create_support_user private # A callback that creates a support user after an account is created. def create_support_user user = User.new user.email = " support@example.com " user.password = "test1234" user.password_confirmation = "test1234" user.account_id = self.id user.name = "Support" user.skip_confirmation! user.admin = true user.save end end 
0
source

If I understand your needs correctly, the st-approach should follow these steps:

  • how the administrator can "become" another user to access your application, as if you used his credentials to log into the system
  • After "becoming" this user, you want to be able to "become" your real user again whenever you want, without having to log in again.
  • Keep admin rights while you become a different user (see answer below for this)
  • Avoid logs so that the mention of an action is done by the user you "became"

Become a user

This is necessary if you need to perform actions as another user or "see what he sees"

First you need to implement the official development method (this is pseudocode , I let you adapt it to your personal situation)

 # the usage of session[:original_user_id] is explained later def become if admin? or session[:original_user_id] if session[:original_user_id] == params[:id] session[:original_user_id] = nil # This is intended to clean-up stuff after you become your self back again else session[:original_user_id] = current_user.id # This is to record your real identity while you are becoming some one else end sign_in(:user, User.find(params[:id])) end end 

As you can see, we "become" the requested user, plus we write your real user.id into the session. Please note: if you choose this solution, you MUST configure the rails to store session data in the database, to prevent this data from being moved to cookies.

Coming back

Secondly, you need the link "back to you" somewhere in your presentation, I suggest the headline as a good place

 if session[:original_user_id] link_to 'Be my self', become_path(session[:original_user_id]) end 

This will create a link, visible only to the administrator, which has "become" someone else, and this link will allow you to "become" a user with an identifier that matches your real user account. Clicking on it will return your real identity.

Keep admin rights while you are another user

Then you want to preserve administrator privileges, we need to trick the system to make him believe that the user you "became" is an administrator, but we must protect the application so that it does not make unwanted saving of this "fake privilege" in the database

In your application controller, implement before the filter

 before_filter :fake_admin def fake_admin if session[:original_user_id] current_user.fake_admin = true current_user.admin = true end end 

Then, to protect the user record in order to obtain an undesired administrator privilege, in your user model you can set before_save_filter (or before_validation_filter, depending on your architecture).

 before_save :check_for_fake_admin def check_for_fake_admin self.admin = false if self.fake_admin end 

Avoid logs to indicate the username you become

You have no choice but to manually hack all the places in your application where the action should contain the administratorโ€™s name and not the username. The template in updated_by records must be set to session[:original_user_id] if it is not nil

Now it is necessary not only in magazines, but also for any other thing. It all depends on your application, and it can become very tedious to maintain.

Legal information

  • This is pseudo-code, unsafe, and if you choose this solution, you will need to ensure security
  • I answer your question because you asked, but my personal advice: do not implement this solution, because it looks like a big security hole, and you must allow the administrator to log out and log in after they become someone else .
+9
source

I use the following solution in my applications.

 class RandomController < ApplicationController  before_filter :authenticate_user!, unless: :super_user end class ApplicationController < ActionController::Base def super_user? current_user.email == ' super@example.com ' end end 
+3
source

There is a How To section in the development documentation : Log in as a different user if you are an administrator , which explains how to achieve what you are trying to do.

This is the essence of the documentation you have to do:

 class AdminController < ApplicationController before_filter authenticate_user! def become return unless current_user.is_an_admin? sign_in(:user, User.find(params[:id])) redirect_to root_url # or user_root_url end end 
+1
source

Authentication and authorization are two different actions, and I believe that this should be done separately. Use a development method for authentication and implement your own authorization code.

Example:

 class SomeController < ApplicationController before_filter :authenticate_user! before_filter :authorize_user end class ApplicationController < ActionController::Base def authorize_user unless current_user.admin? or request.subdomain == current_user.subdomain# logic to check if user is authorized redirect_to root_path, :notice => "Access denied" end end end 
+1
source

I think you need to separate authorization and authentication. Authentication checks if a specific account is valid, authorization assigns a set of resources to the user.

If I have general authorization, you can simply create a method in the ApplicationController that returns a resource (filtered) if the user has access to it. Or you can, for example, add an area for each active record model that is taxed by user_id if the user has only rights to view his resources.

0
source

Source: https://habr.com/ru/post/1484051/


All Articles