I want to allow an admin on my app to sign in as any user. I found the following on the devise wiki:
class AdminController < ApplicationController
# Sign in as another user if you are an admin
def become
return unless current_user.is_an_admin?
sign_in(:user, User.find(params[:id]))
redirect_to root_path
end
end
In the view, how do you build a form to post to this?
Thanks
You wouldn't even need to build a form, you could simply allow the admin to go to the following url:
example.com/admin/become?id=25
where 25 is the id you want to log into as.
So with this method, you would just create a link for an admin to click on.
Related
I am using devise for user registration/login, after the user has successfully signed up, I want to show a page/a dialog box and redirect to another page based on user response. How can I do that?
User Model (By devise)
username
password
Student Model
name
student_id
Teacher Model
name
grade
First_page:
signup signin links
Signup link will show the devise views/devise/registrations/new.html.erb page.
After successful signup, it takes the user to root page. I have defined the root page in routes.rb:
` Rails.application.routes.draw do
devise_for :users
resources :students, :teachers
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root to: "students#index"
end `
At this point, the application doesn't have any idea who the user is.
So, I want to get the identity information(student/teacher) from the user.
How will I get this information?
Student/Teacher controller:
`class StudentsController < ApplicationController
before_action :authenticate_user!, only: [:new, :create]
def index
#students = Student.all
end
def new
#student = Student.new
end
def create
current_user.create_student(student_params)
redirect_to root_path
end
private
def student_params
params.require(:student).permit(:name, :skypid)
end
end`
After the user has successfully signed in, I want to ask if the user is a student or teacher. Based on what they select, redirect them to a student form page or teacher form page.
How can I do that in rails?
Thank you
You can write a custom after_sign_in_path_for function in your ApplicationController assuming you're using all the default Devise controllers otherwise. Any named path helper or other route that it returns will be where the user is redirected, so you could do something simple like always redirect to a selection page that presents the options and handles the choice on a subsequent action:
def after_sign_in_path_for(resource)
user_type_selection_path # whatever route in your app manages the selection
end
Alternately, you could invoke a custom method on the user model in that function to make a choice right there:
def after_sign_in_path_for(resource)
resource.student? ? student_path : teacher_path
end
You could hybridize these of course as well to do the latter when the selection has already been made and redirect otherwise, with something similar to the following:
def after_sign_in_path_for(resource)
if resource.user_type_chosen?
resource.student? ? student_path : teacher_path
else
user_type_selection_path
end
Bear in mind that none of those functions or paths are real, since I can't be more specific on the information you've provided, but hopefully this gets you headed in the right direction. The after_sign_in_path_for hook is your primary tool here, unless you get into the world of overriding the default devise controllers and interrupting the usual workflow there to accommodate this step, which doesn't seem strictly necessary by your description.
I have created a user authentication using devise in rails app .Now i have to create a new model for Admin.i can do that by either creating a new admin model(devise) or write roles in user model like
example
class User < ActiveRecord::Base
enum :roles[:admin,:superadmin]
end
but how should I login as admin when without creating another SIGNUP OR LOGIN form.or if i create a diffrent regestration and login for admin how can I hide that from users.Inshort i need to create a admin panel and dashbord for admin and need some authorizations.iam new to rails plz help.also you can suggest me another approch for doing it (i dont want selec box or checkbox in my login for roles because anyone can become admin then)
EDIT:
I want to know about the authentication for admin and user ,authorization is the next part .if i create a diffrent admin registration form any user can come and become admin.what will be the other approch?.
Basically you can make additional model Role which will be [admin, superadmin, user] and will be related to User.
let's say user can have only one role (has_one) so when user is created you should assign a particular role to him. This way you can simply use:
current_user.role.name #=> "admin"
Good practice is to implement methods in User class:
def admin?
role.name == "admin"
end
def user?
role.name == "user"
end
So you can simply call: current_user.admin?.
I suggest you to use some authorization library, for restricting/allowing access to diff parts on your application.
There is a plenty of them, like Pundit, CanCan etc ...
Hope this will help you to start, then you will see how many options you have ;)
Update:
You're assigning role to user during registration process, or via admin panel later.
About register form, you will have RegistrationController which is overridden from Devise so you can simply put user.role = Role.find_by_name("user") before creating user.
This is default role for all users who are registered via register form. But, you will have some admin dashboard where you can change role for users and assign to them maybe to be moderator, admin, superadmin etc..
About login form, there is no need to assign role but just to get current_user and to get his role.
Let's say you have 2 different navigations for user & admin. When user is successfully logged in, in you application.html.erb layout you can do simply check :
<% if current_user.admin? %>
<%= render "navigation/admin_navigation" %>
<% elsif current_user.user? %>
<%= render "navigation/user_navigation" %>
<% end %>
This way you will show appropriate navigation, so this is authorization on view level.
You can also have authorization logic on controller level, for certain actions:
class PostsController < ApplicationController
before_action :authorize_admin, only: [:index]
private
def authorize_admin
redirect_to root_path, alert: "Permissions denied" unless
current_user.admin?
end
end
This way you're allowing ONLY admin to access to Posts#index.
Hope it's more clear now :)
Cheers
Very simple would be to create column for example "admin" type boolean in user model and based on that make permissions to administration.
You can create permisson check in application_controller.rb like this
def check_admin
unless current_user.admin
redirect_to '/', :alert => "Don't have permission!"
end
end
And use it in controller for actions only admin can make like this:
before_action :check_admin, only: [:edit, :create]
For more scurity use separate models for User and Admin with separate routes and view for Public and Admin users.
It is not direct answer to your question, but read some info on STI - single table inheritance.
And wherever you need special behavior for the admin you can just check if user type is admin
The simplest thing I can think of is to add a role column on the users table and check the value, for example:
class User < ActiveRecord::Base
def role
super.try(:inquiry)
end
end
user.role.admin?
It depends on your needs, do you really need a Role model or a separate User and Admin model. Do you need to know any more than is this user an admin, if not, this is an easy and simple solution.
I am using devise and want to redirect users to a confirmation page upon signup, this is what I am doing right now:
users/registrations_controller.html.erb
class Users::RegistrationsController < Devise::RegistrationsController
def confirm_email
end
private
def after_inactive_sign_up_path_for(resource)
users_confirmyouremail_path
end
end
config/routes.rb
devise_scope :user do
get 'users/confirmyouremail' => 'users/registrations#confirm_email'
end
I have no problem with redirecting the page after signup. However, I think it is quite weird that anyone can visit the page with url like `host.com/confirmyouremail' and see the confirmation page. Are there any ways I can write a route that will use random code that is allow only for one time visit? Thanks in advance.
Maybe something like this:
before_action :authenticate_user!
def confirm_mail
redirect_to root_path if current_user.confirmed
...
end
You are storing in the database if the user has already confirmed his account. If his account is confirmed then he won't be able to access this page. You can redirect to whatever page you want. A user without any account won't be able to access this page because of the before action
In case the user is not logged in when he accesses this confirm_mail page you have different possibilities. You could use a session or a cookie:
# after sign up:
session[:confirm] = true
# alternatively a cookie
cookies[:confirm] = true
Then in the confirm mail action:
def confirm_mail
if session[:confirm].blank? # or cookies[:confirm].blank?
redirect_to root_path
end
# otherwise delete the field from the session
session.delete(:confirm)
# alternatively the cookie
cookies.delete(:confirm)
end
Another way would be by using a Token. You create a new model like ConfirmMailToken. Then on sign up you create a new token and redirect the user to the confirm page with the token as a URL param. Then in the confirm_mail action you check if a token is available and delete it if it is. This way you ensure that the page is only shown after redirect.
I am working on an app in which there is a model User with roles member and Admin.
As per requirement, I have to made two separate login pages for Admin and Member.
with http://localhost:3000/admin/admin_login
it goes to admin login page and with
http://localhost:3000/users/sign_in
it goes to member login page.
Just after login I route them according to their roles to Admin panel or simple website for members.
But at time of logout both goes to
http://localhost:3000
but I want admin to go to http://localhost:3000/admin/admin_login,
while http://localhost:3000 is fine for member's logout.
Is there a way to see User's Role at time of Sign_out and route them accordingly.
You can define a after sign out path according to resource in application controller..
class ApplicationController < ActionController::Base
private
# Overwriting the sign_out redirect path method
def after_sign_out_path_for(resource_or_scope)
root_path
end
end
In after_sign_out_for_for method you can check user role and redirect to
For more details visit devise wiki After Sign out path in devise
I think you can try like this
Just save whatever path you want to redirect user after sign_out based on the role after login in session and use that session in after_sign_out_path_for method
after_filter :store_location
def store_location
return unless session[:login_url].blank?
session[:login_url] = current_user.admin? ? admin_path : other_user_path
end
def after_sign_out_path_for(resource)
session[:login_url] || request.referer || root_path
end
there are one other way just overwrite devise sessoin controller and redirect user from there based on role
# routes.rb
devise_for :users, :controllers => { :sessions => "sessions" } # etc
# sessions_controller.rb
class SessionsController < Devise::SessionsController
def destroy
#login_path = set path in a variable based on user role before sing_out
#code to sign out
#
redirect_to login_path
end
end
Are the pages that they are clicking on the logout links different for admins and users? If so, you could check the request.referrer property in your after_sign_out_path method and route accordingly.
BTW if you are routing them to the right pages after logging in then why do you need separate login pages? you may want to just have one login page for simplicity.
You can also leave it config.sign_out_via =: get => config/initializers/devise.rb is not the best way but solved for me.
How can I configure my Rails app such that after the form to create a new user is submitted (through devise), I redirect to my own desired page ?
Thank you
After the create user form is submitted the user is created and then logged in so the page you are being redirected to is actually the after log in page. If you only want to change this page when a user is created you can set session["#{resource_name}_return_to"] in a custom registration controller like this:
class Users::RegistrationsController < Devise::RegistrationsController
def create
session["#{resource_name}_return_to"] = some_custom_path
super
end
end
You can also create a root route for your user object in routes.rb which will redirect all users whenever they log in:
match "user_root" => "users#home"
Finally you can define the after_sign_in_path_for(resource_or_scope) method in your application_controller and this will allow you to conditionally redirect users:
def after_sign_in_path_for(resource_or_scope)
if resource_or_scope.is_a?(User)
some_custom_path
else
super
end
end