How to implement the dynamic authorization with CanCan? - ruby-on-rails-3

i am following this tutorial http://eveloverails.wordpress.com/2011/04/02/183/. I have created the users through devise and i want when the user log in as an admin he should have the list of users in which it can edit the permissions of the users like edit destroy,etc.
Thanks in advance

you can add a field in devise model call role. then create cancan ability class in your model then define your authorization like
class Ability
include CanCan::Ability
def initialize(user)
# Define abilities for the passed in user here. For example:
user ||= Login.new # guest user (not logged in)
if user.role == 'admin'
can :manage, :all
else
can :read, :all
end
end
end
See the wiki for details: https://github.com/ryanb/cancan/wiki/Defining-Abilities

Related

Applying cancan to custom actions

I'm working on a polling app and use Devise and Cancan for authentication and authorization. I have a User model generated by Devise and a Poll model. A poll belongs to a user. My problem is that I have a custom action in my Polls controller and I can't get Cancan to work with that custom action. This is what I tried to do in my code:
config/routes.rb:
match 'users/:user_id/polls' => 'polls#show_user'
Ability.rb:
def initialize(user)
user ||= User.new
if user.is? :admin
can :manage, :all
else # default
can :read, :all
can :manage, Poll, :user_id => user.id
can :show_user, Poll, :user_id => user.id
end # if else admin
end
polls_controller.rb:
class PollsController < ApplicationController
before_filter :authenticate_user!
load_and_authorize_resource :except => :show_user
def show_user
authorize! :show_user, user
#polls = Poll.find_all_by_user_id(params[:user_id])
render "index"
end
<...>
end
The idea is that a user's polls can be viewed only when the owner of the poll is signed in. However, with this code, when a poll's owner is signed in, that user gets kicked out of that page with a message that says authorization failed. If I remove the line authorize! :show_user, user, then a user who's signed in can view all other user's polls (the authorization doesn't work at all).
Can anyone see what I might be missing? Thanks in advance!
In abiltity.rb, you're verb/noun combination is :show_user and Poll, but in your controller you're using :show_user and user--you would need to use a Poll instead.
If, instead you want to allow the user to view all their own Polls, you might go with something like:
ability.rb:
can :show_polls_for, User, :id => user.id
polls_controller.rb:
def show_user
authorize! :show_polls_for, user
...
end

I don't want any specific role.I want to assign permission to any user from GUI by check boxes. So that user can do whatever permissions he have

i just want an application through which i can dynamically assign roles to users through check boxes.
Any answer will be appreciated.
Thanks
There is this gem "cancan" by Ryan Bates.
https://github.com/ryanb/cancan
It integrates nicely with Devise for authentication as well.
Read this 2 - part tutorial.
http://www.tonyamoyal.com/2010/07/28/rails-authentication-with-devise-and-cancan-customizing-devise-controllers/
class Ability
include CanCan::Ability
def initialize(user)
if user.admin?
can :manage, :all
else
user.permissions.each do |permission|
can permission.action_name.to_sym, permission.object_type.constantize # Getting the class name
end
end
end
end
This would now dynamically create permissions for the user. Does this help?

Devise and user profiles

I have set up a test applications and have setup devise to take care of the authentication, additionally I have set up a component where they are sent to a create profile page after registration which works well.
The problem I have is when a logged in user goes to edit they're profile it is easy for then to change the query string and access another users data -
http://localhost:3000/profiles/1/edit
the question i have is how do I lock this down to the current user so that can only edit they're data?
Robbie
I would go for a before_filter.
# in profiles controller
class ProfilesController < ApplicationController
before_filter :find_profile
before_filter :check_if_authorized
def find_profile
#profile = Profile.find(params[:id])
end
def check_if_authorized
render :status => 404 and return unless current_user == #profile.user
end
end
Assumptions:
devise model is named User
user has one profile
you're already checking if a user is logged in
You can use token authentication along with session for more precise and secure authentication.
Add devise :token_authenticatable to the model User
This will create an authentication token into the field authentication_token field of users table every time a user is created.
Then go for a before_filter :verify_auth_token
def verify_auth_token
if current_user.authentication_token == params[:auth_token]
return true
else
return false
end
end
Also the edit request should be http:///profiles/1/edit?auth_token=12wqaasaeaad

CanCan has_many through, specific abilities

I'm currently making a project using devise and cancan.
To understand my problem i have this models :
User with some attributes and is_admin boolean to global access
Role belongs_to project and user with a specific ability for user on each project
Project has_many some others models user can edit or not (depend of it's role on the project)
So my question is how can I do this ?
Actually I have this Ability class :
class Ability
include CanCan::Ability
def initialize(user)
if user
can :read, :all # allow everyone to read everything
if user.is_admin?
can :manage, :all
end
end
end
end
I need to manage role in models depend on my Project model or something else ?
Thank you in advance.
class Ability
include CanCan::Ability
def initialize(user)
if user
can :read, :all # allow everyone to read everything
if user.is_admin?
can :manage, :all
end
can manage, Project do |project|
project.users.include? user
#projects.users return the list of the users in the the role table.
end
end
end
end
You can customize it but I think it's the good way to start.
Here's a cleaner way to organize your Ability.rb.
def initialize(user)
user ||= User.new # Set user to blank User.new if user isn't logged in.
# Everyone, including guests, can read everything
can :read, :all
# Will only let user manage if #project.admin_id == user.id
can :manage, Project, admin_id: user.id
end

Howto redirect users based on their roles in rails 3?

I am trying to figure out how to redirect users on certain URL based on their role, after they log to the Ruby/Rails3 application.
So far, I have used authlogic gem for authentification and cancan gem for role setting.
Roles are just like this (defined in app/models/user.rb):
class User < ActiveRecord::Base
acts_as_authentic
ROLES = %w[admin customer demo]
end
Now there is app/controllers/user_session_controller.rb which is taking care of logins.
I would like to make something like this:
for r in User.role
if r == "admin"
redirect_to admins_url
else
redirect_to users_url
end
end
This is not working because of the following error:
"undefined method `role' for #<Class:0xb5bb6e88>"
Is there a simple or elegant way how to redirect users to the certain URLs according to their roles?
(Roles are defined in mysql column 'role' in the users table.)
The for r in User.role is confusing. Are you trying to access the array of ROLES defined on the class or are you trying to access the role value of the current user?
If you are trying to access the array of ROLES, then use User::ROLES.
Using authlogic, one typically defines the current_user in the application_controller. So the role of the current user can be found using current_user.role
So your code could look something like
if current_user.role == "admin"
redirect_to admins_url
else
redirect_to users_url
end
You should definitely check out CanCan. It is a pretty logical way to manage user roles and abilities.