Authlogic Current User Question - hiding admin links
I think I am missing something while using the Auth开发者_如何学运维logic gem w/ Rails. To set the stage I have multiple users and each user can create posts and comments. Upon the display of a post or comment I would like to give the user who created them the option to edit or destroy.
I am successfully using the following code to hide and show elements based on if a user is logged in or not but can't seem to find out how to only show these links to the actual user who created them...not any user that is logged in.
<% if current_user %>
<%= link_to 'Edit', edit_question_path(question) %> |
<%= link_to 'Destroy', question, :confirm => 'Are you sure?', :method => :delete %>
<% else %>
<p>nothing to see here</p>
<% end %>
Here is the def of current_user located in the application controller in case I need to change something here.
class ApplicationController < ActionController::Base
helper :all # include all helpers, all the time
protect_from_forgery # See ActionController::RequestForgeryProtection for details#
helper_method :current_user
private
def current_user_session
return @current_user_session if defined?(@current_user_session)
@current_user_session = UserSession.find
end
def current_user
return @current_user if defined?(@current_user)
@current_user = current_user_session && current_user_session.record
end
end
Authentication solutions like authlogic were not built to support what you're trying to do. There are authorization solutions you can use on top on authlogic that let you do fine-grained checks like whether or not a user may access a given action:
<% if current_user.may_update_question? @question %>
<%= link_to 'Edit', edit_question_path(@question) %>
<% end %>
The example above is uses Aegis.
Try this:
class ApplicationController < ActionController::Base
# add your methods (eg: current_user etc)
helper_method :current_user, :logged_in?, :current_user_is_owner?
def init_data
klass = controller_name.camelize.singularize.constantize #User
param_key = controller_name.camelize.downcase.singularize.to_sym # :user
obj = case (action_name.to_sym)
when :new, :create
klass.new(params[param_key])
when :edit, :show, :destroy
klass.find(params[:id])
when :update
klass.find(params[:id]).tap{|o| o.attributes = params[param_key]}
end
instance_variable_set("@#{param_key}", obj) # set the obj to @line_item
end
def require_user
return true if logged_in?
render_error_message("You must be logged in to access this page",
new_user_session_url)
return false
end
def require_owner
obj = instance_variable_get("@#{controller_name.singularize.camelize.underscore}") # LineItem becomes @line_item
return true if current_user_is_owner?(obj)
render_error_message("You must be the #{controller_name.singularize.camelize} owner to access this page", root_url)
return false
end
def logged_in?
return current_user != nil
end
def current_user_is_owner?(obj)
logged_in? and obj.respond_to?(:user_id) and
(obj.send(:user_id) == current_user.id)
end
def render_error_message message, url
respond_to do |format|
format.html do
flash[:notice] = message
if request.xhr?
head :bad_request, :error => message
else
redirect_to url
end
end
format.json { render :json => message, :status => :unprocessable_entity }
format.xml { render :xml => message, :status => :unprocessable_entity }
end
end
end
Now in your controller
class PostsController < ApplicationController
before_filter :require_user # all actions require user to be logged in
before_filter :init_data # create a member variable called @post, initialized based on the action
before_filter :require_owner, :only => [:edit, :update, :destroy] #edit, update, and destroy actions require ownership
def update
if @post.save
else
end
end
end
In the view code:
<% if current_user_is_owner?(question) %>
.. display something
<% end %>
精彩评论