ActiveAdmin Redirect if not an admin - ruby-on-rails

I would like to create a simple redirect for admin:false Users who are willing to go to /admin pages. I am using ActiveAdmin and a single User model with a admin:bool flag. I tried the following:
in my AA init file
config.authentication_method = :authenticate_admin_user!
in my App controller
def authenticate_admin_user!
redirect_to root_path unless current_user.try(:is_admin?)
end
And nothing happens.
I also tried creating a custom method like this in a new ActiveAdmin::AuthorizationAdapter but could not figure out how to use it
def authorized?(action, subject = nil)
user.admin?
end

Try this. In my case active admin provide current_admin_user not current_user
def authenticate_admin_user!
redirect_to root_path unless current_admin_user.try(:is_admin?)
end

Related

How can I prevent user access?

I have a view that to access you must log in ,my users table I have a field called kind.
I am using gem devise
enum kind: {
admin: 0,
customer: 1
}
add this in application_controller
def user_can_access(resource)
if current_user
if resource.is_admin?
root_path
else
sign_out current_user
new_user_session_path
end
end
end
user.rb
def is_admin?
self.admin?
end
That is my attempt to solve it, but it is wrong since I want the user that I do not want to access the view to not login.
In my method, the user who does not have access logs in but then I log him out, which I think is wrong
How can I prevent client access?
note:I will only have a page for the administrator, the other users will not have a view to access.
You can check the cancancan gem for authorization features or you can write yours then include a before action to check if the current_user is authorized before rendering the view.
e.g
class MyPage < ApplicationController
before_action :is_authorized?
def show_my_page
#foo == bar
end
private
def is_authorized?
return true if current_user.kind == admin
redirect_to root_path, notice: "You are not allowed to access this page"
end
end

sRails 5 Devise after_sign_in_path

I have a Rails 5 app with Devise. Each user has a role_id where they are assigned a role upon creation. I'm trying to use the after_sign_in_path_for method that Devise gives to redirect to a specific page on login based on the role.
Below is what I have so far, but it doesn't work when trying to sign out a disabled user.
class ApplicationController < ActionController::Base
def after_sign_in_path_for(resource)
case resource.role_id
when Role.find_by(name: "admin").id
root_path
when Role.find_by(name: "disabled").id
destroy_user_session_path
else
super
end
end
end
I'm able to sign in when I'm an admin user and it redirects. But if I try to sign in as a user whose role is disabled, it tries to tear down the session then raises an exception of No route matches [GET] "/users/sign_out". I know the method destroy_user_session_path expects a delete method but how can I pass this in the application controller?
What am I doing wrong here?
Update
I tried the sign_out(resource) as suggested in the first answer, and it raises an exception undefined methodto_model' for true:TrueClassin mymy_sessions_controller.rb` which I use to override the create method to set a login token and limit concurrent sessions. Here is the controller.
class MySessionsController < Devise::SessionsController
skip_before_action :check_concurrent_session
def create
super
set_login_token
end
private
def set_login_token
token = Devise.friendly_token
session[:token] = token
current_user.login_token = token
current_user.save(validate: false)
end
end
You can check roles inside MySessionsController#create and prevent logging if the role not valid instead of allowing user to login then logout
def create
unless current_user.role_id == Role.find_by(name: "disabled").id
super set_login_token
else
redirect_to new_user_session_path, alert: "You can't log in"
end
end
You can also use active_for_authentication? and inactive_message methods in user model to prevent him from login. in /app/models/user.rb:
def active_for_authentication?
super and self.role_id != Role.find_by(name: "disabled").id
end
def inactive_message
"You can't log in"
end
destroy_user_session_path is making [GET] "/users/sign_out" request.
You can use sign_out or reset_session function to delete session directly.
Hope this answer works for you.
Use devise's sign_out(resource) method instead of destroy_user_session_path. This method will destroy the user session.

Rails Devise - Different redirect paths on signup

I'm using devise for users but I have two types of users (customers and suppliers), and need different redirect routes based on which path they follow. EG: If a customer signs (/signup) up it will redirect them to their dashboard. If a supplier signs up(/suppliers/registrations/user), it needs to direct them to the next form where they start describing their business(/suppliers/registrations/business). How do you manage this?
UPDATE
I've update my devise registrations controller to include the following (I've excluded all of the commented out stuff)
users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
if resource.supplier == true
redirect_to supplier_business_path
elsif resource.supplier == false
redirect_to user_projects_path(current_user)
end
end
end
But it keeps taking me to the root regardless.
after_sign_in_path_for should just return the path but not perform a redirect, try changing your method like this:
protected
def after_sign_up_path_for(resource)
if resource.supplier == true
# also add specific url = '/suppliers/registrations/user'
supplier_business_path
elsif resource.supplier == false
user_projects_path(current_user)
end
end
also refer this link:
https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-on-successful-sign-up-(registration)
Use devise after_sign_in_path_for method in aplication controller. For eg
def after_sign_in_path_for(resource)
if resource.role == "customer"
redirect_to customer_dashboard_path
elsif resource.role == "supplier"
redirect_to supplier_dashboard_path
end
end

How can I make specific user(not current_user) sign out on rails-devise website?

I want to know how I can make specific user(not current_user) sign out.
I saw this http://www.rubydoc.info/github/plataformatec/devise/master/Devise/Controllers/SignInOut#sign_out-instance_method and maked this code.
def kick_admin
user = User.find params[:user_id]
user.admin = false
user.save
sign_out user #want to kick him.
end
But it does not make that user sign out but make me(current_user) signed out.
What is the right way to use the sign_out method?
I checked this answer(Sign out specific user with Devise in Rails) but it was not helpful.
One way you could do this is create a new attribute in the User table, call it force_sign_out.
def kick_admin
user = User.find params[:user_id]
user.update_attributes(admin: false, force_sign_out: true)
end
And have a before action in ApplicatonController so that if the user attempts any activity he's signed out
class ApplicationController < ActionController::Base
before_action :check_if_force_sign_out
def check_if_force_sign_out
return unless current_user.force_sign_out
current_user.update_attributes(force_sign_out: false) # reset for non-admin log in
sign_out
redirect_to root_path
end
end

Redirect After Sign Up and Sign In with 2 Models (Devise)

I have two models in my application, User and Admin. So, I put these code in my application controller:
def after_sign_in_path_for(user)
root_path
end
def after_sign_in_path_for(admin)
admin_path
end
However, it only executes the last one (admin). So, whenever I signed in as user, I will be redirected to the admin_path instead of root_path as it should be. Any ideas?
Do something like this, in case you have two separate models for User and Admin:
def after_sign_in_path_for(resource)
resource.is_a?(Admin) ? admin_path : root_path
end
Ruby understands that you are redefining after_sign_in_path_for, so the last one defined will take effect.
You can simply modify your code like this to make it work:
def after_sign_in_path_for(user)
user.admin? ? admin_path : root_path
end
Just make sure user.admin? is the function to check whether a user has admin role or not!

Resources