Defining Admins Rails - ruby-on-rails

How can I define a method between Users and Admins? I am using Omniauth Twitter for my users but there are actions that I want to make sure users can not do if they are not admins. I have bundled the gem Active admin but because I am not using devise, any user can currently access the Admin dashboard.

If it were me, I'd create a role attribute on your User model, and have it default to say "customer" or whatever a default user is, but have the ability to set some user's role to "admin". You should be able to set that using Active Admin's edit page. Than create a custom method on your User model, or maybe create a helper method, whatever you prefer...something like:
def admin?
if self.role == "admin"
true
else
false
end
That way you wrap sensitive info (like info on your dashboard) in a user.admin? if statement.
if user.admin?
..display stuff..
end
Or check out this: http://activeadmin.info/docs/13-authorization-adapter.html

Related

Ruby on Rails - Sorcery override login method

I have a user table with guest column(boolean) to distinguish user's identity.
I don't want user with guest? => true able to login.
Is it possible to override Sorcery's login method?
I want it work like
User.where(guest: false).authenticate(email, password)
Another way I'm thinking is to separate User and GuestUser using polymorphic association.
However, I don't really want to create GuestUser with same columns as User.
Please give me some suggestions.
# find specific user and check guest or not
user = User.find_by_email(email)
if user && user.guest == false
User.authenticate(email, password)
end

Rails Pundit how the policies are worknig?

I have a web application in ruby on rails with devise as the authentication and pundit as the authorization.
I have a model user with an integer role attribute with values 0, 1, 2, for visitor, vip, and admin respectively. I also have a scaffold, say Page that I want just vip and admin to have access to and not visitor users.
In page_policy.rb I have
def index?
current_user.vip? or current_user.admin?
end
and in pages_controller.rb I have a line authorize current_user.
Although I have given access to vip but it is available just for admin user. Where have I been wrong with the code?
Thank you
I assume you have properly set up your predicate methods vip? and admin? on the User model, and these work as expected? Can you check the result of calling each of these methods on your current user?
Pundit actually passes the result of current_user to your policy initializer, and you can access that via the user method inside your policy methods. Also I would be careful of using the or operator in this context (see http://www.virtuouscode.com/2010/08/02/using-and-and-or-in-ruby/).
So I would try:
def index?
user.vip? || user.admin?
end
Also, pundit expects you to pass the resource you are checking to the authorize method, not the user object. If you don't have an instance to pass, you can pass the class:
authorize Page

Rails 4 - secure way to give some users admin privileges?

I have a Rails app where I want some users to be super users with special privileges, like being able to access menus where they can edit content of the site. I'm not 100% sure that my implementation is secure, or the Rails way. It looks like this:
I have created an environment variable using the Figaro gem where I store the email-address of the original site creator:
ENV["site_manager_email"]
As I understand it, Figaro's application.yml works like Rails secrets.yml. My user model have a site_manager BOOLEAN attribute. The original site manager should be able to add other site managers by setting this property to true. In my user model I have a method to check whether users are site managers or not, it looks like this:
def is_site_manager?
self.email.eql?(ENV["site_manager_email"]) || self.site_manager == true
end
In my views where I have content that only site managers should be able to see I use the above method like this:
- if current_user.is_site_manager?
SUPER SECRET CONTENT THAT ONLY SITE MANAGERS SHOULD SEE
In my controllers I'm also planning to add a before action filter to only give access to some actions.
So my question is, is this a secure way to do it? If not, what should I change?
And, is there a more Rails way to do it? If so, how does it look?
What are you using for authentication? Devise?
For admins you can look into roles-based authorization and CanCan:
https://github.com/ryanb/cancan
There is a RailsCast that will show how to set it up:
http://railscasts.com/episodes/192-authorization-with-cancan
Once you install it and add a .role column to your Users you can create Ability.rb in your app/models that will look like something like this:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.role? :administrator
can :manage, :all
else
can :read, :all
can :create, Product
end
end
end

Using CanCan with a static roles list

I’m looking to set up simple role based access on my rails app without using a database, we use CAS to handle the authentication so can capture the username from the CAS variables.
My thought was to map usernames to specific roles in a hash (in application.rb, see below for an idea)) and then use that role to determine if the content is viewable.
ROLES = {
'admin' => [ 'username1', 'username2'],
'standard_user' => ['username3']
}
I’ve been advised to look at the CanCan gem but that seems to want to get the role information from a user model which I don’t want to setup, mainly because we intend to pass over role information as another CAS variable in the near future.
So I wondered if anyone has any idea if this plan is do-able and maybe point me in the direction of any code snippets that might help me
Even with this kind of setup, you should be able to use cancan. If you have a user model where you store the username and the ability is revolving around this model, try the following on ability.rb
# user.rb
ROLES = {
admin: %w[username1 username2],
standard_user: %w[username3]
}
# ability.rb
user ||= User.new # username is blank
if User::ROLES[:admin].include?(user.username)
can :manage, :all
elsif User::ROLES[:standard_user].include?(user.username)
cannot :manage, Invoices
else
...
end

User model, attr_accessible and admin

I'm building a simple blog-style application. I really only need admin and non-admin users, so it seems like having a simple column in the user model called admin (boolean) will suffice.
I'm using Devise for authorization right now, and I've got the admin column added. I'm trying to set up my default admin user (myself) in seeds.rb, however admin comes out as false unless I add the admin column to attr_accessible. It seems like this would be a security concern, however, and I don't generally want admin users to be able to be created except by another admin. What's the correct, and safe, way to do this?
You want to handle setting the admin boolean internally. Don't expose it to mass-assignment.
Have your user model automatically default the first user (you) to an admin. Use a before_create method for this...
# models/user.rb
before_create :make_first_user_an_admin
def make_first_user_an_admin
self.admin = self.class.count == 0 # sets true if no users exist, false otherwise
end
Then use an instance method to set adminship...
# models/user.rb
def toggle_admin
self.admin = !self.admin
save
end
guard this method in your controller...
# controllers/users_controller.rb
def change_adminship
if current_user.admin
#user.toggle_admin
else
raise "Can't do that."
end
end
You are very correct to leave admin as not attr_accessible, this just disables setting it via mass-assignment. You can still set admin in your seeds by setting it singularly. Example:
user = User.new(:name => 'joe') ...
user.admin = true
user.save

Resources