permissify 0.0.17 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
@@ -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