1
votes

Role based authorization in my app is based on cancan (using rvm 1.9.2@rails_3_0_9 and AuthLogic):

In the view I'm testing I get this:

wrong number of arguments (1 for 0) Extracted source (around line #12):

12: %td = link_to 'Edit', edit_session_path(session) if can? :manage, @session

I should explain the usual authentication classes for Authlogic, User and User_session models are replaced in this app with Contact and Contact_sessions. The Session model instance above is not part of authentication here. (Think, the court is now in session...). This means you have to tell cancan about this change.

I've reset the default in ApplicationController:

class ApplicationController < ActionController::Base

  helper :all # include all helpers, all the time
  protect_from_forgery # See ActionController::RequestForgeryProtection for details

  helper_method :current_ability   #:current_contact

  def role?(base_role)
    ROLES.index(base_role.to_s) <= ROLES.index(role)
  end


  # = = = = = = = = = = = = logon controls = = = = = = = = = = = = = = = = = = =   
  private

    # Override default assumption by CanCan
    # https://github.com/ryanb/cancan/wiki/changing-defaults
    # in ApplicationController
    def current_ability
      @current_ability ||= Ability.new(current_contact)
    end  

    def require_contact
      unless current_contact
        redirect_to root_url, :notice => "You must be logged in to access this page."
        return false
      end
    end

    def current_contact_session
      return @current_contact_session if defined?(@current_contact_session)
      @current_contact_session = ContactSession.find
    end

    # return user model
    def current_contact
      return @current_contact if defined?(@current_contact)
      @current_contact = current_contact_session && current_contact_session.record
    end  

end

Roles and rights are defined in my Ability class, here:

class Ability
include CanCan::Ability

  # Role Inheritance
  # https://github.com/ryanb/cancan/wiki/Role-Based-Authorization
  # in Ability#initialize

  def initialize

    if @contact.role? :visitor
      can :read, [Home, Session]
    end

    if @contact.role? :camper
      can :read, [Home, Contact_session, Session]
      can :manage, Registration
    end

    if @contact.role? :admin
      can :manage, [Home, Contact_session, Contact, Session]
    end

    if @contact.role? :superadmin
      can :manage, :all
    end 

  end

end

And for what it's worth I have not added any code to any other controllers at this point (thinking I would decide what to do once I had can? methods where I want them).

Any idea what's wrong here? I'm assuming the wrong number of arguments is to something invoked by the can? method in line 12 of the view? I've tried dozens of alternatives and generated lots of other errors but as soon as I clean them up I'm back to this one. Every suggestion will be appreciated!

1
Welcome to Stack Overflow! When posting questions (and answers) there are markup possibilities that can make the question more readable. I've done some formatting to your post, if there are more things you want to do you can do that through the edit link.Anders Abel

1 Answers

1
votes

I figured it out: the Ability#initialize method takes an argument which is the current user object, and you can default this if there's no user logged in, like this (my User class is replaced in this app by one named Contact):

def initialize(current_contact) current_contact ||= Contact.create(:role => 'visitor') # guest user (not logged in)

Also, I found I didn't need the role? method in ApplicationController because it is quite straightforward and precise to specify the permissions explicitly and add to them over time, like this (in Ability#initialize):

if current_contact.role == 'superadmin'
  can :manage, :all
end 

if current_contact.role == 'admin'
  can :manage,

[Accommodation,Cabin,Contact,Identifier,Itinerary,Payment,Resident,Session,Sport] end

if current_contact.role == 'camper'
  can :read, Session
  can [:read,:update], Registration #:active => true, :user_id =>

user.id if it's their own.... add code for this end

 # A visitor can look around and register (but not manage

registrations) if current_contact.role == 'visitor' can :read, Session can :update, Registration end