1
votes

I think I am missing something while using the Authlogic 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
2

2 Answers

1
votes

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.

0
votes

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 %>