Setup Devise to only allow editing of own records? - ruby-on-rails

I've got Devise working in my Rails app but I can't figure out how to now lock it down so a user can only edit their own record in the users table AND in tables belonging to the user.
What am I missing here? Is this done in the controller or the model?

I would create a helper in application_controller for current_user and remove the use of User.find
The simplest way of creating an authorization is with a boolean flag (admin true/false). For other simple solutions are cancan, as mentioned by Yannis or easy_roles KISS is recommend to start with. You may implement the edit action like this
def edit
if current_user.is_admin?
User.find(params[:id])
else
current_user
end
end
application_controller.rb
def current_user
UserSession.find
end
To limit access by the user, like a user having his/hers own tasks, do this.
def index
#tasks = current_user.tasks
end

Devise is an authentication solution. You now need an authorization system. Have a look to Ryan Bates CanCan (github, railscasts).

Related

How to implement a login counter for Ruby on Rails?

So in my ruby on rails project, I want to track how many times a user has logged in. I am using devise for authentication. Right now, I think what I have is sufficient for my current project, I am just having an issue incrementing the login_count column from my db.
Application.rb snippet:
def after_sign_in_path_for(resource)
if current_user.login_count == 0
new_user_profile_path(user_id: current_user.id)
else
root_path
end
User.user_id.increment_counter(:login_count, 1)
end
Right now User.user_id.increment_counter(:login_count,1) gives me undefined method `to_model' for 1:Integer Did you mean? to_yaml.
You’d be much better off providing a custom SessionsController and modifying the create action to perform the actions you require.
Use the devise generator to create controllers for you to work with, if you haven’t already. Then in your sessions_controller.rb add something like this:
def create
super do |resource|
# at this point, resource is your logged in user (or whatever model)
resource.class.increment_counter(:login_count, resource.id)
end
end

single login page in devise gem for two type of user

Using Devise gem :-
in my application i have two type user
1) Company
2) Employee
i have two separate model for both user and i want to give single sign-in page for both user
i already generate different views for both user using devise but then also i need single sign-in.
so how it is possible please help me out...!!!!!!!!!
i try this:-
controllers/compnaies/sessions_controller.rb
def create
#employee = Employee.new
#company = Company.new
if #company.email_exist?(params[:company][:email])
super
elsif #employee.email_exist?(params[:company][:email])
params[:employee]=params[:company]
redirect_to employee_session_path(params)
end
end
employee_session_path is the path of employees's sessions create method but it always call new method of employees's sessions
controllers/employees/sessions_controller.rb
def create
super
end
email_exist? method check the email id in both model which is provided by any of user
in my model:
company.rb
def email_exist?(email)
if Company.find_by(email: email)
return true
end
end
employee.rb
def email_exist?(email)
if Employee.find_by(email: email)
return true
end
end
Thanks in advance...!!!!!!!!
CanCan and Rolify seems to be the combination stack you are looking for to solve your problems here are the link to the github pages:
Rolify https://github.com/RolifyCommunity/rolify
CanCan https://github.com/ryanb/cancan and the Railscast http://railscasts.com/episodes/192-authorization-with-cancan
Let me know if you need any help

Ruby on Rails Role-based Authentication System, how to work with different roles?

I'm using Rails 4.1. I have 3 types of users, Admin, Leader, Worker and each has his own page.
I've chosen a devise+pundit for that role, but cannot get an idea how to send users to different paths. For example, how i can take admin to admin section after sign_in, and a Leader to leader's section, can I restrict entry to some views?
Would any other gems be helpful for this problem?
No idea about a gem. But something like this should work:
class HomeController < ApplicationController
def after_sign_in_path_for(resource)
if current_user.admin?
redirect_to admin_path
elsif current_user.leader?
redirect_to leader_path
else
redirect_to worker_path
end
end
after_sign_in_path_for is a callback in Devise.

Should I have a different admin? method for the view and for the before_filter?

I'm learning Rails and working on DinnerDash.
In application_controller.rb I have:
helper_method :admin?
def admin?
current_user.admin_code == 'secret' if current_user
end
So I could use if admin? in my view files to display certain things only to admins. Now I want to write a before_filter that checks if the current_user is an admin and if not, redirects.
It seems to me that I have to write another method to do this. For view files, I want the method to return false if the user isn't an admin, and for the before_filter, I want it to redirect.
Still, something tells me that this isn't the most efficient way to do this. Since I'm learning Rails, I don't want to develop any bad habits of writing code that isn't DRY. Any ideas on how to best handle this situation?
I would make admin? an instance method of the User model. I think it belongs there because you're actually asking for information about a user object.
Then, for the before_filter, I would do something like this:
before_filter :admin_or_redirect
def admin_or_redirect
redirect_to some_url if !current_user.admin?
end
Then you can still call admin? in your views on #user (which you assign current_user to in your controller), and have a different behavior for your before_filter.
EDIT:
You also want to change your admin? method like this:
class User < ActiveRecord::Base
...
def admin?
self.admin_code == 'secret'
end
end

Ruby on rails passing information from session into db

I have been trying to set up a little twitter app to teach myself ruby on rails, i have a log in page that works and stores the user like this
session[:user_id] = user.id
I can use that in the views, but i am trying to create a relationship based on it so that the tweet, which is created on a new page in in a basic form, is linked to the current session user.
I for some reason can't figure out how to do it.
You can have the current_user (for example) method:
def current_user
#current_user ||= User.find_by_id(session[:user_id])
end
If you already have this, you can create post with:
#post = current_user.posts.create(params[:post])
You should also check, of course, if any user is signed in before creating post, or you'll have NoMethodError.
See devise gem https://github.com/plataformatec/devise
Devise provided current_user and user_session methods in your views and controllers

Resources