I'm using cancancan.. and it works fine on development env .. but once i got it on the production the site works like if there's no gem installed at all.. no authorization handled.
I can't figure out what is wrong
--------------------edited
in the application controller there's
before_filter :authenticate_user!, if: :devise_controller?
rescue_from CanCan::AccessDenied do |exception|
# Make sure we don't redirect to an HTML page
# in API requests because this is absolutely a bad idea
unless request.accept == 'application/json'
flash[:error] = "Access denied."
redirect_to root_url
end
end
and in the ability file
def initialize(user)
# Define abilities for the passed in user here. For example:
#
user ||= User.new # guest user (not logged in)
if user.admin?
can :manage, :all
else
can :index, Book
can :index, Category
end
end
Related
I am not beeing able to make this work.
I have a project with activeadmin 0.4.4 and devise working, and I need to include role-based permissions to it, so I thought on CanCan. The roles could be 'administrator' or 'publisher', administrator can manage all and publisher only a post section.
I followed https://github.com/gregbell/active_admin/wiki/How-to-work-with-cancan-with-activeadmin, the AdminUser crud it is working fine, and the config.authentication_method = :authenticate_admin_user! was alredy uncomment.
In my ApplicationController I added the following:
# https://github.com/ryanb/cancan/wiki/exception-handling
rescue_from CanCan::AccessDenied do |exception|
respond_to do |format|
format.html do
redirect_to admin_root_path, :alert => exception.message
end
end
end
# https://github.com/ryanb/cancan/wiki/changing-defaults
def current_ability
#current_ability ||= Ability.new(current_admin_user)
end
And here is my Ability class:
class Ability
include CanCan::Ability
def initialize(user)
user ||= AdminUser.new
if user.role?('administrator')
can :manage, :all
else
can :read, :all
end
end
end
The Ability initialize method is not executing. I tried abort, -as the comments suggest- puts or p, and even sintax error and I have nothing. What am I mising?
I'm stuck here, I also tried http://www.activeadmin.info/docs/13-authorization-adapter.html#using_the_cancan_adapter but it is rising undefined method "authorization adapter", I am not sure if this is working with my activeadmin version. And adding a require active_admin/cancan_adapter rise a LoadError.
Thanks.
Finally I did the trick thanks to http://makandracards.com/jan0sch/13877-rails-activeadmin-and-cancan
Basically I need to add a controller block in the activeadmin register page for loading it:
ActiveAdmin.register Whatever do
#...
controller do
load_and_authorize_resource :except => :index
def scoped_collection
end_of_association_chain.accessible_by(current_ability)
end
end
#...
end
I am new in Ruby on Rails and i am using Ruby version 1.9.3 and Rails version 4.0.2.
My Query is:-
How to create `authenticate_user' method without devise in Ruby on Rails.
Below my routes
get "admin/users/sign_in" => "admin/users#sign_in"
Below My Application Controller:-
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
rescue_from CanCan::AccessDenied do |exception|
flash[:alert] = "Access denied. You are not authorized to access the requested page."
redirect_to root_path and return
end
helper_method :current_user
before_filter :authenticate_user, :current_user
def current_user
# Note: we want to use "find_by_id" because it's OK to return a nil.
# If we were to use User.find, it would throw an exception if the user can't be found.
#current_user ||= User.find_by_id(session[:user_id]) if session[:user_id]
#current_user ||= User.find_by_authentication_token(cookies[:auth_token]) if cookies[:auth_token] && #current_user.nil?
#current_user
end
def authenticate_user
if #current_user.nil?
flash[:error] = 'You must be signed in to view that page.'
redirect_to :admin_users_sign_in
end
end
protected
#derive the model name from the controller. egs UsersController will return User
def self.permission
return name = self.name.gsub('Controller','').singularize.split('::').last.constantize.name rescue nil
end
def current_ability
#current_ability ||= Ability.new(current_user)
end
#load the permissions for the current user so that UI can be manipulated
def load_permissions
#current_permissions = current_user.role.permissions.collect{|i| [i.subject_class, i.action]}
end
end
Below code using my controller
before_filter :authenticate_user!
My authenticate_user method not redirect properly
redirect_to :admin_users_sign_in
admin_users_sign_in path define in routes see on top
Above the code every time say on browser "The page isn't redirecting properly"
Please help
I suspect the problem is due to this line:
redirect_to :admin_users_sign_in
You need to pass either an action & controller or a friendly name of the path to redirect_to.
Change your routes to be something like
get "admin/users/sign_in" => "admin/users#sign_in", :as => :admin_user_signin
Then you can do something like
redirect_to admin_user_signin_path
This looks an infinite loop.
You defined authenticate_user at ApplicationController level. So, when a visitor visited page 'foo', he is denied by this method because current_user is nil. Then he got redirected to admin sign in page, but that page has this before_filter as well, so he got redirected again, to the same page and never end.
To fix, move such filter to specific controllers which need protection. And do not set it in sign in/sign up page.
Side notes:
You've already used CanCan which has authorization on "read" as well. There is no point to use authenticate_user again for same functionality.
I am new in Ruby on Rails and i am using Ruby Version 1.9.3 and Rails version 4.0.2.
My query is:
How to get controller and his action name with router prefix in application controller?
See Below my code:-
See Router
root :to=>"home#index"
get "admin/" => "admin/users#index"
get "admin/sign_in" => "admin/users#sign_in"
get "sign_in" => "admin/users#sign_in"
See my application controlle
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
helper_method :current_user
rescue_from CanCan::AccessDenied do |exception|
flash[:alert] = "Access denied. You are not authorized to access the requested page."
redirect_to root_path and return
end
before_filter :current_user, :get_model
def current_user
# Note: we want to use "find_by_id" because it's OK to return a nil.
# If we were to use User.find, it would throw an exception if the user can't be found.
#current_user ||= User.find_by_id(session[:user_id]) if session[:user_id]
#current_user ||= User.find_by_authentication_token(cookies[:auth_token]) if cookies[:auth_token] && #current_user.nil?
#current_user
end
def authenticate_user
#mydata = params
if current_user.nil?
flash[:error] = 'You must be signed in to view that page.'
redirect_to :admin_sign_in
end
end
end
def authenticate_user method i have create in application controller.
I want
if current_user.nil? and router prefix is admin Like localhost:3000/admin
it will be redirect on admin sign in path
redirect_to :admin_sign_in
Other then it will be redirect front end sign in part
redirect_to :sign_in
Update my question
My query is how to set condition according to controller and action name with namespace in authenticate_user method where redirect to page.
Please help. How it is possible?
Use namespaces in your routes.
http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing
especially chapter 2.6
2.6 Controller Namespaces and Routing
You may wish to organize groups of controllers under a namespace. Most commonly, you might group a number of administrative controllers under an Admin:: namespace. You would place these controllers under the app/controllers/admin directory, and you can group them together in your router:
namespace :admin do
resources :posts, :comments
end
Also call admin_sign_in_path or sign_in_path instead of symbols. to see all routes in you app use rake routes .
I'm new to ruby and Rails. I'm Using Devise and CanCan along with Rails_Admin in my app.
I'm trying to do -> If a user is already logged in, and it's an admin, redirect to rails_admin_path if it's not an admin but just a user then redirect to 'upload_path', if it's not logged in then redirect to sign_in path, however probably due to my lack of knoledge, I'm creating an infinite redirect loop. Even if I try to access sign_in without the "require_login" filter.
Here's what I've done so far:
application_controller.rb
class ApplicationController < ActionController::Base
before_filter :require_login
protect_from_forgery
#IDEA 1
#def require_login
# if current_user.role? == 'Administrator'
# redirect_to rails_admin_path
# elsif current_user.role? == (('C1' or 'D1') or ('M1' or 'M2'))
# redirect_to upload_path
# end
# end
#I saw this somewhere and It doesn't work either
def require_login
redirect_to new_user_session_path, alert: "You must be logged in to perform this action" if current_user.nil?
end
rescue_from CanCan::AccessDenied do |e|
redirect_to new_user_session_path, alert: e.message
end
end
routes.rb
Siteconfigurationlistgenerator::Application.routes.draw do
mount RailsAdmin::Engine => '/admin', :as => 'rails_admin'
devise_for :users
# The priority is based upon order of creation:
# first created -> highest priority.
match 'upload' => 'upload_file#new'
.
.
.
ability.rb
class Ability
include CanCan::Ability
def initialize(user)
#Define abilities for the passed in user here.
user ||= User.new #guest user (not logged in)
#a signed-in user can do everything
if user.role == 'Administrator'
#an admin can do everything
can :manage, :all
can :access, :rails_admin # grant access to rails_admin
can :dashboard # grant access to the dashboard
elsif user.role == (('C1' or 'M1') or ('D1' or 'M1'))
# can :manage, [ProductList, Inventory]
# can :read, SiteConfigurationList
# end
end
end
When I run rake routes, I get the routes for Devise and the Rails_admin routes, plus the "upload" route.
I've really tried to fix this stupid error but honestly I ran out of ideas. I'd appreciate any help you're able to provide me. Thank you in advance.
The problem is that you have a before_filter that requires a user to sign in, in your ApplicationController. Basically you are asking your users to sign in before accessing the sign in page.
You can solve this by using devise's built-in method :authenticate_user :
before_filter :authenticate_user!
Or you can specify that your before_filter doesn't run on an action from the DeviseController.
before_filter :require_login, :unless => :devise_controller?
I've been working through Michael Hartl's Rails tutorial (which is unbelievably awesome by the way).
Anyway, everything has been going pretty well and I've nearly reached the end of chapter 10. The problem is that my rspec tests have started to generate some failures and I can't figure out what's wrong.
The first failure occurred when I was working through the section on destroying users. The test
before :each do
#user = Factory :user
end
describe "as a non-signed-in user" do
it "should deny access" do
delete :destroy, :id => #user
response.should redirect_to(signin_path)
end
end
gives the error:
UsersController DELETE 'destroy' as a non-signed-in user should deny access
Failure/Error: delete :destroy, :id => #user
NoMethodError:
undefined method `admin?' for nil:NilClass
# ./app/controllers/users_controller.rb:76:in `admin_user'
# ./spec/controllers/users_controller_spec.rb:308:in `block (4 levels) in <top (required)>'
Here's the code the message references in users_controller:
def admin_user
# the error tels me that current_user = NilClass
redirect_to(root_path) unless current_user.admin?
end
So I guess this would suggest that current_user isn't working correctly and is being set to nil. Now current_user involves a lot of methods of the SessionsHelper which (afaik) deal with setting the users ID in secure cookies and referencing the cookie as they move around the site. So this suggests that there is something wrong with the cookies.
I've checked the browser and the cookie is being set, I've also gone over every part of the code and it all replicates the tutorial exactly as far as I can tell.
Is there something else I should be looking at?
Appendix
Here is the contents of the SessionsHelper module:
module SessionsHelper
def sign_in user
# rails represents cookies as a hash and deals with the conversion for us
# making the cookie "signed" makes it impervious to attack
cookies.permanent.signed[:remember_token] = [user.id, user.salt]
# this line calls the assignment operator below
self.current_user = user
end
def current_user=(user)
#current_user = user
end
# this is a getter method
def current_user
# this sets #current_user = to the user corresponding to the remember token
# but only if #current user is undefined. ie it only works once
#current_user ||= user_from_remember_token
end
def signed_in?
# return true if current_user is not nil
!current_user.nil?
end
def sign_out
cookies.delete(:remember_token)
self.current_user = nil
end
def current_user? user
# returns true if the user object == the current_user object
user == current_user
end
def authenticate
deny_access unless signed_in?
end
def deny_access
store_location
# this is a shortcut for flash notices: flash[:notice] = "Please sign in to access this page."
redirect_to signin_path, :notice => "Please sign in to access this page."
end
def redirect_back_or(default)
redirect_to(session[:return_to] || default)
clear_return_to
end
private
def user_from_remember_token
# the * allows us to give a 2 element array to a method expecting 2 seperate arguments
User.authenticate_with_salt(*remember_token)
end
def remember_token
# return [nil, nil] if the :remember_token cookie is nil
cookies.signed[:remember_token] || [nil, nil]
end
def store_location
# stores the url the browser was requesting
session[:return_to] = request.fullpath
end
def clear_return_to
session[:return_to] = nil
end
end
In your spec ypu are trying to delete user, while you are not logged in, so current_user is nil. You should prevent access to this action non singed in user.
class UsersController < ApplicationController
before_filter :authenticate, :only => [:index, :edit, :update, :destroy]
....
Just as it is described in example.
I made the same omission and this fixed worked. Thanks. I agree with ducky, Michael Hartl's Rails tutorial is tremendously awesome. It's almost a shame to +just+ call it a "Rails Tutorial." While the tutorial does indeed seem to be pointing me towards good Rails development habits, the text concisely contains much more. Very well done.