Skip to content
Browse files

added permit role files

  • Loading branch information...
1 parent 69277ca commit 8d40e89d9ff03d3328882d644e2727da61d0a7b8 Kristian Mandrup committed Nov 25, 2011
View
6 README.mdown
@@ -2,7 +2,11 @@
Roles and Role groups extension for [CanTango](https://github.com/kristianmandrup/cantango)
-The Configuration DSL has now been almost fully "spec'ed".
+* Roles and RoleGroups Configuration Registry
+* Role and RoleGroup Permits for the Permits Ability executor (formerly engine)
+* Role and RoleGroup Permit Genenerators
+* Role and RoleGroup Filters
+* Role and RoleGroup Helpers
## Contributing to cantango-config
View
35 lib/cantango/builder/permit/role.rb
@@ -0,0 +1,35 @@
+module CanTango::Builder
+ module Permit
+ class Role < Base
+ include CanTango::Helpers::Debug
+
+ # builds a list of Permits for each role of the current ability user (or account)
+ # @return [Array<RoleGroupPermit::Base>] the role permits built for this ability
+ def build
+ if roles.empty?
+ debug "Not building any RolePermit"
+ return []
+ end
+ roles.inject([]) do |permits, role|
+ debug "Building RolePermit for #{role}"
+ (permits << create_permit(role)) if valid?(role.to_sym)
+ permits
+ end.compact
+ end
+
+ protected
+
+ def roles
+ ability.respond_to?(:roles) ? ability.roles : []
+ end
+
+ def valid? role
+ filter(role).valid?
+ end
+
+ def filter role
+ CanTango::Filters::RoleFilter.new role
+ end
+ end
+ end
+end
View
61 lib/cantango/builder/permit/role_group.rb
@@ -0,0 +1,61 @@
+module CanTango::Builder
+ module Permit
+ class RoleGroup < Base
+ include CanTango::Helpers::Debug
+ # builds a list of Permits for each role group of the current ability user (or account)
+ # @return [Array<RoleGroupPermit::Base>] the role group permits built for this ability
+ def build
+ matching_permits = matching_role_groups(roles).inject([]) do |permits, role_group|
+ debug "Building RoleGroupPermit for #{role_group}"
+ (permits << create_permit(role_group)) if valid?(role_group)
+ permits
+ end.compact
+
+ if matching_permits.empty?
+ debug "Not building any RoleGroupPermits since no role groups could be found that are relevant for the permission candidate"
+ return []
+ end
+ matching_permits
+ end
+
+ def name
+ :role_group
+ end
+
+ def valid? role_group
+ return true if !role_groups_filter?
+ filter(role_group).valid?
+ end
+
+ def filter role_group
+ CanTango::Filters::RoleGroupFilter.new role_group
+ end
+
+ private
+
+ def role_groups
+ ability.respond_to?(:role_groups) ? ability.role_groups : []
+ end
+
+ def matching_role_groups roles
+ role_groups | matching_role_groups_for(roles)
+ end
+
+ # will also run role_groups for which any role of the candidate is a member
+ # so if the candidate is a user and the user has a :trustee role and this role is part of the :trust role group,
+ # then the :trust role group permit will be run!
+ # Thus if the candidate has a particular role group or just has a role belonging to that role group, the permit
+ # for that role group will be run
+ def matching_role_groups_for roles
+ roles.inject([]) do |groups, role|
+ groups << subject.role_groups_for(role) if subject.respond_to?(:role_groups_for)
+ groups
+ end.flatten.compact.uniq
+ end
+
+ def role_groups_filter?
+ CanTango.config.role_groups.filter?
+ end
+ end
+ end
+end
View
34 lib/cantango/filter/base.rb
@@ -1,34 +0,0 @@
-module CanTango
- module Filter
- class Base
- attr_reader :item, :include_list
-
- def initialize item, list = nil
- @item = item.to_sym
- @include_list = list || []
- end
-
- def valid?
- return false if !in_include_list?
- return false if not_only?
- !excluded?
- end
-
- def in_include_list?
- return true if include_list.empty?
- include_list.include? item
- end
-
- def not_only?
- false
- end
-
- def excluded?
- false
- end
- end
- end
-end
-
-
-
View
33 lib/cantango/permit/role.rb
@@ -0,0 +1,33 @@
+module CanTango
+ module Permit
+ class Role < Base
+ extend ClassMethods
+
+ # creates the permit
+ # @param [Permits::Ability] the ability
+ # @param [Hash] the options
+ def initialize ability
+ super
+ end
+
+ def valid_for? subject
+ in_role? subject
+ end
+
+ def self.hash_key
+ roles_list_meth
+ end
+
+ protected
+
+ include CanTango::Helpers::RoleMethods
+ extend CanTango::Helpers::RoleMethods
+
+ def in_role? subject
+ return subject.send(has_role_meth, role) if subject.respond_to? has_role_meth
+ return subject.send(roles_list_meth).include? role if subject.respond_to? roles_list_meth
+ false
+ end
+ end
+ end
+end
View
45 lib/cantango/permit/role_group.rb
@@ -0,0 +1,45 @@
+module CanTango
+ module Permit
+ class RoleGroup < Base
+ extend ClassMethods
+
+ def name
+ self.class.permit_name self.class
+ end
+
+ # creates the permit
+ def initialize executor
+ super
+ end
+
+ def execute!
+ super
+ end
+
+ def valid_for? subject
+ in_role_group? subject
+ end
+
+ def self.hash_key
+ role_groups_list_meth
+ end
+
+ protected
+
+ include CanTango::Helpers::RoleMethods
+ extend CanTango::Helpers::RoleMethods
+
+ def in_role_group? subject
+ has_role_group?(subject) || role_groups_of(subject).include?(role)
+ end
+
+ def has_role_group? subject
+ subject.send(has_role_group_meth, role) if subject.respond_to?(has_role_group_meth)
+ end
+
+ def role_groups_of subject
+ subject.respond_to?(role_groups_list_meth) ? subject.send(role_groups_list_meth) : []
+ end
+ end
+ end
+end
View
71 lib/generators/cantango/base.rb
@@ -0,0 +1,71 @@
+require 'generators/cantango/basic'
+
+module Cantango
+ module Generators
+ class Base < ::Rails::Generators::Base
+
+ include Cantango::Generators::Basic
+
+ CAN_ACTIONS = [:create, :update, :manage, :read, :access]
+
+ CAN_ACTIONS.each do |action|
+ class_eval %{
+ class_option :#{action}, :type => :array, :default => [], :desc => "Models allowed to #{action}"
+ class_option :not_#{action}, :type => :array, :default => [], :desc => "Models not allowed to #{action}"
+ }
+ end
+
+ protected
+
+ [:user, :account].each do |name|
+ define_method :"#{name}?" do
+ false
+ end
+ end
+
+ CAN_ACTIONS.each do |action|
+ class_eval %{
+ def #{action}
+ options[:#{action}]
+ end
+ }
+ end
+
+ CAN_ACTIONS.each do |action|
+ class_eval %{
+ def not_#{action}
+ options[:not_#{action}]
+ end
+ }
+ end
+
+ def rules_logic
+ can_logic
+ cannot_logic
+ end
+
+ def can_logic
+ CAN_ACTIONS.map do |action|
+ send(action).map do |c|
+ "can(:#{action}, #{act_model(c)})"
+ end.join("\n ")
+ end.join("\n")
+ end
+
+ def cannot_logic
+ CAN_ACTIONS.map do |action|
+ send(action).map do |c|
+ "can(:#{action}, #{act_model(c)})"
+ end.join("\n ")
+ end.join("\n")
+ end
+
+ def act_model name
+ return ':all' if name == 'all'
+ name.camelize
+ end
+ end
+ end
+end
+
+
View
41 lib/generators/cantango/basic.rb
@@ -0,0 +1,41 @@
+module Cantango
+ module Generators
+ module Basic
+ def rules_logic
+ ''
+ end
+
+ def license_logic
+ ''
+ end
+
+ def base_logic
+ %{
+ }
+ end
+
+ def admin_logic
+ %{
+ can :manage, :all
+ }
+ end
+
+ def guest_logic
+ %{
+ can :read, :all
+ }
+ end
+
+ def account
+ options[:account]
+ end
+
+ [:is_user, :is_account, :is_group].each do |name|
+ define_method :"#{name}?" do
+ false
+ end
+ end
+ end
+ end
+end
+
View
15 lib/generators/cantango/license_base.rb
@@ -0,0 +1,15 @@
+module Cantango
+ module Generators
+ module LicenseBase
+ def licenses
+ options[:licenses]
+ end
+
+ def license_logic
+ return ' # use any licenses here' if licenses.empty?
+ ls = licenses.map{|c| ":#{c}"}.join(", ")
+ "licenses #{ls}"
+ end
+ end
+ end
+end
View
58 lib/generators/cantango/permit_generator.rb
@@ -0,0 +1,58 @@
+require 'generators/cantango/basic'
+
+module Cantango
+ module Generators
+ module PermitGenerator
+ attr_accessor :permit_name, :permit_logic
+
+ include Cantango::Generators::Basic
+
+ def template_permit name, account = nil
+ @permit_name = name
+ set_logic name
+ account.present? ? template_account_permit(name, account) : template_simple_permit(name)
+ end
+
+ def template_simple_permit name
+ template permit_source, "app/permits/#{permit_target(name)}"
+ end
+
+ def template_account_permit name, account
+ template "account_permit.erb" , "app/permits/#{account}/#{permit_target(name)}"
+ end
+
+ def load_permit_template name
+ template = ERB.new File.open(template_filepath).read.gsub(/\n/, "\n\s\s")
+ template.result(binding)
+ end
+
+ def template_filepath
+ File.join source_path, permit_source
+ end
+
+ def source_path
+ source_paths.first
+ end
+
+ def permit_source
+ return "user_permit.erb" if is_user?
+ return "account_permit.erb" if is_account?
+
+ is_group? ? "role_group_permit.erb" : "role_permit.erb"
+ end
+
+ def permit_target name
+ name = name.to_s.underscore
+ return "#{name}_permit.rb" if is_user?
+ return "#{name}_account_permit.rb" if is_account?
+
+ is_group? ? "#{name}_role_group_permit.rb" : "#{name}_role_permit.rb"
+ end
+
+ def set_logic name
+ meth = "#{name}_logic"
+ @permit_logic = respond_to?(meth) ? send(meth) : base_logic
+ end
+ end
+ end
+end
View
39 lib/generators/cantango/role_permit/role_permit_generator.rb
@@ -0,0 +1,39 @@
+require 'generators/cantango/base'
+require 'generators/cantango/license_base'
+require 'generators/cantango/permit_generator'
+
+module Cantango
+ module Generators
+ class RolePermitGenerator < Cantango::Generators::Base
+ desc "Creates a Permit for a role in 'app/permits' with specific permissions and/or licenses"
+
+ argument :role, :type => :string,
+ :desc => "Role to create permit for"
+
+ class_option :licenses, :type => :array, :default => [],
+ :desc => "Licenses to use in Permit"
+
+ class_option :account, :type => :string,
+ :desc => "Generate permits for a specific user account"
+
+ class_option :group, :type => :boolean, :default => false, :desc => "Generate permit for a role group"
+
+ source_root File.dirname(__FILE__) + '/templates'
+
+ def main_flow
+ template_permit role
+ end
+
+ protected
+
+ include Cantango::Generators::LicenseBase
+ include Cantango::Generators::PermitGenerator
+
+ alias_method :role_group, :role
+
+ def is_group?
+ options[:group]
+ end
+ end
+ end
+end
View
4 lib/generators/cantango/role_permit/templates/account_permit.erb
@@ -0,0 +1,4 @@
+module <%= account.to_s.camelize%>AccountPermits
+<%= load_permit_template :role_permit %>
+end
+
View
24 lib/generators/cantango/role_permit/templates/role_group_permit.erb
@@ -0,0 +1,24 @@
+class <%= permit_name.to_s.camelize %>RoleGroupPermit < CanTango::RoleGroupPermit
+ def initialize ability
+ super
+ end
+
+ protected
+
+ def permit_rules
+ # insert your can, cannot and any other rule statements here
+ <%= rules_logic.strip %>
+ <%= license_logic %>
+ end
+
+ module Cached
+ def permit_rules
+ end
+ end
+
+ module NonCached
+ def permit_rules
+ end
+ end
+end
+
View
23 lib/generators/cantango/role_permit/templates/role_permit.erb
@@ -0,0 +1,23 @@
+class <%= permit_name.to_s.camelize %>RolePermit < CanTango::RolePermit
+ def initialize ability
+ super
+ end
+
+ protected
+
+ def permit_rules
+ # insert your can, cannot and any other rule statements here
+ <%= rules_logic.strip %>
+ <%= license_logic %>
+ end
+
+ module Cached
+ def permit_rules
+ end
+ end
+
+ module NonCached
+ def permit_rules
+ end
+ end
+end
View
45 lib/generators/cantango/role_permits/role_permits_generator.rb
@@ -0,0 +1,45 @@
+require 'generators/cantango/permit_generator'
+
+module Cantango
+ module Generators
+ class RolePermitsGenerator < Rails::Generators::Base
+ desc "Creates a Permit for each role in 'app/permits' and ensures that the permit folder is added to Rails load path."
+
+ argument :roles, :type => :array,
+ :desc => "Roles to create permits for"
+
+ class_option :special_permits, :type => :boolean, :default => false,
+ :desc => "Create special permits Syatem and Any"
+
+ class_option :account, :type => :string,
+ :desc => "Generate permits for a specific user account"
+
+ class_option :group, :type => :boolean, :default => false,
+ :desc => "Generate permits for role groups"
+
+ source_root File.dirname(__FILE__) + '/../role_permit/templates'
+
+ def main_flow
+ create_special_permits if special_permits?
+ create_permits
+ end
+
+ protected
+
+ include Cantango::Generators::PermitGenerator
+
+ def create_special_permits
+ template_permit :any
+ template_permit :system
+ end
+
+ def create_permits
+ roles.each { |role| template_permit role }
+ end
+
+ def special_permits?
+ options[:special_permits]
+ end
+ end
+ end
+end

0 comments on commit 8d40e89

Please sign in to comment.
Something went wrong with that request. Please try again.