permissify 0.0.17 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,14 +7,19 @@ module SystemFixtures::Abilities
7
7
 
8
8
  # can organize permissions into categories that correspond to your client's/product team's view of app.
9
9
  # suggest playing with your Ability class and the builder methods in console.
10
- # add_category('Tabs', 'Tabs', ['Role'], %w(Admin Dealer Corporate Brand Merchant))
10
+
11
+ # NOTE : 'Role' and 'Product' references in following example are actually *class names*.
12
+ # This is a name coupling (see Permissify::Union) that can be overriden.
13
+
14
+ # applies_to_users_only = [User::PERMISSIFIED_ABILITY_APPLICABILITY]
15
+ # add_category('Tabs', 'Tabs', applies_to_users_only, %w(Admin Dealer Corporate Brand Merchant))
11
16
  # { 'Roles' => 'Admin',
12
17
  # 'Admin Users' => 'Admin',
13
18
  # 'Dealer Users' => 'Dealer Admin',
14
19
  # 'Corporate Users' => 'Corporate Admin',
15
20
  # 'Brand Users' => 'Brand Admin',
16
21
  # 'Merchant Users' => 'Merchant Admin',
17
- # }.each{ |category, section| add_category(category, section) }
22
+ # }.each{ |category, section| add_category(category, section, applies_to_users_only) }
18
23
  end
19
24
 
20
25
  end
@@ -1,10 +1,10 @@
1
- module PermissifiedController # Interface : override/rewrite as needed for your app
1
+ module PermissifiedController # Interfaces : override/rewrite as needed for your app
2
2
 
3
- # app-specific consideration for whether operating on a merchant/business, brand, corporation, dealer or admin
4
- def current_entity
5
- TODO_IMPLEMENT_PERMISSIFY_CONTROLLER_CURRENT_ENTITY_INTERFACE_METHOD
6
- # return @current_entity if @current_entity
7
- # nil
8
- end
3
+ # controller-accessible methods that app has implemented to access models that have been permissified.
4
+ PERMISSIFY = SPECIFY_PERMISSIFIED_MODEL_LIST_IN__APP__CONTROLLERS__PERMISSIFIED_CONTROLLER
9
5
 
6
+ # PERMISSIFY = { User::PERMISSIFIED_ABILITY_APPLICABILITY => :current_user,
7
+ # 'Product' => :current_entity, # Merchant::PERMISSIFIED_ABILITY_APPLICABILITY
8
+ # }
9
+
10
10
  end
data/lib/permissify.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'permissify/ability_class'
2
- require 'permissify/aggregate'
2
+ require 'permissify/common'
3
3
  require 'permissify/controller'
4
4
  require 'permissify/model'
5
5
  require 'permissify/model_class'
6
+ require 'permissify/union'
6
7
  require 'permissify/roles'
@@ -18,22 +18,30 @@ module Permissify
18
18
 
19
19
  def all_for(applicability_types)
20
20
  applicability_types = [applicability_types] if applicability_types.kind_of?(String)
21
+ applicability_types = applicability_types.to_set
21
22
  all.select{|a| (a[:applicability] & applicability_types) == applicability_types}
22
23
  end
23
24
 
24
- def add(key, category, section, action, applicability, number_of_values, position, default_values, admin_expression='', category_allows = :multiple)
25
- @@abilities << { :key => key, :category => category, :section => section, :action => action,
25
+ def get(action, category)
26
+ key = key_for(action, category)
27
+ all.select{ |ability| ability[:key] == key }.first
28
+ end
29
+
30
+ def add(category, section, action, applicability, requires_any_or_all, number_of_values, position, default_values, admin_expression='', category_allows = :multiple)
31
+ applicability = applicability.to_set
32
+ @@abilities << { :key => key_for(action, category), :category => category, :section => section, :action => action,
26
33
  :applicability => applicability, :number_of_values => number_of_values, :position => position,
27
- :default_values => default_values, :administration_expression => admin_expression, :category_allows => category_allows}
34
+ :default_values => default_values, :administration_expression => admin_expression,
35
+ :category_allows => category_allows, :any_or_all => requires_any_or_all}
28
36
  end
29
37
 
30
- def add_category(category, section, applicability=['Role'], actions=%w(View Create Update Delete), category_allows = :multiple)
38
+ def add_category(category, section, applicability, actions = %w(View Create Update Delete), requires_any_or_all = :all?, category_allows = :multiple)
31
39
  actions = [actions] unless actions.kind_of?(Array)
32
40
  actions.collect do |action|
33
- add("#{key_token(category)}_#{key_token(action)}", category, section, action, applicability, 1, actions.index(action)+1, [false], '', category_allows)
41
+ add(category, section, action, applicability, requires_any_or_all, 1, actions.index(action)+1, [false], '', category_allows)
34
42
  end
35
43
  end
36
-
44
+
37
45
  def create_permissions_hash(view_only_categories=[], remove_categories=[], applicability_types = 'Role')
38
46
  @@permissions = {}
39
47
  all_for(applicability_types).each{|permission| @@permissions[permission[:key]] = {'0' => '1'}}
@@ -55,10 +63,15 @@ module Permissify
55
63
  def current_permissions_hash
56
64
  @@permissions
57
65
  end
66
+
67
+ def key_for(action, category)
68
+ "#{key_token(category)}_#{key_token(action)}"
69
+ end
58
70
 
59
71
  private
72
+
60
73
  def key_token(token)
61
- token.downcase.gsub('-','_').gsub(':','').gsub(' ',' ').gsub(' ','_')
74
+ token.to_s.downcase.gsub('-','_').gsub(':','').gsub(' ',' ').gsub(' ','_')
62
75
  end
63
76
 
64
77
  def view_only(category)
@@ -0,0 +1,33 @@
1
+ module Permissify
2
+ module Common
3
+
4
+ def allowed_to?(action, ability_category)
5
+ permission(action, ability_category) == true
6
+ end
7
+
8
+ def viewable?(ability_category); allowed_to?(:view, ability_category); end
9
+ def createable?(ability_category); allowed_to?(:create, ability_category); end
10
+ def updateable?(ability_category); allowed_to?(:update, ability_category); end
11
+ def deleteable?(ability_category); allowed_to?(:delete, ability_category); end
12
+ def subscribed_to?(ability_category); allowed_to?(:on, ability_category); end
13
+
14
+ def permissible?(permissions_hash, action, category)
15
+ key = Ability.key_for(action, category)
16
+ (permission = permissions_hash[key]) && permission['0'] == true
17
+ end
18
+
19
+ def log_permissions
20
+ message = "*** PermissifyController permissions: #{@permissions.inspect}"
21
+ defined?(logger) ? logger.debug(message) : puts(message)
22
+ end
23
+
24
+ # NOTE : mothballed additional permission values...
25
+ # def arbitrate(aggregation, other_descriptor, key, min_or_max) # assuming all permission 'args' are integers stored as strings
26
+ # 1.upto(other_descriptor.size-1) do |i|
27
+ # is = i.to_s
28
+ # aggregation[key][is] = [aggregation[key][is].to_i, other_descriptor[is].to_i].send(min_or_max) # .to_s ?
29
+ # end
30
+ # end
31
+
32
+ end
33
+ end
@@ -1,24 +1,41 @@
1
1
  module Permissify
2
2
  module Controller
3
3
 
4
- def allowed_to?(action, permission_category)
5
- (domain_permissions["#{permission_category}_#{action}"]['0'] == true rescue false)
4
+ include Permissify::Common
5
+
6
+ def permission(action, category) # interface used by Permissfy::Common.allowed_to?
7
+ @permissions ||= construct_permissions # TODO : get lazier?
8
+ permissible?(@permissions, action, category)
6
9
  end
7
-
10
+
8
11
  private
9
12
 
10
- def domain_permissions
11
- @permissions ||= determine_domain_permissions
13
+ def construct_permissions
14
+ @applicable_permissions = {}
15
+ permissions = {}
16
+ Ability.all.each { |ability| permissions[ ability[:key] ] = authorized?(ability) }
17
+ # puts "*** PERMISSIONS: #{permissions.inspect} ***"
18
+ permissions
12
19
  end
13
-
14
- def determine_domain_permissions
15
- e = current_entity
16
- u = current_user
17
- if u.nil?
18
- e ? e.permissions_union : {} # public pages display according to just corp/brand/merchant product permissions
19
- else
20
- e ? u.permissions_intersection(e.permissions_union) : u.permissions_union
21
- end
20
+
21
+ def authorized?(ability, key = ability[:key], applicablity = ability[:applicability], requires_any_or_all = ability[:any_or_all])
22
+ # puts "AUTHORIZED?: ability: #{key}, #{applicablity}, #{requires_any_or_all}"
23
+ authorizations = applicablity.collect{|applicable| applicable_authorization(applicable, key) }
24
+ { '0' => authorizations.send(requires_any_or_all) }
25
+ end
26
+
27
+ def applicable_authorization(applicable, key)
28
+ (permission = applicable_permissions(applicable)[key]) && permission['0'] == true
29
+ end
30
+
31
+ def applicable_permissions(applicablity)
32
+ @applicable_permissions[applicablity] ||= permissified_model_permissions(applicablity)
33
+ end
34
+
35
+ def permissified_model_permissions(applicablity)
36
+ permissified_model_method = self.class::PERMISSIFY[applicablity]
37
+ permissified_model = send(permissified_model_method)
38
+ permissified_model ? permissified_model.permissions : Hash.new({})
22
39
  end
23
40
 
24
41
  end
@@ -1,42 +1,45 @@
1
- module Permissify::Roles
2
- include Permissify::Aggregate
1
+ module Permissify
2
+ module Roles
3
3
 
4
- # inclusion of this module necessitates that the app's roles implementation includes:
5
- # 1. domain_type field
6
- # 2. define DOMAIN_TYPES as a ranked list of strings in implementation of Role/Permissify::Model-including class
4
+ include Permissify::Union
7
5
 
8
- # NOTE: in example app, helper methods enforce only assigning domain_type-specific roles to users
9
- # (an brand user can only be asigned roles that have a domain type of Brand).
10
- def primary_domain_type
11
- return nil if roles.empty?
12
- domain_types = roles.collect(&:domain_type)
13
- ranked_domain_types = roles.first.class::DOMAIN_TYPES
14
- ranked_domain_types.each do |ranked_domain_type|
15
- return ranked_domain_type if domain_types.include?(ranked_domain_type)
6
+ # inclusion of this module necessitates that the app's roles implementation includes:
7
+ # 1. domain_type field
8
+ # 2. define DOMAIN_TYPES as a ranked list of strings in implementation of Role/Permissify::Model-including class
9
+
10
+ # NOTE: in example app, helper methods enforce only assigning domain_type-specific roles to users
11
+ # (an brand user can only be asigned roles that have a domain type of Brand).
12
+ def primary_domain_type
13
+ return nil if roles.empty?
14
+ domain_types = roles.collect(&:domain_type)
15
+ ranked_domain_types = roles.first.class::DOMAIN_TYPES
16
+ ranked_domain_types.each do |ranked_domain_type|
17
+ return ranked_domain_type if domain_types.include?(ranked_domain_type)
18
+ end
19
+ nil # unrecognized domain_type value(s)
16
20
  end
17
- nil # unrecognized domain_type value(s)
18
- end
19
21
 
20
- # uncomment/reimplement methods as needed for example app/as more light shines...
22
+ # uncomment/reimplement methods as needed for example app/as more light shines...
21
23
 
22
- # def primary_domain_type; sorted_domain_types.first; end
23
- # def primary_role_name; role_list(:description).sort.first; end
24
- # def sorted_domain_types; role_list(:domain_type).sort; end
25
- # def manages_roles; role_list(:manages_roles); end
26
- # def manages_role_names; sorted_role_names(manages_roles); end
27
- # def role_list(collection_method); roles.collect(&collection_method).flatten.uniq; end
28
- #
29
- # def can_create_and_modify(users, app_instance) # TODO : unit test for this
30
- # role_names_that_this_user_can_manage = manages_role_names
31
- # # 2 ways to go here : must be able to manage *all* or *any* of a user's roles.
32
- # # Chose *all* to prevent lower ranking users from demoting higher ranking users
33
- # users.select do |u|
34
- # u_role_names = sorted_role_names(u.roles)
35
- # ! u_role_names.blank? && (role_names_that_this_user_can_manage & u_role_names) == u_role_names
36
- # end
37
- # users.delete_if{|u| !u.instances.include?(app_instance)}
38
- # return users
39
- # end
40
- #
41
- # def sorted_role_names(roles); roles.collect(&:name).sort; end
24
+ # def primary_domain_type; sorted_domain_types.first; end
25
+ # def primary_role_name; role_list(:description).sort.first; end
26
+ # def sorted_domain_types; role_list(:domain_type).sort; end
27
+ # def manages_roles; role_list(:manages_roles); end
28
+ # def manages_role_names; sorted_role_names(manages_roles); end
29
+ # def role_list(collection_method); roles.collect(&collection_method).flatten.uniq; end
30
+ #
31
+ # def can_create_and_modify(users, app_instance) # TODO : unit test for this
32
+ # role_names_that_this_user_can_manage = manages_role_names
33
+ # # 2 ways to go here : must be able to manage *all* or *any* of a user's roles.
34
+ # # Chose *all* to prevent lower ranking users from demoting higher ranking users
35
+ # users.select do |u|
36
+ # u_role_names = sorted_role_names(u.roles)
37
+ # ! u_role_names.blank? && (role_names_that_this_user_can_manage & u_role_names) == u_role_names
38
+ # end
39
+ # users.delete_if{|u| !u.instances.include?(app_instance)}
40
+ # return users
41
+ # end
42
+ #
43
+ # def sorted_role_names(roles); roles.collect(&:name).sort; end
44
+ end
42
45
  end
@@ -0,0 +1,33 @@
1
+ module Permissify
2
+ module Union
3
+
4
+ include Permissify::Common
5
+
6
+ def permission(action, category) # interface used by Permissify::Common.allowed_to?
7
+ @union ||= construct_union # TODO : get lazier?
8
+ permissible?(@union, action, category)
9
+ end
10
+
11
+ private
12
+
13
+ def construct_union
14
+ union = {}
15
+ permissified_models = self.send(self.class::PERMISSIFIED_ASSOCIATION)
16
+ permissions_hashes = permissified_models.collect(&:permissions)
17
+ permissions_hashes.each do |permissions_hash|
18
+ permissions_hash.each do |key, descriptor|
19
+ union[key] ||= {'0' => false}
20
+ # NOTE : mothballed additional permission values...
21
+ # if union[key].nil?
22
+ # union[key] = descriptor # TODO : check : does this have '1' or true? is spec construction masking reality?
23
+ # else
24
+ # arbitrate(union, descriptor, key, :max)
25
+ # end
26
+ # union[key]['0'] = (union[key]['0'] == true || descriptor['0'] == '1')
27
+ union[key]['0'] = true if descriptor['0'] == '1'
28
+ end
29
+ end
30
+ union
31
+ end
32
+ end
33
+ end
@@ -11,10 +11,20 @@ describe Permissify::AbilityClass do
11
11
  describe 'and interface seed implemented' do
12
12
  it 'should return the correct number of abilities' do
13
13
  (a = Ability.all).size.should == 29
14
- a.first.should == {:default_values=>[false], :applicability=>["Role"], :category=>"Tabs", :administration_expression=>"", :section=>"Tabs", :category_allows=>:multiple, :number_of_values=>1, :key=>"tabs_admin", :position=>1, :action=>"Admin"}
14
+ a.first.should == tab_admin_ability
15
15
  end
16
16
  end
17
17
  end
18
+
19
+ describe 'get' do
20
+ it 'should return ability that has input action and category' do
21
+ Ability.get('admin', 'tabs').should == tab_admin_ability
22
+ end
23
+
24
+ it 'should be nil when no ability with input key exists' do
25
+ Ability.get('wrong', 'tabs').should be_nil
26
+ end
27
+ end
18
28
 
19
29
  describe 'abilities builder method' do
20
30
  before(:each) { Ability.reset }
@@ -28,24 +38,27 @@ describe Permissify::AbilityClass do
28
38
  describe 'add_category' do
29
39
  it 'should establish correct ability expression for fully specified category and action' do
30
40
  add_category1_section1
31
- Ability.current.should == [{:section=>"section1", :category=>"category1", :action=>"view", :position=>1, :key=>"category1_view", :applicability=>["Role", "Product"], :category_allows=>:one_or_none, :administration_expression=>"", :number_of_values=>1, :default_values=>[false]}]
41
+ Ability.current.should == [{:section=>"section1", :category=>"category1", :action=>"view", :position=>1, :key=>"category1_view", :applicability=>["Role", "Product"].to_set, :category_allows=>:one_or_none, :administration_expression=>"", :number_of_values=>1, :default_values=>[false], :any_or_all => :all?}]
32
42
  end
33
43
 
34
44
  it 'should establish correct ability expression for category and action with defaulted values' do
35
- Ability.add_category('category2', 'section2')
36
- Ability.current.should == [ {:section=>"section2", :category=>"category2", :action=>"View", :position=>1, :key=>"category2_view", :applicability=>["Role"], :category_allows=>:multiple, :administration_expression=>"", :number_of_values=>1, :default_values=>[false]},
37
- {:section=>"section2", :category=>"category2", :action=>"Create", :position=>2, :key=>"category2_create", :applicability=>["Role"], :category_allows=>:multiple, :administration_expression=>"", :number_of_values=>1, :default_values=>[false]},
38
- {:section=>"section2", :category=>"category2", :action=>"Update", :position=>3, :key=>"category2_update", :applicability=>["Role"], :category_allows=>:multiple, :administration_expression=>"", :number_of_values=>1, :default_values=>[false]},
39
- {:section=>"section2", :category=>"category2", :action=>"Delete", :position=>4, :key=>"category2_delete", :applicability=>["Role"], :category_allows=>:multiple, :administration_expression=>"", :number_of_values=>1, :default_values=>[false]} ]
45
+ Ability.add_category('category2', 'section2', ['Role'])
46
+ Ability.current.should == [ {:section=>"section2", :category=>"category2", :action=>"View", :position=>1, :key=>"category2_view", :applicability=>["Role"].to_set, :category_allows=>:multiple, :administration_expression=>"", :number_of_values=>1, :default_values=>[false], :any_or_all => :all?},
47
+ {:section=>"section2", :category=>"category2", :action=>"Create", :position=>2, :key=>"category2_create", :applicability=>["Role"].to_set, :category_allows=>:multiple, :administration_expression=>"", :number_of_values=>1, :default_values=>[false], :any_or_all => :all?},
48
+ {:section=>"section2", :category=>"category2", :action=>"Update", :position=>3, :key=>"category2_update", :applicability=>["Role"].to_set, :category_allows=>:multiple, :administration_expression=>"", :number_of_values=>1, :default_values=>[false], :any_or_all => :all?},
49
+ {:section=>"section2", :category=>"category2", :action=>"Delete", :position=>4, :key=>"category2_delete", :applicability=>["Role"].to_set, :category_allows=>:multiple, :administration_expression=>"", :number_of_values=>1, :default_values=>[false], :any_or_all => :all?} ]
40
50
  end
41
51
  end
42
52
  end
43
53
 
44
- # TODO : specs for just Product, and Role and Product, applicabilities
45
54
  describe 'permission builder method' do
46
55
 
47
- describe 'create_permissions_hash(view_only_categories=[], remove_categories=[], applicability_types = "Role")' do
48
- before(:each) { Ability.seed; @ability_key_set = Ability.current.collect{|a| a[:key]}.to_set }
56
+ describe 'create_permissions_hash' do
57
+ before(:each) do
58
+ Ability.reset;
59
+ Ability.seed;
60
+ @ability_key_set = Ability.current.collect{|a| a[:key]}.to_set
61
+ end
49
62
 
50
63
  it 'should express each current ability when invoked with no arguments' do
51
64
  @ability_key_set.should == Ability.create_permissions_hash.keys.to_set
@@ -78,6 +91,10 @@ describe Permissify::AbilityClass do
78
91
  end
79
92
 
80
93
  def add_category1_section1(actions = 'view')
81
- Ability.add_category('category1', 'section1', %w(Role Product), actions, :one_or_none)
94
+ Ability.add_category('category1', 'section1', %w(Role Product), actions, :all?, :one_or_none)
95
+ end
96
+
97
+ def tab_admin_ability
98
+ {:default_values=>[false], :applicability=>["Role"].to_set, :category=>"Tabs", :administration_expression=>"", :section=>"Tabs", :category_allows=>:multiple, :number_of_values=>1, :key=>"tabs_admin", :position=>1, :action=>"Admin", :any_or_all => :all?}
82
99
  end
83
100
  end
@@ -1,74 +1,99 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Permissify::Controller do
4
- before(:each) { @controller = PermissifiedController.new }
5
-
4
+
6
5
  describe 'allowed_to?' do
7
- describe 'and no current entity' do
8
- before(:each) { @controller.should_receive(:current_entity).and_return(nil) }
6
+ before(:each) do
7
+ @controller = PermissifiedControllerish.new # controller specifies multiple permissified_model_method/ability applicability pairs
8
+ end
9
9
 
10
- it 'should return false when no current user' do
10
+ describe 'for an ability with a single applicability type, ' do
11
+ before(:each) do
12
+ @applicability = [Userish::PERMISSIFIED_ABILITY_APPLICABILITY]
13
+ add_ability :all?
14
+ end
15
+
16
+ it 'should be false when controller-specified model method for applicability type returns nil' do
11
17
  @controller.should_receive(:current_user).and_return(nil)
12
18
  allowed_to_should be_false
13
19
  end
14
20
 
15
- describe 'and current user is not nil' do
16
- before(:each) do
17
- @user = Userish.new
18
- @controller.should_receive(:current_user).and_return(@user)
19
- end
20
-
21
- it 'should return true when current user has permission for category action' do
21
+ describe 'and the model method associated with applicability type returns a (permissified) model, ' do
22
+ before(:each) { current_user_exists }
23
+
24
+ it 'should be true when model authorizes permission for ability' do
22
25
  category_action_permission_causes_allowed_to_be true, be_true
23
26
  end
24
27
 
25
- it 'should return false when current user does not have permission for category action' do
28
+ it 'should be false when model does not authorize permission for ability' do
26
29
  category_action_permission_causes_allowed_to_be false, be_false
27
30
  end
28
31
  end
29
32
  end
30
33
 
31
- describe 'and current entity exists' do
32
- describe 'and no current user' do
33
- it 'should return true when current entity has permission for category action' do
34
- pending('products phase')
34
+ describe 'for an ability with multiple applicability types, ' do
35
+ before(:each) do
36
+ current_user_exists
37
+ @applicability = [Entityish::PERMISSIFIED_ABILITY_APPLICABILITY, Userish::PERMISSIFIED_ABILITY_APPLICABILITY]
38
+ end
39
+
40
+ describe 'and ability requires all, ' do
41
+ before(:each) { add_ability(:all?) }
42
+
43
+ it 'should be false when any applicable model permission method returns nil' do
44
+ @controller.should_receive(:current_entity).and_return(nil)
45
+ category_action_permission_causes_allowed_to_be false, be_false
35
46
  end
47
+
48
+ describe 'and all applicable model permission methods return a (permissified) model' do
49
+ before(:each) do
50
+ @entity = Entityish.new
51
+ @controller.should_receive(:current_entity).and_return(@entity)
52
+ @entity.should_receive(:permissions).and_return( {"something_manage" => {'0' => true} })
53
+ end
54
+
55
+ it 'should be false when any applicable permissified model does not have permission for the ability' do
56
+ category_action_permission_causes_allowed_to_be false, be_false
57
+ end
36
58
 
37
- it 'should return false when current entity does not have permission for category action' do
38
- pending('products phase')
59
+ it 'should be true when all applicable permissified models have permission for the ability' do
60
+ category_action_permission_causes_allowed_to_be true, be_true
61
+ end
39
62
  end
40
63
  end
41
64
 
42
- describe 'and current user is not nil' do
43
- describe 'and current entity has permission for category action' do
44
- it 'should return true when current user has permission for category action' do
45
- pending('products phase')
46
- end
65
+ describe 'and ability requires any' do
66
+ before(:each) { add_ability(:any?) ; @controller.should_receive(:current_entity).and_return(nil) }
47
67
 
48
- it 'should return false when current user does not have permission for category action' do
49
- pending('products phase')
50
- end
68
+ it 'should be true when any applicable permissified model has permission for the ability' do
69
+ category_action_permission_causes_allowed_to_be true, be_true, :log_permissions
51
70
  end
52
-
53
- describe 'and current entity does not have permission for category action' do
54
- it 'should return false when current user has permission for category action' do
55
- pending('products phase')
56
- end
57
71
 
58
- it 'should return false when current user does not have permission for category action' do
59
- pending('products phase')
60
- end
72
+ it 'should be false when no applicable permissified model has permission for the ability' do
73
+ category_action_permission_causes_allowed_to_be false, be_false, :log_permissions
61
74
  end
62
75
  end
63
76
  end
64
77
 
65
- def category_action_permission_causes_allowed_to_be(permission_true_or_false, be_true_or_false, action = :view, category = :something)
66
- @user.should_receive(:permissions_union).and_return( {"#{category}_#{action}" => {'0' => permission_true_or_false} })
78
+ def add_ability(requires_any_or_all)
79
+ Ability.reset
80
+ Ability.add_category('something', 'a section', @applicability, 'manage', requires_any_or_all)
81
+ end
82
+
83
+ def category_action_permission_causes_allowed_to_be(permission_true_or_false, be_true_or_false, log_option = :none, action = :manage, category = :something)
84
+ @user.should_receive(:permissions).and_return( {"#{category}_#{action}" => {'0' => permission_true_or_false} })
67
85
  allowed_to_should be_true_or_false, action, category
86
+ @controller.log_permissions if log_option == :log_permissions
68
87
  end
69
88
 
70
- def allowed_to_should(be_true_or_false, action = :view, category = :something)
71
- @controller.allowed_to?(:view, :something).should be_true_or_false
89
+ def allowed_to_should(be_true_or_false, action = :manage, category = :something)
90
+ @controller.allowed_to?(:manage, :something).should be_true_or_false
72
91
  end
92
+
93
+ def current_user_exists
94
+ @user = Userish.new
95
+ @controller.should_receive(:current_user).and_return(@user)
96
+ end
97
+
73
98
  end
74
99
  end
@@ -1,23 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Permissify::Aggregate do
3
+ describe Permissify::Union do
4
4
 
5
- describe 'permissions_union' do
6
- before(:each) { new_aggregate; @union = @a.permissions_union}
7
-
8
- it 'should include keys for permissions specified (true or false) in any permissified model' do
9
- @union.keys.to_set.should == @pms.collect(&:permissions).collect(&:keys).flatten.uniq.to_set
10
- end
11
-
12
- it 'should indicate permission for a key is true if permission set to true in any permissified object permission set' do
13
- %w(p_1 p_2 p_3 p_4 p_5).each{ |permission| @union[permission]['0'].should be_true }
14
- end
15
-
16
- it 'should indicate permission for a key is false if permission not set to true in any permissified object permission set' do
17
- %w(p_6 p_7 p_8).each{ |permission| @union[permission]['0'].should be_false }
18
- end
19
- end
20
-
21
5
  describe 'allowed_to?' do
22
6
  before(:each) { new_aggregate }
23
7
 
@@ -56,12 +40,6 @@ describe Permissify::Aggregate do
56
40
  end
57
41
  end
58
42
 
59
- # TODO : work out intersection specs in corp/brand/business products phase
60
- # describe 'permissions_intersection' do
61
- # it 'should ...' do
62
- # end
63
- # end
64
-
65
43
  def new_aggregate(permissified_models = default_permissified_models)
66
44
  @a = Userish.new
67
45
  @pms = permissified_models
data/spec/spec_helper.rb CHANGED
@@ -2,7 +2,6 @@ require 'rubygems'
2
2
  require 'bundler/setup'
3
3
 
4
4
  require 'permissify'
5
- require 'permissify/ability_class'
6
5
 
7
6
  RSpec.configure do |config|
8
7
  config.treat_symbols_as_metadata_keys_with_true_values = true
@@ -22,7 +21,7 @@ class Ability
22
21
  'Corporate Users' => 'Corporate Admin',
23
22
  'Brand Users' => 'Brand Admin',
24
23
  'Merchant Users' => 'Merchant Admin',
25
- }.each{ |category, section| add_category(category, section) }
24
+ }.each{ |category, section| add_category(category, section, ['Role']) }
26
25
  end
27
26
  end
28
27
  end
@@ -47,7 +46,8 @@ class Roleish < PermissifiedModel
47
46
  end
48
47
 
49
48
  class Userish
50
- include Permissify::Aggregate
49
+ include Permissify::Union
50
+ PERMISSIFIED_ABILITY_APPLICABILITY = 'Role'
51
51
  PERMISSIFIED_ASSOCIATION = :roles
52
52
  attr_accessor :roles
53
53
  end
@@ -58,6 +58,16 @@ class UserishWithRoles
58
58
  attr_accessor :roles
59
59
  end
60
60
 
61
- class PermissifiedController
61
+ class Entityish
62
+ include Permissify::Union
63
+ PERMISSIFIED_ABILITY_APPLICABILITY = 'Product'
64
+ PERMISSIFIED_ASSOCIATION = :products
65
+ attr_accessor :products
66
+ end
67
+
68
+ class PermissifiedControllerish
62
69
  include Permissify::Controller
70
+ PERMISSIFY = { Userish::PERMISSIFIED_ABILITY_APPLICABILITY => :current_user,
71
+ Entityish::PERMISSIFIED_ABILITY_APPLICABILITY => :current_entity,
72
+ } # in lieu of 'include PermissifiedController'
63
73
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: permissify
3
3
  version: !ruby/object:Gem::Version
4
- hash: 61
4
+ hash: 59
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 17
10
- version: 0.0.17
9
+ - 18
10
+ version: 0.0.18
11
11
  platform: ruby
12
12
  authors:
13
13
  - Frederick Fix
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-06-11 00:00:00 Z
18
+ date: 2012-06-13 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rspec
@@ -102,18 +102,19 @@ files:
102
102
  - lib/generators/permissify/views/USAGE
103
103
  - lib/generators/permissify/views/views_generator.rb
104
104
  - lib/permissify/ability_class.rb
105
- - lib/permissify/aggregate.rb
105
+ - lib/permissify/common.rb
106
106
  - lib/permissify/controller.rb
107
107
  - lib/permissify/model.rb
108
108
  - lib/permissify/model_class.rb
109
109
  - lib/permissify/roles.rb
110
+ - lib/permissify/union.rb
110
111
  - lib/permissify.rb
111
112
  - spec/permissify/ability_class_spec.rb
112
- - spec/permissify/aggregate_spec.rb
113
113
  - spec/permissify/controller_spec.rb
114
114
  - spec/permissify/model_class_spec.rb
115
115
  - spec/permissify/model_spec.rb
116
116
  - spec/permissify/roles_spec.rb
117
+ - spec/permissify/union_spec.rb
117
118
  - spec/spec.opts
118
119
  - spec/spec_helper.rb
119
120
  - CHANGELOG.rdoc
@@ -1,102 +0,0 @@
1
- module Permissify
2
- module Aggregate
3
- attr_accessor :abilities
4
-
5
- def permissions_union
6
- @union ||= construct_union
7
- @working_permissions = @union
8
- end
9
-
10
- def permissions_intersection(product_permissions)
11
- @intersection ||= construct_intersection
12
- @working_permissions = @intersection
13
- end
14
-
15
- def allowed_to?(action, feature)
16
- @working_permissions ||= permissions_union
17
- (@working_permissions["#{feature}_#{action}"]['0'] == true rescue false)
18
- end
19
-
20
- def viewable?(feature); allowed_to?(:view, feature); end
21
- def createable?(feature); allowed_to?(:create, feature); end
22
- def updateable?(feature); allowed_to?(:update, feature); end
23
- def deleteable?(feature); allowed_to?(:delete, feature); end
24
- def subscribed_to?(feature); allowed_to?(:on, feature); end
25
-
26
- private
27
-
28
- def construct_union
29
- union = {}
30
- permissified_models = self.send(self.class::PERMISSIFIED_ASSOCIATION)
31
- permissions_hashes = permissified_models.collect(&:permissions)
32
- permissions_hashes.each do |permissions_hash|
33
- permissions_hash.each do |key, descriptor|
34
- descriptor ||= {'0' => false}
35
- if union[key].nil?
36
- union[key] = descriptor
37
- else
38
- arbitrate(union, descriptor, key, :max)
39
- end
40
- union[key]['0'] = (union[key]['0'] == true || descriptor['0'] == '1')
41
- end
42
- end
43
- union
44
- end
45
-
46
- def arbitrate(aggregation, other_descriptor, key, min_or_max) # assuming all permission 'args' are integers stored as strings
47
- 1.upto(other_descriptor.size-1) do |i|
48
- is = i.to_s
49
- aggregation[key][is] = [aggregation[key][is].to_i, other_descriptor[is].to_i].send(min_or_max) # .to_s ?
50
- end
51
- end
52
-
53
- # TODO : flush out intersection stuff in corp/brand/business products phase
54
- # def construct_intersection
55
- # intersection = {}
56
- # permissions_union
57
- #
58
- # # TODO : Product/Role references should be plugged-in...
59
- # # - could aggregate keep track of class names that it is included in?
60
- # # - there is a lot tangled up in here...
61
- # Ability.all_for(%w(Product Role)).each do |ability|
62
- # key = ability[:key]
63
- # descriptor = @union[key]
64
- # product_descriptor = product_permissions[key]
65
- # if permissable?(descriptor) && permissable?(product_descriptor)
66
- # intersection[key] = descriptor
67
- # arbitrate(intersection, product_descriptor, key, :min)
68
- # else
69
- # intersection[key] = null_permission
70
- # end
71
- # end
72
- #
73
- # include_permissions_unless_common_to_role_and_product('Product', product_permissions)
74
- # include_permissions_unless_common_to_role_and_product('Role', @union)
75
- # intersection
76
- # end
77
- #
78
- # def permissable?(descriptor)
79
- # descriptor && (descriptor['0'] == true || descriptor['0'] == '1')
80
- # end
81
- #
82
- # def include_permissions_unless_common_to_role_and_product(applicability_type, applicable_permissions)
83
- # Ability.all_for(applicability_type).each do |ability|
84
- # key = ability[:key]
85
- # descriptor = applicable_permissions[key]
86
- # unless @intersection.has_key?(key)
87
- # if permissable?(descriptor)
88
- # descriptor['0'] = true
89
- # @intersection[key] = descriptor
90
- # arbitrate(@intersection, descriptor, key, :min)
91
- # else
92
- # @intersection[key] = null_permission
93
- # end
94
- # end
95
- # end
96
- # end
97
- #
98
- # def null_permission
99
- # {'0' => false, '1' => 0}
100
- # end
101
- end
102
- end