2012-01-18 1 views
7

Я рассмотрел declarative_authorization, CanCan и CanTango. Все они хороши в добавлении авторизации к приложению, но мне было интересно, как добавить авторизацию к конкретному экземпляру модели, т.е. человек может иметь доступ к управлению в одном проекте и только ограниченный (читать меньше, чем управлять: ограниченное обновление и т. Д.), в другой.Авторизация в Rails 3.1: CanCan, CanTango, declarative_authorization?

Не могли бы вы предложить лучший способ? Извиняюсь, если мой вопрос звучит слишком тривиально. Это может быть потому, что я новичок в RoR.

спасибо, Джон

+0

В CanCan вы можете определить способности через блоки с условиями - https://github.com/ryanb/cancan/wiki/Defining-Abilities-with-Blocks. –

+0

1. TeamMembers имеет много пользователей, ролей 2. Команды имеют много TeamMembers 3. В проекте есть одна команда ... С блоками указанная выше настройка не дает средств для фильтрации для конкретного экземпляра проекта. Если вы думаете, что это можно сделать ... Не могли бы вы предоставить мне, например. Заранее спасибо. –

ответ

4

Как я знаю, канкан и declarative_authorization, и я реализовал на основе ролей разрешения с обоими, я рекомендую канкан. Только мои два цента.

Пример (непроверенные, к сожалению, я не могу проверить здесь и у меня нет доступа к моему коду)

Так скажем, у нас есть структура вроде этого:

class User < ActiveRecord::Base 
    belongs_to :role 
end 

class Role < ActiveRecord::Base 
    has_many :users 

    # attributes: project_read, project_create, project_update 
end 

Тогда, канкан может выглядеть например:

class Ability 
    include CanCan::Ability 

    def initialize(user) 
    @user = user 
    @role = user.role 

    # user can see a project if he has project_read => true in his role 
    can :read, Project if role.project_read? 

    # same, but with create 
    can :create, Project if role.project_create? 

    # can do everything with projects if he is an admin 
    can :manage, Project if user.admin? 
    end 

end 

Вы можете найти всю необходимую информацию в вики CanCan на github. Личная рекомендация следующего содержания:

В основном вам просто нужно расширить пример выше, чтобы включить свои роли через свои отношения. Чтобы это было просто, вы также можете создать дополнительные вспомогательные методы в ability.rb.

Основное среднее предостережение может упасть (по крайней мере, я): Убедитесь, что пользователь может сделать что-то с моделью, прежде чем определить, что пользователь не может . В противном случае вы будете сидеть там разочарованы и подумать «но почему? Я никогда не писал, что пользователь не может». Да. Но вы также никогда явно не писал, что он может ...

+0

Я реализовал cancan .. но не могу понять, как определить/ограничить пользователя конкретным экземпляром (например, проекта). Любой, например. было бы действительно полезно. Существует косвенная связь между пользователем и проектом ... 1. У TeamMembers много пользователей 2. Команды имеют много TeamMembers 3. В проекте есть одна команда –

+0

, приведенная в качестве примера. – pduersteler

+0

Мне нужно установить cancan И создать образец для подражания? Я не вижу в документации канкана, что это необходимо. Не могли бы вы объяснить это? спасибо –

0
class User < ActiveRecord::Base 

    belongs_to :role 
    delegate :permissions, :to => :role 

    def method_missing(method_id, *args) 
    if match = matches_dynamic_role_check?(method_id) 
     tokenize_roles(match.captures.first).each do |check| 
     return true if role.name.downcase == check 
     end 
     return false 
    elsif match = matches_dynamic_perm_check?(method_id) 
     return true if permissions.find_by_name(match.captures.first) 
    else 
     super 
    end 
    end 


    private 

    def matches_dynamic_perm_check?(method_id) 
    /^can_([a-zA-Z]\w*)\?$/.match(method_id.to_s) 
    end 

    def matches_dynamic_role_check?(method_id) 
    /^is_an?_([a-zA-Z]\w*)\?$/.match(method_id.to_s) 
    end 

    def tokenize_roles(string_to_split) 
    string_to_split.split(/_or_/) 
    end 

end 

Использование:

user.is_an? admin

user.can_delete?