permissify 0.0.16 → 0.0.17

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.
data/Gemfile CHANGED
@@ -43,12 +43,10 @@
43
43
  source :rubygems
44
44
 
45
45
  # gem "sqlite3"
46
- # TODO : any activerecord version dependency?
47
46
  # gem "activerecord", '~> 3.0.9', :require => "active_record"
48
- # gem "activerecord", :require => "active_record"
49
47
  # gem "with_model", "~> 0.2.5"
50
48
  # gem "meta_where"
51
49
 
52
50
  gemspec
53
51
 
54
- gem 'rspec'
52
+ gem 'rspec'
@@ -16,6 +16,11 @@ class Role < ActiveRecord::Base
16
16
  class << self
17
17
  include Permissify::ModelClass
18
18
  include SystemFixtures::Roles
19
+
20
+ def force_seed_id(table, permissions_model, id)
21
+ # not sure if this is still needed, may differ depending on db adapter (written against mysql)
22
+ ActiveRecord::Base.connection.execute "UPDATE #{table}s SET id=#{id} WHERE id=#{permissions_model.id};"
23
+ end
19
24
  end
20
25
 
21
26
  def initialize_non_permission_values
@@ -5,7 +5,7 @@ module SystemFixtures::Roles
5
5
 
6
6
  def seeded?(role); role.id <= SEEDED_ORDERED_ROLES.length; end
7
7
  def seed
8
- create_seeds :roles, SEED_SPECIFICATIONS
8
+ create_seeds SEED_SPECIFICATIONS
9
9
  Role.find(1).manage_ids = [2,3,4,5,6]
10
10
  Role.find(2).manage_ids = [2,3,4,5,6]
11
11
  Role.find(3).manage_ids = [3,4,5,6]
@@ -46,6 +46,11 @@ module Permissify
46
46
  @@permissions.keys.each{ |key| @@permissions.delete(key) if key.start_with?(key_prefix) }
47
47
  @@permissions
48
48
  end
49
+
50
+ def remove_permissions(key_prefixes)
51
+ key_prefixes.each{ |key_prefix| remove_permission(key_prefix) }
52
+ @@permissions
53
+ end
49
54
 
50
55
  def current_permissions_hash
51
56
  @@permissions
@@ -2,13 +2,34 @@ module Permissify
2
2
  module Aggregate
3
3
  attr_accessor :abilities
4
4
 
5
- def permissions_union # [integer values].max
5
+ def permissions_union
6
6
  @union ||= construct_union
7
+ @working_permissions = @union
7
8
  end
8
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
+
9
28
  def construct_union
10
29
  union = {}
11
- self.send(self.class::PERMISSIFIED_ASSOCIATION).collect(&:permissions).each do |permissions_hash|
30
+ permissified_models = self.send(self.class::PERMISSIFIED_ASSOCIATION)
31
+ permissions_hashes = permissified_models.collect(&:permissions)
32
+ permissions_hashes.each do |permissions_hash|
12
33
  permissions_hash.each do |key, descriptor|
13
34
  descriptor ||= {'0' => false}
14
35
  if union[key].nil?
@@ -16,70 +37,66 @@ module Permissify
16
37
  else
17
38
  arbitrate(union, descriptor, key, :max)
18
39
  end
19
- union[key]['0'] = (union[key]['0'] == '1' || descriptor['0'] == '1')
40
+ union[key]['0'] = (union[key]['0'] == true || descriptor['0'] == '1')
20
41
  end
21
42
  end
22
43
  union
23
44
  end
24
-
25
- def permissions_intersection(product_permissions)
26
- return @intersection if @intersection
27
- @intersection = {}
28
- permissions_union
29
-
30
- # TODO : Product/Role references should be plugged-in...
31
- # - could aggregate keep track of class names that it is included in?
32
- # - there is a lot tangled up in here...
33
- Ability.all_for(%w(Product Role)).each do |ability|
34
- key = ability[:key]
35
- descriptor = @union[key]
36
- product_descriptor = product_permissions[key]
37
- if permissable?(descriptor) && permissable?(product_descriptor)
38
- @intersection[key] = descriptor
39
- arbitrate(@intersection, product_descriptor, key, :min)
40
- else
41
- @intersection[key] = null_permission
42
- end
43
- end
44
-
45
- include_permissions_unless_common_to_role_and_product('Product', product_permissions)
46
- include_permissions_unless_common_to_role_and_product('Role', @union)
47
- @intersection
48
- end
49
-
50
- def permissable?(descriptor); descriptor && (descriptor['0'] == true || descriptor['0'] == '1'); end
51
- def subscribed_to?(feature); allowed_to?('on', feature); end
52
- def allowed_to?(action, feature); (permissions_union["#{feature}_#{action}"]['0'] == true rescue false); end
53
-
54
- def include_permissions_unless_common_to_role_and_product(applicability_type, applicable_permissions)
55
- Ability.all_for(applicability_type).each do |ability|
56
- key = ability[:key]
57
- descriptor = applicable_permissions[key]
58
- unless @intersection.has_key?(key)
59
- if permissable?(descriptor)
60
- descriptor['0'] = true
61
- @intersection[key] = descriptor
62
- arbitrate(@intersection, descriptor, key, :min)
63
- else
64
- @intersection[key] = null_permission
65
- end
66
- end
67
- end
68
- end
69
-
70
- private
45
+
71
46
  def arbitrate(aggregation, other_descriptor, key, min_or_max) # assuming all permission 'args' are integers stored as strings
72
47
  1.upto(other_descriptor.size-1) do |i|
73
- is = i.to_s; aggregation[key][is] = [aggregation[key][is].to_i, other_descriptor[is].to_i].send(min_or_max) # .to_s ?
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 ?
74
50
  end
75
51
  end
76
- def null_permission; {'0' => false, '1' => 0}; end
77
-
78
- # # TODO : need to do this differently : specify in model? discern from
79
- # def permissions_association # kinda icky
80
- # klass = self.respond_to?(:products) ? self.class : Business
81
- # @permissions_association ||= {User => :roles, klass => :products}[self.class]
82
- # @permissions_association ||= :permission_objects
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}
83
100
  # end
84
101
  end
85
102
  end
@@ -1,15 +1,24 @@
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)
6
+ end
7
+
8
+ private
9
+
4
10
  def domain_permissions
5
- return current_entity.permissions_union if current_user.nil? # public pages allow corp/brand/merchant product permissions
6
- return current_user.permissions_union unless current_entity # admin, by convention, not subscribed to any products
7
- current_user.permissions_intersection(current_entity.permissions_union)
11
+ @permissions ||= determine_domain_permissions
8
12
  end
9
13
 
10
- def allowed_to?(action, permission_category)
11
- @permissions ||= domain_permissions
12
- (@permissions["#{permission_category}_#{action}"]['0'] == true rescue false)
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
13
22
  end
14
23
 
15
24
  end
@@ -12,17 +12,23 @@ module Permissify
12
12
 
13
13
  def allows?(ability_key)
14
14
  allowed = self.permissions[ability_key];
15
- allowed && allowed['0'];
16
- end
15
+ # allowed && allowed['0']
16
+ allowed && (allowed['0'] == '1')
17
+ end
18
+
17
19
  def remove_permissions(keys)
18
- keys = [keys] if keys.class == String
20
+ keys = [keys] if keys.class != Array
19
21
  keys.each{ |k| self.permissions[k] = nil}
20
22
  self.save
21
23
  end
24
+
22
25
  def update_permissions(new_or_updated_permissions)
23
26
  self.permissions = self.permissions.merge(new_or_updated_permissions)
24
27
  self.save
25
28
  end
26
- def underscored_name_symbol; self.class.underscored_name_symbol(self.name); end
29
+
30
+ def underscored_name_symbol
31
+ self.class.underscored_name_symbol(self.name)
32
+ end
27
33
  end
28
34
  end
@@ -1,17 +1,12 @@
1
1
  module Permissify
2
2
  module ModelClass
3
- def retire_permissions_objects(retire_sql)
4
- ActiveRecord::Base.connection.execute retire_sql
5
- end
6
-
7
- def create_seeds(table_name, seed_specifications)
8
- @model_class_seed_specifications = seed_specifications
3
+
4
+ def create_seeds(seed_specifications)
9
5
  seed_specifications.each do |id, name|
10
6
  permissions_model = locate(id, name)
11
- permissions_model.permissions = send("#{underscored_name_symbol(name)}_permissions")
7
+ permissions_model.permissions = send("#{underscored_name_symbol(name)}_permissions") # interface methods needed for each seeded model
12
8
  permissions_model.save
13
9
  end
14
- ActiveRecord::Base.connection.execute "ALTER TABLE #{table_name} AUTO_INCREMENT = 101;"
15
10
  end
16
11
 
17
12
  def create_with_id(table, id, name)
@@ -20,17 +15,18 @@ module Permissify
20
15
  permissions_model.name = name
21
16
  permissions_model.permissions = permissions
22
17
  permissions_model.save
23
- ActiveRecord::Base.connection.execute "UPDATE #{table}s SET id=#{id} WHERE id=#{permissions_model.id};"
18
+ force_seed_id(table, permissions_model, id) # interface method : force_seed_id
24
19
  find(id)
25
20
  end
26
21
 
27
22
  def locate(id, name)
28
- model_with_id = find_by_id(id)
29
- model_with_id ||= send("create_#{underscored_name_symbol(name)}")
23
+ model_with_id = find_by_id(id) # interface method : ActiveRecord::Base.find_by_id
24
+ model_with_id ||= send("create_#{underscored_name_symbol(name)}") # interface methods needed for each seeded model
30
25
  end
31
26
 
32
27
  def underscored_name_symbol(name)
33
- name.to_s.downcase.gsub('-','_').gsub(':','').gsub(' ',' ').gsub(' ','_')
28
+ name.to_s.downcase.gsub(':','').gsub('-','_').gsub(' ','_').gsub(/__*/,'_')
34
29
  end
30
+
35
31
  end
36
32
  end
@@ -1,24 +1,42 @@
1
1
  module Permissify::Roles
2
2
  include Permissify::Aggregate
3
-
4
- def primary_domain_type; sorted_domain_types.first; end
5
- def primary_role_name; role_list(:description).sort.first; end
6
- def sorted_domain_types; role_list(:domain_type).sort; end
7
- def manages_roles; role_list(:manages_roles); end
8
- def manages_role_names; sorted_role_names(manages_roles); end
9
- def role_list(collection_method); roles.collect(&collection_method).flatten.uniq; end
10
-
11
- def can_create_and_modify(users, app_instance) # TODO : unit test for this
12
- role_names_that_this_user_can_manage = manages_role_names
13
- # 2 ways to go here : must be able to manage *all* or *any* of a user's roles.
14
- # Chose *all* to prevent lower ranking users from demoting higher ranking users
15
- users.select do |u|
16
- u_role_names = sorted_role_names(u.roles)
17
- ! u_role_names.blank? && (role_names_that_this_user_can_manage & u_role_names) == u_role_names
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
7
+
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)
18
16
  end
19
- users.delete_if{|u| !u.instances.include?(app_instance)}
20
- return users
17
+ nil # unrecognized domain_type value(s)
21
18
  end
22
19
 
23
- def sorted_role_names(roles); roles.collect(&:name).sort; end
20
+ # uncomment/reimplement methods as needed for example app/as more light shines...
21
+
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
42
  end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+ describe Permissify::Aggregate do
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
+ describe 'allowed_to?' do
22
+ before(:each) { new_aggregate }
23
+
24
+ it 'should return true when permission is set in a permissified model permission set' do
25
+ (1..5).each{ |action| @a.allowed_to?(action.to_s, 'p').should be_true }
26
+ end
27
+
28
+ it 'should return false when permission is set to false in all permissified model permission sets where it is present or not present in any permission set' do
29
+ (6..9).each{ |action| @a.allowed_to?(action.to_s, 'p').should be_false }
30
+ end
31
+ end
32
+
33
+ [ %w(subscribed_to? product1_on product1),
34
+ %w(viewable? thing_view thing),
35
+ %w(createable? thing_create thing),
36
+ %w(updateable? thing_update thing),
37
+ %w(deleteable? thing_delete thing),
38
+ ].each do |method_name, permission_key, method_arg|
39
+ describe "#{method_name}" do
40
+ it "should be true when permission for '#{permission_key}' is specified as true" do
41
+ method_should(be_true, {permission_key => {'0' => '1'}}, method_name, method_arg)
42
+ end
43
+
44
+ it "should be false when permission for '#{permission_key}' specified as false" do
45
+ method_should(be_false, {permission_key => {'0' => '0'}}, method_name, method_arg)
46
+ end
47
+
48
+ it "should be false when permission for '#{permission_key}' not specified" do
49
+ method_should(be_false, {}, method_name, method_arg)
50
+ end
51
+
52
+ def method_should(be_true_or_false, permissions, method_name, method_arg)
53
+ new_aggregate( [new_permissified_model( permissions )] )
54
+ @a.send(method_name, method_arg).should be_true_or_false
55
+ end
56
+ end
57
+ end
58
+
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
+ def new_aggregate(permissified_models = default_permissified_models)
66
+ @a = Userish.new
67
+ @pms = permissified_models
68
+ @a.roles = @pms
69
+ end
70
+
71
+ def default_permissified_models
72
+ [ new_permissified_model( {'p_1' => {'0' => '0'}, 'p_2' => {'0' => '1'}, 'p_3' => {'0' => '1'}, 'p_6' => {'0' => '0'}} ),
73
+ new_permissified_model( {'p_1' => {'0' => '1'}, 'p_2' => {'0' => '0'}, 'p_4' => {'0' => '1'}, 'p_7' => {'0' => '0'}} ),
74
+ new_permissified_model( {'p_1' => {'0' => '0'}, 'p_2' => {'0' => '0'}, 'p_5' => {'0' => '1'}, 'p_8' => {'0' => '0'}} )
75
+ ]
76
+ end
77
+
78
+ def new_permissified_model(permissions)
79
+ pm = PermissifiedModel.new
80
+ pm.permissions = permissions
81
+ pm
82
+ end
83
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ describe Permissify::Controller do
4
+ before(:each) { @controller = PermissifiedController.new }
5
+
6
+ describe 'allowed_to?' do
7
+ describe 'and no current entity' do
8
+ before(:each) { @controller.should_receive(:current_entity).and_return(nil) }
9
+
10
+ it 'should return false when no current user' do
11
+ @controller.should_receive(:current_user).and_return(nil)
12
+ allowed_to_should be_false
13
+ end
14
+
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
22
+ category_action_permission_causes_allowed_to_be true, be_true
23
+ end
24
+
25
+ it 'should return false when current user does not have permission for category action' do
26
+ category_action_permission_causes_allowed_to_be false, be_false
27
+ end
28
+ end
29
+ end
30
+
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')
35
+ end
36
+
37
+ it 'should return false when current entity does not have permission for category action' do
38
+ pending('products phase')
39
+ end
40
+ end
41
+
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
47
+
48
+ it 'should return false when current user does not have permission for category action' do
49
+ pending('products phase')
50
+ end
51
+ 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
+
58
+ it 'should return false when current user does not have permission for category action' do
59
+ pending('products phase')
60
+ end
61
+ end
62
+ end
63
+ end
64
+
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} })
67
+ allowed_to_should be_true_or_false, action, category
68
+ end
69
+
70
+ def allowed_to_should(be_true_or_false, action = :view, category = :something)
71
+ @controller.allowed_to?(:view, :something).should be_true_or_false
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ describe Permissify::ModelClass do
4
+ describe 'create_seeds' do
5
+ it 'should locate, set permissions and save each specified seed' do
6
+ (seed_specifications = [ [21, 'seeded model name1'], [81, 'seeded model name 2'] ]).each do |id, name|
7
+ PermissifiedModel.should_receive(:locate).with(id, name).and_return(located_model = mock)
8
+ app_implemented_permissions_method = "#{name.gsub(' ','_')}_permissions"
9
+ PermissifiedModel.should_receive(app_implemented_permissions_method).and_return(:name_permissions)
10
+ located_model.should_receive(:permissions=).with(:name_permissions)
11
+ located_model.should_receive(:save)
12
+ end
13
+ PermissifiedModel.create_seeds seed_specifications
14
+ end
15
+ end
16
+
17
+ describe 'create_with_id' do
18
+ it 'should create a new object, set its name, permissions, save it, force its id and then find it' do
19
+ PermissifiedModel.should_receive(:name_permissions).and_return(:permissions_for_name)
20
+ PermissifiedModel.should_receive(:new).and_return(mocked_permissions_model = mock())
21
+ mocked_permissions_model.should_receive(:name=).with(:name)
22
+ mocked_permissions_model.should_receive(:permissions=).with(:permissions_for_name)
23
+ mocked_permissions_model.should_receive(:save)
24
+ PermissifiedModel.should_receive(:force_seed_id).with(:table, mocked_permissions_model, :id)
25
+ PermissifiedModel.should_receive(:find).with(:id).and_return(:model_returned_from_find)
26
+ PermissifiedModel.create_with_id(:table, :id, :name).should == :model_returned_from_find
27
+ end
28
+ end
29
+
30
+ describe 'locate' do
31
+ it 'should return model corresponding to input id when model with id exists' do
32
+ mock_find_by_id :model_from_find_by_id
33
+ PermissifiedModel.locate(:input_model_id, :input_model_id_name).should == :model_from_find_by_id
34
+ end
35
+
36
+ it 'should return response from app-implemented "create_input_model_id_name"' do
37
+ mock_find_by_id nil
38
+ PermissifiedModel.should_receive(:create_input_model_id_name).and_return(:model_from_create_input_model_id_name)
39
+ PermissifiedModel.locate(:input_model_id, :input_model_id_name).should == :model_from_create_input_model_id_name
40
+ end
41
+
42
+ def mock_find_by_id(mocked_return)
43
+ PermissifiedModel.should_receive(:find_by_id).with(:input_model_id).and_return(mocked_return)
44
+ end
45
+ end
46
+
47
+ describe 'underscored_name_symbol' do
48
+ it 'should return a string' do
49
+ PermissifiedModel.underscored_name_symbol(:symbol).class.name.should == 'String'
50
+ end
51
+
52
+ it 'should return a downcased version of input' do
53
+ PermissifiedModel.underscored_name_symbol(:SYMBOL).should == 'symbol'
54
+ end
55
+
56
+ it 'should squish whitespace into a single underscore' do
57
+ PermissifiedModel.underscored_name_symbol(' squish it ').should == '_squish_it_'
58
+ end
59
+
60
+ it 'should convert dashes to underscores' do
61
+ PermissifiedModel.underscored_name_symbol('-dash--to---underscore----').should == '_dash_to_underscore_'
62
+ end
63
+
64
+ it 'should remove colons' do
65
+ PermissifiedModel.underscored_name_symbol(':colons:::be:gone:::').should == 'colonsbegone'
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ describe Permissify::Model do
4
+ describe 'establish_from_permissions_model' do
5
+ it 'should set from_permissions_model to nil when from is nil' do
6
+ from_permissions_model_should_be nil
7
+ end
8
+
9
+ it 'should set from_permissions_model to find response when from is set' do
10
+ PermissifiedModel.should_receive(:find).with(:with_from_value).and_return(:find_response)
11
+ from_permissions_model_should_be(:find_response, :with_from_value)
12
+ end
13
+
14
+ def from_permissions_model_should_be(expected_from_permissions_model, from_value = nil)
15
+ new_model
16
+ @pm.from = from_value
17
+ @pm.establish_from_permissions_model
18
+ @pm.from_permissions_model.should == expected_from_permissions_model
19
+ end
20
+ end
21
+
22
+ describe 'initialize_permissions' do
23
+ before(:each) { new_model }
24
+
25
+ it 'should set permissions to empty hash when from is not set' do
26
+ permissions_should_be({}, nil)
27
+ end
28
+
29
+ it 'should set permissions from model that can be found with from value' do
30
+ other_permissions_model = mock(:permissions => :other_permissions)
31
+ @pm.should_receive(:establish_from_permissions_model).and_return(other_permissions_model)
32
+ permissions_should_be(:other_permissions, :with_from_value)
33
+ end
34
+
35
+ def permissions_should_be(expected_permissions, from_value = nil)
36
+ @pm.from = from_value
37
+ @pm.initialize_permissions
38
+ @pm.permissions.should == expected_permissions
39
+ end
40
+ end
41
+
42
+ describe 'allows?' do
43
+ it 'should return false when ability key is not present in permissions' do
44
+ expect_allows({}, be_false)
45
+ end
46
+
47
+ it 'should return false when ability key is present in permissions but does not have a value corresponding to key \'0\'' do
48
+ expect_allows({'permission' => {'1' => 'notzero'}}, be_false)
49
+ end
50
+
51
+ [nil, 0, '0', 1].each do |value_that_evaluates_to_false|
52
+ it "should return false when ability key is present in permissions, and value corresponding to key '0' is #{value_that_evaluates_to_false} (#{value_that_evaluates_to_false.class.name})" do
53
+ expect_allows({'permission' => {'0' => value_that_evaluates_to_false}}, be_false)
54
+ end
55
+ end
56
+
57
+ it "should return true when ability key is present in permissions, and value corresponding to key '0' is '1'" do
58
+ expect_allows({'permission' => {'0' => '1'}}, be_true)
59
+ end
60
+
61
+ def expect_allows(permission_hash_value, be_true_or_false)
62
+ new_model
63
+ @pm.permissions = permission_hash_value
64
+ @pm.allows?('permission').should be_true_or_false
65
+ end
66
+ end
67
+
68
+ describe 'remove_permissions' do
69
+ it 'should set permissions value associated with input key(s) to nil' do
70
+ new_model
71
+ @pm.permissions = {:key1 => 1, :key2 => 1}
72
+ @pm.should_receive(:save)
73
+ @pm.remove_permissions(:key1)
74
+ @pm.permissions.should == {:key1 => nil, :key2 => 1}
75
+ end
76
+ end
77
+
78
+ describe 'update_permissions' do
79
+ before(:each) { new_model }
80
+ it 'should save merged permissions' do
81
+ @pm.should_receive(:permissions).and_return(current_permissions = {})
82
+ current_permissions.should_receive(:merge).with(:new_permissions).and_return(:merged_permissions)
83
+ @pm.should_receive(:permissions=).with(:merged_permissions)
84
+ @pm.should_receive(:save)
85
+ @pm.update_permissions(:new_permissions)
86
+ end
87
+ end
88
+
89
+ describe 'underscored_name_symbol' do
90
+ before(:each) { new_model }
91
+
92
+ it 'should invoke class underscored_name_symbol method with model name' do
93
+ PermissifiedModel.should_receive(:underscored_name_symbol).with(@pm.name).and_return(:response_from_class_underscored_name_symbol_method)
94
+ @pm.underscored_name_symbol.should == :response_from_class_underscored_name_symbol_method
95
+ end
96
+ end
97
+
98
+ def new_model
99
+ @pm = PermissifiedModel.new
100
+ @pm.name = 'model name'
101
+ end
102
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe Permissify::Roles do
4
+
5
+ describe 'primary_domain_type' do
6
+ ranked_domain_types = Roleish::DOMAIN_TYPES
7
+ n = ranked_domain_types.length - 1
8
+ (0..n).each do |i|
9
+ subset_of_ranked_domain_types = ranked_domain_types[i..n]
10
+ expected_primary_domain_type = subset_of_ranked_domain_types[0]
11
+ it "should return '#{expected_primary_domain_type}' when represented domain types are #{subset_of_ranked_domain_types.join(',')}" do
12
+ new_user_with_roles( subset_of_ranked_domain_types.collect{|dt| new_role(dt) }.reverse )
13
+ @u.primary_domain_type.should == expected_primary_domain_type
14
+ end
15
+ end
16
+ end
17
+
18
+ def new_user_with_roles(roles)
19
+ @u = UserishWithRoles.new
20
+ @roles = roles
21
+ @u.roles = @roles
22
+ end
23
+
24
+ def new_role(domain_type)
25
+ pm = Roleish.new
26
+ pm.domain_type = domain_type
27
+ pm
28
+ end
29
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,9 +1,3 @@
1
- # This file was generated by the `rspec --init` command. Conventionally, all
2
- # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
- # Require this file using `require "spec_helper.rb"` to ensure that it is only
4
- # loaded once.
5
- #
6
- # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
1
  require 'rubygems'
8
2
  require 'bundler/setup'
9
3
 
@@ -38,3 +32,32 @@ class NoSeedAbility
38
32
  include Permissify::AbilityClass
39
33
  end
40
34
  end
35
+
36
+ class PermissifiedModel
37
+ include Permissify::Model
38
+ attr_accessor :name, :permissions
39
+ class << self
40
+ include Permissify::ModelClass
41
+ end
42
+ end
43
+
44
+ class Roleish < PermissifiedModel
45
+ DOMAIN_TYPES = %w(Admin Dealer Corporate Brand Merchant)
46
+ attr_accessor :domain_type
47
+ end
48
+
49
+ class Userish
50
+ include Permissify::Aggregate
51
+ PERMISSIFIED_ASSOCIATION = :roles
52
+ attr_accessor :roles
53
+ end
54
+
55
+ class UserishWithRoles
56
+ include Permissify::Roles
57
+ PERMISSIFIED_ASSOCIATION = :roles
58
+ attr_accessor :roles
59
+ end
60
+
61
+ class PermissifiedController
62
+ include Permissify::Controller
63
+ 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: 63
4
+ hash: 61
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 16
10
- version: 0.0.16
9
+ - 17
10
+ version: 0.0.17
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-06 00:00:00 Z
18
+ date: 2012-06-11 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rspec
@@ -109,6 +109,11 @@ files:
109
109
  - lib/permissify/roles.rb
110
110
  - lib/permissify.rb
111
111
  - spec/permissify/ability_class_spec.rb
112
+ - spec/permissify/aggregate_spec.rb
113
+ - spec/permissify/controller_spec.rb
114
+ - spec/permissify/model_class_spec.rb
115
+ - spec/permissify/model_spec.rb
116
+ - spec/permissify/roles_spec.rb
112
117
  - spec/spec.opts
113
118
  - spec/spec_helper.rb
114
119
  - CHANGELOG.rdoc