Skip to content
kristianmandrup edited this page Nov 8, 2011 · 1 revision

The CanTango API consist of a User API and an Account API. The full CanTango API is added to Rails Views and Controllers on application initialization and also to the CanTango::Api module, in order to be globally accessible, for example at the class level when various classes are loaded (fx required for ActiveAdmin integration).

User API

CanTango comes with the following Core APIs for users:

  • Ability API
  • Can API
  • Scope API
  • Session API

The examples below assume we have the user models User and Admin registered as Cantango users.

User Ability API

  • user_ability user, options
  • current_user_ability user_type

Example use:

user_ability(current_user).can? :read, Project
current_user_ability(:admin).can? :edit, Post

User Can API

The Can API is very similar to the CanCan API but instead uses a CanTango::Ability for a specific kind of current user. The devise methods #current_xxxx such as current_user, current_admin etc. are wll integrated in the Can API. For the user models User and Admin, Cantango will provide the following API:

API methods:

  • user_can? actions, targets
  • user_cannot? actions, targets
  • admin_can? actions, targets
  • admin_cannot? actions, targets

Example use:

if user_can? :edit, Article
  # do sth
end
if admin_cannot? :manage, Article
  # do sth
end

User Scope API

The Scope API is useful when you want to do several ability tests for the same kind of user.

API methods:

  • scope_user type, options = {}, &block
  • real_user type, options = {}, &block

#scope_user is used to define an ability scope for a specific user. The permission API can then operate on this ability scope directly instead of having to create the ability each time.

Example use #scope_user:

scope_user :admin do |admin|
  if admin.can?(:edit, Article) || admin.can?(:read, Post)
    # do stuff
  end
  if admin.can? :delete, Article
    # delete link here
  end
end

User Session API

The session user API consists of the following methods

  • session_[user type]
  • any_user *names
  • guest_user

Example use:

  @user = session_user || session_admin
  @some_user = any_user :admin, :user
  show_guest if guest_user

Real user

The method #real_user is used to explicitly negate masquerading within the scope. Thus the permissions apply to the real user, not the masqueraded user.

Assume we have an app divided into a public app and an admin app.

For an Admin user it could make sense to masquerade as a Public user in the public part of the application, but remain as an Admin user in the admin app while remaining in the same session.

This can be achieve using #real_user in the admin app.

Example use #real_user:

real_user :admin do |admin|
  if admin.can?(:edit, Article) || admin.can?(:read, Post)
    # do stuff
  end
  if admin.can? :delete, Article
    # delete link here
  end
end

User Account API

The User Account APIs are very similar to the User APIs

  • Ability API
  • Can API
  • Scope API
  • Session API

Assume we have the account models UserAccount and AdminAccount registered as Cantango users.

Account Ability API

  • account_ability account, options
  • current_account_ability account_type

Example use:

account_ability(current_user_account).can? :read, Project
current_account_ability(:admin).can? :edit, Post

Account Can API

The Account Can API expects methods in the form #current_xxxx are available for each type of user account. In our scenario, #current_user_account and #current_admin_account should be available. Cantango will provide the following API:

API methods:

  • user_can? actions, targets
  • user_cannot? actions, targets
  • admin_can? actions, targets
  • admin_cannot? actions, targets

Example use:

if user_account_cannot? :edit, Article
  # do sth
end
if admin_account_can? :manage, Article
  # do sth
end

Account Scope API

The Scope API is useful when you want to do several ability tests for the same kind of user account.

API methods:

  • scope_acount type, options = {}, &block
  • as_real_account type, options = {}, &block

#scope_account is used to define an ability scope for a specific user account. The permission API can then operate on this ability scope directly instead of having to create the ability each time.

Example use #scope_account:

scope_account :admin do |account|
  if account.can?(:edit, Article) || account.can?(:read, Post)
    # do stuff
  end
  if account.can? :delete, Article
    # delete link here
  end
end

Account Session API

The session user API consists of the following methods

  • session_[account type]_account
  • any_account *names
  • guest_account

Example use:

  @account = session_user_account || session_admin_account
  @some_account = any_account :admin, :user
  show_guest_account(guest_account) if guest_account

Real account

#real_account is used to explicitly negate masquerading within the scope. Thus the permissions apply to the real account, not the masqueraded account.

Assume we have an app divided into a public app and an admin app.

For an Admin user it could make sense to masquerade as if he was logged in to the Public account in the public part of the application. The admin should remain as an Admin user on the Admin account when accessing the admin app, while remaining in the same session.

This can be achieve using #real_account in the admin app.

Example use #real_account:

real_account :admin do |account|
  if account.can?(:edit, Article) || account.can?(:read, Post)
    # do stuff
  end
  if account.can? :delete, Article
    # delete link here
  end
end

Attribute API

The Attribute API, allows you to define fine grained permissions on the object attribute level. Here an example:

class EditorRolePermit < CanTango::RolePermit
  def permit_rules
    can :edit, User
    cannot :delete, User
    can read_attributes(:name, :description), Project
    cannot edit_attributes(:version, :published), User
    can edit_attribute(:title), Post
  end
end

The two permission levels are :read and :edit, given by the methods #read_attributes and #edit_attributes that each takes a list of symbols for the attributes. You can also use the singular form which takes a single symbol as argument.

You can test for attribute permissions like this:

user_can? read_attributes(:name, :description), Project
user_can? edit_attribute(:title), Post