I have a problem with my users-controller. Currently, an admin user can delete itself, other users can not delete themselves. In addition, each user can edit themselves.
However, I would like an admin user to delete and edit itself and others. How i've to edit the users-conroller?
users controller:
class UsersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update, :destroy,
:following, :followers]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def edit
#user = User.find(params[:id])
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "Nutzer gelöscht"
redirect_to users_url
end
private
def user_params
params.require(:user).permit(:name, :capacity, :resource_id, :email, :password,
:password_confirmation)
end
# Before filters
# Confirms the correct user.
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user)
end
# Confirms an admin user.
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
thank for the help! :)
Best regard,
Phillip
Currently, before_action :correct_user, only: [:edit, :update] prevents admin from entering edit page. Modify correct_user method to change this behaviour:
# Confirms the correct user.
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user) || current_user.admin?
end
Related
I'm working on review applications. In this app, users can post their own project and other users review to it. But I faced this error when other users try to edit their own reviews. To edit a project is only allowed to project owners. But to edit reviews should be allowed to users who wrote its review.
How can I divide this authentication?
/controllers/projects_controller.rb
class ProjectsController < ApplicationController
before_action :signed_in_user, only: [:new, :create, :edit, :update, :destroy]
before_action :set_project, only: [:show, :edit, :update]
before_action :correct_user, only: [:edit, :update]
def edit
end
def update
#project.attributes = create_params
if #project.save
redirect_to #project
else
render edit_project_path(id: #project.id)
end
end
private
def signed_in_user
unless user_signed_in?
redirect_to root_path
end
end
def set_project
#project = Project.find_by_id(params[:id])
end
def correct_user
unless current_user.projects.include?(#user)
redirect_to root_path
end
end
end
/controllers/reviews_controller.rb
class ReviewsController < ApplicationController
before_action :set_projectct, only: [:new, :create, :edit, :update]
before_action :set_review, only: [:edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
def edit
end
def update
#review.attributes = create_params
if #reviews.save
redirect_to prokect_path(id: #review.project_id)
else
redirect_to project_path(id: #review.project_id)
end
end
def set_project
#project = Project.find_by_id(params[:project_id])
end
def set_review
#review = Review.find_by_id(params[:id])
end
def correct_user
unless current_user.review.include?(#review)
redirect_to root_path
end
end
end
routes.rb
resources :projects do
resources :reviews
end
If you want to verify that the user has written the review, why not compare like this:
#review.user == current_user
By the way, this is an authorization verification, so if the user does not have the right to edit the review, you should return a 403 (Forbidden) instead of a redirect.
Gems like pundit or cancancan may help you doing that properly
I want to have correct users, admins, and editors be able to edit, update, and delete a blog.
I have this in my Blogs controller:
before_action :require_user, only: [:new, :create, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update, :destroy, :can_edit_blog?]
and this in under private:
def can_edit_blog?
true if ((current_user.admin? || current_user.editor?) || correct_user)
end
def correct_user
#blog = current_user.blogs.find_by(id: params[:id])
redirect_to root_url if #blog.nil?
end
Right now it only allows the correct user, but not the admin or editors. I've tried using another before_action :admin_user, but that didn't seem to work.
before_action :require_creator, only: [:edit, :update, :destroy]
...
def can_edit_blog?
current_user.admin? || current_user.editor?
end
def require_creator
#blog = Blog.find(params[:id])
redirect_to root_url unless (current_user == #blog.user || can_edit_blog?)
end
I have an app that has some similar logic. Here is what my controller code would look like. Some of the private methods can be abstracted to the ApplicationController.
before_action :require_user, only: [:new, :create, :edit, :update, :destroy]
before_action :require_creator, only: [:edit, :update, :destroy]
private
def require_user
access_denied unless logged_in?
end
def logged_in?
!!current_user
end
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
def access_denied
redirect_to root_path
end
def require_creator
access_denied unless logged_in? and (current_user == #blog.user || current_user.admin?)
end
You don't want to call can_edit_blog in the :only option of the before_action calling correct_user. You want to call can_edit_blog? in correct_user:
before_action :correct_user?, only: [:edit, :update, :delete]
...
private
def can_edit_blog?
current_user.admin? || current_user.editor?
end
def correct_user
#blog = current_user.blogs.find_by(id: params[:id])
if #blog.nil? or not can_edit_blog?
redirect_to root_url
end
end
OP's solution is correct, mine is not, refer to their updated question
now only current_user can edit his own account, but only admin can delete account. Don't know how to give permission to admin to edit users because current_user function is blocking it.
users_controller.rb
class UsersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: [:index, :destroy]
...
private
...
# Confirms the correct user.
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user)
end
# Confirms an admin user.
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
you can add check for admin.
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless (current_user?(#user) || current_user.admin?)
end
Could you not define a new method that returns true for correct user or admin?
# Confirms an admin or user.
def admin_or_correct_user
unless current_user.admin? || current_user?(#user)
redirect_to(root_url)
end
end
I want the user who created post and admin to delete but it's throwing me an 'undefined error'. I want to know why it's throwing me an undefined method error.
Here's my code from the controller:
Before actions:
before_action :set_recipe, only: [:edit, :update, :show, :like]
before_action :require_user, except: [:show, :index, :like]
before_action :require_user_like, only: [:like]
before_action :require_same_user, only: [:edit, :update]
before_action :admin_or_authorship, only: :destroy
Destroy method:
def destroy
Recipe.find(params[:id]).destroy
flash[:danger] = "Deleted"
redirect_to stories_path
end
private
def recipe_params
params.require(:recipe).permit(:name, :summary, :description)
end
def set_recipe
#recipe = Recipe.find(params[:id])
end
def require_same_user
if current_user != #recipe.user and !current_user.admin?
flash[:danger] = "You can only edit your own recipes"
redirect_to stories_path
end
end
def require_user_like
if !logged_in?
flash[:danger] = "log in to like!"
redirect_to :back
end
end
def admin_or_authorship
redirect_to stories_path unless administrator? || authorship?
end
def administrator?
current_user.admin?
end
def authorship?
#recipe.user == current_user
end
The problem is that in your before_filter admin_or_authorship, which is further calling authorship?, is saying #recipe.user .... Here #recipe is not defined so is nil by default.
You need to call before_filter set_recipe for destroy too:
before_action :set_recipe, only: [:edit, :update, :show, :like, :destroy]
Your action will become:
def destroy
#recipe.destroy
flash[:danger] = "Deleted"
redirect_to stories_path
end
I want to allow either the correct user or the admin user to delete a model. How do I set this up?
Controller
before_filter :correct_user, only: [:edit, :update, :destroy]
before_filter :admin_user, only: :destroy
...
private
def signed_in_user
unless signed_in?
store_location
redirect_to signin_path, notice: "Please sign in."
end
end
def correct_user
if (Event.find(params[:id]).user_id != current_user.id)
redirect_to events_path, :notice => "You do not own this event"
end
end
def admin_user
redirect_to(root_path) unless current_user.admin?
end
Currently the user needs to be both the admin and owner of the model. I would like to have an either or permission arrangement.