accessing user edit pages when you are admin - ruby-on-rails

currently, my edit action in my users controller is like so:
def edit
#user = User.find(params[:id])
end
This works if I want to access my own user profile. However, if I want to access someone else's user profile, this wouldn't work. How should I change this?

Add a before action check_right_user which checks whether the current user is trying to access his own profile.
before_action :check_admin, only: [:edit, :update, :destroy]
def check_admin
unless current_user.admin?
redirect_to root_path, alert: "You're not authorized"
end
end
I assume you have a current_user method defined in your application_controller or users_controller and an admin field in your user model.

Related

Rails: Current user should only be able to view their own users#show page (Devise)?

Is there a way to allow a user to only view their own profile page (users#show)? So when someone with an id of say 1 tries to go to the www.myapp.com/users/412 url, he will be re-directed to the root page? He can only access www.myapp.com/users/1.
I am using devise and this is what I've tried. However with this code strangely enough, the current user cannot access his own page.
users_controller.rb
class UsersController < ApplicationController
before_action :authenticate_user!
before_action :only_see_own_page, only: [:show]
def show
#some ruby code here
end
private
def only_see_own_page
if current_user.id != params[:id]
redirect_to root_path, notice: "Sorry, but you are only allowed to view your own profile page."
end
end
end
**routes.rb*
resources :users, only: [:show]
Argh, it was that easy... This is what worked for me:
def only_see_own_page
#user = User.find(params[:id])
if current_user != #user
redirect_to root_path, notice: "Sorry, but you are only allowed to view your own profile page."
end
end

railstutorial chapter 9 limit user access

i followed the tutorial in railstutorial.org. I noticed that if i use the url
localhost:3000/users/102
logged in or out, i can view the profile. If i change the 102 to another existing user i can also view it. How can i limit the access to this page? I want that only the current user can be able to view his/her profile.
I am new at rails.
i know its got to do something with users_controller.erb in the code
def show
#user = User.find(params[:id])
end
This does depend on how you define your current_user helper. For instance, if you were using Devise for authentication, it would be if current_user == #user, but I believe for the helper on that tutorial, the method below should work.
def show
#user = User.find(params[:id])
if current_user?(#user)
# show page
else
# render error page?
flash[:error] = "Nope" # Clearly here you can do whatever you want, from error pages to redirections
redirect_to root_path
end
end
seems like the right solution would be to add another function
at the top it would be
before_action :correct_user, only: [:edit, :update]
before_action :correct_user_return, only: [:show]
and then in the private section it would be
def correct_user_return
#user = User.find(params[:id])
redirect_to current_user unless current_user?(#user)
end

"Could not find User without ID" ActiveRecord Error and editing trouble

So I am having some trouble with my rails app and I think I went a little out of my own depth. I am creating a simple alumni application and I want users to be able to join organizations. For some reason in my new join page I get the error "Couldn't find User without an ID". I want to know why the ID isn't passing in, which would imply signed_in? = false. I don't know why everything worked find when I created other additions to my users controller but here it refuses to take on the logged in user id. I feel like I am missing something simple, let me know if updates are necessary!
Here is the relevant information in my Users controller:
class UsersController < ApplicationController
before_action :signed_in_user, only: [:edit, :update, :index, :show, :join]
before_action :correct_user, only: [:edit, :update, :join]
before_action :admin_user, only: :destroy
def join
end
def show
#user = User.find(params[:id])
#organization = #user.organization
end
def create
#user = User.new(user_params)
if #user.save
sign_in #user
flash[:success] = "Welcome to the Sample App!"
redirect_to #user
else
render 'new'
end
end
...
private
def user_params
params.require(:user).permit(:name,:email, :password, :password_confirmation,:organization_id)
end
def signed_in_user
unless signed_in?
store_location
redirect_to signin_url, notice: "Please sign in."
end
end
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user)
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
I included the def create method because I tried editing it to redirect users to the join page right after login but then I came across this error and I thought that was the problem so i switched it back. I guess it wasnt.... NOTE: I am basing a lot of this app off of the Hartl tutorial if that is helpful.
You should have a Memberships controller and model with a belongs_to :user (has_many :memberships for User & Organization), instead of defining a join method in the Users controller. The controller should be responsible for adding/deleting organization user-memberships. From that controller you fetch the user info by #user = User.find(:id) and don't forget to properly set the route file for nested resources.
resources :users do
resources :memberships
end
Also note that your join method doesn't create any instance variables for the view (#user). It looks like it properly goes through the signed_in_user action but nothing is instantiated in the join method.
Change line 3 to:
before_action :correct_user, only: [:edit, :update]
If the purpose of "join" is to create a user, then there should not be a user yet. However if your purpose for "join" is to get the current user you should add this to your join method:
#user = current_user
What about if you changed it to this:
def show
#users = User.all
#user = #users.find(params[:id])
#organization = #user.organization
end

before_action logs out user post update (using devise)

I'm trying to restrict access to the user edit page so that logged in user can only edit his/her own profile. FYI, I'm using Devise for user authentication, login, register, etc. This is supposed to be pretty easy to do with
class UsersController < ApplicationController
before_action :find_user, only: [:edit, :update]
before_action :correct_user, only: [:edit, :update]
def edit
end
def update
if #user.update_attributes(user_params)
flash[:success] = 'Profile Updated!'
redirect_to edit_user_path(#user)
else
render 'edit'
end
end
private
def user_params
# code left out... but pretty self explanatory right?
end
def find_user
#user = User.find(params[:id])
end
def correct_user
redirect_to(root_url) unless current_user == find_user
end
end
The weird thing is, when I have the before_action :correct_user, when the user updates... it logs the user out post-update! When I don't have the before_action :correct_user, it leaves the user logged in and redirects to edit page of the user. I tried manually signing the user in def update prior to redirecting to edit page, but it does not work. In fact, that isn't even the issue. When I compare the current_user and User.find(params[:id]), the current_user is logged in! But for some reason, having the before_action :correct_user there logs me out!
I've been banging my head on the wall for quite some time on this one. Can anyone help out? This is a Rails 4 app and am using the latest version of devise.
Thank you!
I'm not sure you really need the find_user method here.
class UsersController < ApplicationController
respond_to :html
def update
current_user.update_attributes user_params
respond_with current_user, location: [:edit, current_user]
end
private
def user_params
...
end
end
Seeing as you only let a user edit their own record, you can just use current_user in the update method.
Also, if you are happy to use the standard Rails convention for CRUD operations, then respond_to/with will save you a little time and code by implementing that for you. I used the location option otherwise respond_with defaults to the show page of the resource.

Need help with custom authentication

Hey guys I created some custom authentication thanks to railscasts.com but I'm somewhat stuck as I need to restrict my users from editing other users' profiles.
Here's my authenticate_user and current_user methods:
private
def current_user
#current_user ||= User.find_by_auth_token!(cookies[:auth_token]) if cookies[:auth_token]
end
def authenticate_user!
if current_user.nil?
redirect_to login_url, :alert => "You must first log in to access this page"
end
end
Here's the before_filter in my UsersController:
before_filter :authenticate_user!, :only => [:edit, :update, :destroy]`
EDIT: Fixed it thanks to alock27.
I had to edit my users_controller and modify the edit action as follows:
#user = User.find(params[:id]
redirect_to root_url unless current_user == #user
I think you want this:
Adding security on routes in Rails
you need to find the User by :id and check if current_user = #user
You don't have to provide an id for edit, update and destroy: you already have current_user.
Instead of editing #user = User.find(id), edit current_user. Thus, your authentication functions ensure the user will only edit its own profile.

Resources