cantango 0.8.9.5 → 0.9.3.2

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.
Files changed (84) hide show
  1. data/README.textile +35 -7
  2. data/VERSION +1 -1
  3. data/cantango.gemspec +39 -12
  4. data/lib/cantango.rb +4 -3
  5. data/lib/cantango/ability.rb +17 -21
  6. data/lib/cantango/ability/cache/key.rb +32 -4
  7. data/lib/cantango/ability/cache/rules_cache.rb +9 -2
  8. data/lib/cantango/ability/cache_helpers.rb +1 -7
  9. data/lib/cantango/ability/engine_helpers.rb +27 -0
  10. data/lib/cantango/ability_executor.rb +41 -0
  11. data/lib/cantango/api/user/ability.rb +8 -12
  12. data/lib/cantango/api/user/session.rb +2 -1
  13. data/lib/cantango/api/user_account.rb +2 -2
  14. data/lib/cantango/api/user_account/ability.rb +19 -14
  15. data/lib/cantango/api/user_account/can.rb +8 -0
  16. data/lib/cantango/api/user_account/session.rb +33 -0
  17. data/lib/cantango/cached_ability.rb +26 -0
  18. data/lib/cantango/configuration.rb +3 -3
  19. data/lib/cantango/configuration/ability.rb +1 -0
  20. data/lib/cantango/configuration/candidate_registry.rb +51 -0
  21. data/lib/cantango/configuration/categories.rb +2 -2
  22. data/lib/cantango/configuration/engines.rb +7 -3
  23. data/lib/cantango/configuration/engines/permission.rb +5 -0
  24. data/lib/cantango/configuration/engines/permit.rb +1 -0
  25. data/lib/cantango/configuration/engines/user_ac.rb +19 -0
  26. data/lib/cantango/configuration/guest.rb +1 -1
  27. data/lib/cantango/configuration/modes.rb +21 -0
  28. data/lib/cantango/configuration/permits.rb +1 -1
  29. data/lib/cantango/configuration/role_groups.rb +1 -2
  30. data/lib/cantango/configuration/user_accounts.rb +1 -1
  31. data/lib/cantango/configuration/users.rb +1 -1
  32. data/lib/cantango/engine.rb +40 -0
  33. data/lib/cantango/helpers.rb +1 -1
  34. data/lib/cantango/helpers/debug.rb +9 -0
  35. data/lib/cantango/model.rb +6 -0
  36. data/lib/cantango/model/filter.rb +102 -0
  37. data/lib/cantango/model/scope.rb +57 -0
  38. data/lib/cantango/permission_engine.rb +14 -3
  39. data/lib/cantango/permission_engine/loader/base.rb +1 -6
  40. data/lib/cantango/permission_engine/loader/permissions.rb +10 -16
  41. data/lib/cantango/permission_engine/store.rb +1 -7
  42. data/lib/cantango/permission_engine/yaml_store.rb +3 -10
  43. data/lib/cantango/permit_engine.rb +17 -4
  44. data/lib/cantango/permit_engine/builder/base.rb +3 -1
  45. data/lib/cantango/permit_engine/executor/abstract.rb +2 -0
  46. data/lib/cantango/permit_engine/executor/base.rb +1 -1
  47. data/lib/cantango/permit_engine/factory.rb +5 -3
  48. data/lib/cantango/permit_engine/finder.rb +4 -6
  49. data/lib/cantango/permit_engine/util.rb +1 -1
  50. data/lib/cantango/permits/permit.rb +25 -0
  51. data/lib/cantango/permits/role_group_permit/builder.rb +23 -7
  52. data/lib/cantango/permits/role_permit.rb +1 -2
  53. data/lib/cantango/rails/helpers/rest_helper.rb +3 -2
  54. data/lib/cantango/user_ac_engine.rb +40 -0
  55. data/lib/cantango/user_ac_engine/executor.rb +59 -0
  56. data/lib/cantango/users/macros.rb +3 -0
  57. data/lib/cantango/users/user.rb +1 -1
  58. data/lib/cantango/users/user_account.rb +1 -1
  59. data/lib/generators/cantango/permission/permission_generator.rb +43 -0
  60. data/spec/active_record/migrations/008_create_permissions.rb +10 -0
  61. data/spec/cantango/ability_executor/cached_only_spec.rb +76 -0
  62. data/spec/cantango/ability_executor_spec.rb +75 -0
  63. data/spec/cantango/api/attributes_spec.rb +2 -1
  64. data/spec/cantango/api/current_user_accounts.rb +5 -1
  65. data/spec/cantango/api/user/ability_api_spec.rb +17 -4
  66. data/spec/cantango/api/user/can_api_spec.rb +9 -5
  67. data/spec/cantango/api/user/scope_api_spec.rb +15 -7
  68. data/spec/cantango/api/user_account/ability_api_spec.rb +12 -5
  69. data/spec/cantango/api/user_account/can_api_spec.rb +8 -4
  70. data/spec/cantango/cached_ability_spec.rb +0 -0
  71. data/spec/cantango/model/filter_spec.rb +168 -0
  72. data/spec/cantango/model/scope_spec.rb +107 -0
  73. data/spec/cantango/permission_engine/loader/permissions/{cantango_permissions_loader.rb → cantango_permissions_loader_spec.rb} +0 -0
  74. data/spec/cantango/permission_engine/loader/permissions/shared.rb +2 -2
  75. data/spec/cantango/permission_engine/yaml_store_spec.rb +0 -1
  76. data/spec/cantango/permit_engine/role_group_permit_spec.rb +2 -2
  77. data/spec/cantango/permits/permit_spec.rb +2 -2
  78. data/spec/cantango/rules_spec.rb +6 -6
  79. data/spec/cantango/user_ac_engine_spec.rb +53 -0
  80. data/spec/fixtures/config/cantango_permissions.yml +49 -0
  81. data/spec/fixtures/models/permission.rb +12 -0
  82. data/spec/fixtures/models/user.rb +8 -0
  83. data/spec/generators/cantango/permission_generator_spec.rb +44 -0
  84. metadata +59 -35
@@ -0,0 +1,10 @@
1
+ class CreatePermissions < ActiveRecord::Migration
2
+ def change
3
+ create_table :permissions do |t|
4
+ t.integer :user_id, :thing_id
5
+ t.string :thing_type, :action
6
+ t.timestamps
7
+ end
8
+ end
9
+ end
10
+
@@ -0,0 +1,76 @@
1
+ require 'rspec'
2
+ require 'cantango'
3
+ # require 'simple_roles'
4
+ require 'fixtures/models'
5
+ require 'cantango/rspec'
6
+
7
+ def config_folder
8
+ File.dirname(__FILE__)+ "/../fixtures/config/"
9
+ end
10
+
11
+ CanTango.configure do |config|
12
+ config.clear!
13
+ end
14
+ # CanTango.debug!
15
+
16
+ class User
17
+ tango_user
18
+ include_and_extend SimpleRoles
19
+ end
20
+
21
+ class AdminRolePermit < CanTango::RolePermit
22
+ def initialize ability
23
+ super
24
+ end
25
+
26
+ protected
27
+
28
+ def static_rules
29
+ can :read, Article
30
+ end
31
+
32
+ module Cached
33
+ def permit_rules
34
+ can :edit, Article
35
+ can :delete, Article
36
+ end
37
+ end
38
+ end
39
+
40
+ module CanTango
41
+ class CachedAbility
42
+ def permit_rules
43
+ can :read, Post
44
+ end
45
+ end
46
+ end
47
+
48
+ describe CanTango::AbilityExecutor do
49
+ context 'cached only' do
50
+ before do
51
+ CanTango.configure.ability.mode = :cache
52
+
53
+ @user = User.new 'admin', 'admin@mail.ru', :role => 'admin'
54
+ @abil = CanTango::AbilityExecutor.new @user
55
+ end
56
+
57
+ subject { CanTango::AbilityExecutor.new @user }
58
+
59
+ describe 'config cache' do
60
+ specify { CanTango.configure.ability.modes.should == [:cache] }
61
+ end
62
+
63
+ describe 'engines_on?' do
64
+ specify { subject.engines_on?.should be_true }
65
+ end
66
+
67
+ its(:cached_rules) { should_not be_empty }
68
+ its(:non_cached_rules) { should be_empty }
69
+
70
+ describe 'rules contain only non-cached rules' do
71
+ specify { subject.rules.size.should == @abil.cached_rules.size }
72
+ specify { subject.rules.size.should == 4 }
73
+ end
74
+ end
75
+ end
76
+
@@ -0,0 +1,75 @@
1
+ require 'rspec'
2
+ require 'cantango'
3
+ # require 'simple_roles'
4
+ require 'fixtures/models'
5
+ require 'cantango/rspec'
6
+
7
+ def config_folder
8
+ File.dirname(__FILE__)+ "/../fixtures/config/"
9
+ end
10
+
11
+ CanTango.configure do |config|
12
+ config.clear!
13
+ end
14
+ # CanTango.debug!
15
+
16
+ class User
17
+ tango_user
18
+ include_and_extend SimpleRoles
19
+ end
20
+
21
+ class AdminRolePermit < CanTango::RolePermit
22
+ def initialize ability
23
+ super
24
+ end
25
+
26
+ protected
27
+
28
+ def static_rules
29
+ can :read, Article
30
+ end
31
+
32
+ module Cached
33
+ def permit_rules
34
+ can :edit, Article
35
+ can :delete, Article
36
+ end
37
+ end
38
+ end
39
+
40
+ module CanTango
41
+ class Ability
42
+ def permit_rules
43
+ can :read, Post
44
+ end
45
+ end
46
+ end
47
+
48
+ describe CanTango::AbilityExecutor do
49
+ context 'non-cached only' do
50
+ before do
51
+ CanTango.configure.ability.mode = :no_cache
52
+
53
+ @user = User.new 'admin', 'admin@mail.ru', :role => 'admin'
54
+ @abil = CanTango::AbilityExecutor.new @user
55
+ end
56
+
57
+ subject { CanTango::AbilityExecutor.new @user }
58
+
59
+ describe 'config no_cache' do
60
+ specify { CanTango.configure.ability.modes.should == [:no_cache] }
61
+ end
62
+
63
+ describe 'engines_on?' do
64
+ specify { subject.engines_on?.should be_true }
65
+ end
66
+
67
+ its(:cached_rules) { should be_empty }
68
+ its(:non_cached_rules) { should_not be_empty }
69
+
70
+ describe 'rules contain only non-cached rules' do
71
+ specify { subject.rules.size.should == @abil.non_cached_rules.size }
72
+ specify { subject.rules.size.should == 2 }
73
+ end
74
+ end
75
+ end
@@ -4,7 +4,8 @@ require 'fixtures/models'
4
4
  require 'cantango/api/current_users'
5
5
  require 'cantango/configuration/engines/store_engine_shared'
6
6
 
7
- CanTango.config.users.register :user, :admin
7
+ CanTango.config.users.register :user, User
8
+ CanTango.config.users.register :admin, Admin
8
9
 
9
10
  class Context
10
11
  include CanTango::Api::User::Ability
@@ -1,7 +1,11 @@
1
1
  require 'cantango/api/current_users'
2
2
 
3
3
  module CurrentUserAccounts
4
- include CurrentUsers
4
+ include ::CurrentUsers
5
+
6
+ def self.included(base)
7
+ base.extend ::CurrentUsers
8
+ end
5
9
 
6
10
  def current_user_account
7
11
  ::UserAccount.new(current_user, :roles => [:user])
@@ -1,16 +1,29 @@
1
1
  require 'rspec'
2
2
  require 'cantango'
3
+ require 'simple_roles'
3
4
  require 'fixtures/models'
4
5
  require 'cantango/api/current_users'
5
- require 'cantango/configuration/engines/store_engine_shared'
6
+ # require 'cantango/configuration/engines/store_engine_shared'
6
7
 
7
- CanTango.config.users.register :user, :admin
8
+ class User
9
+ include_and_extend SimpleRoles
10
+ end
11
+
12
+ class Admin < User
13
+ end
14
+
15
+ CanTango.configure do |config|
16
+ config.users.register :user, User
17
+ config.users.register :admin, Admin
18
+
19
+ config.cache_engine.set :off
20
+ config.permit_engine.set :on
21
+ end
8
22
 
9
23
  class Context
10
24
  include CanTango::Api::User::Ability
11
25
 
12
- include CurrentUsers
13
- extend ::CurrentUsers
26
+ include_and_extend ::CurrentUsers
14
27
  end
15
28
 
16
29
  describe CanTango::Api::User::Ability do
@@ -7,16 +7,21 @@ require 'cantango/api/current_users'
7
7
 
8
8
  class User
9
9
  include CanTango::Users::Masquerade
10
-
11
10
  include_and_extend SimpleRoles
12
11
  end
13
12
 
13
+ class Admin < User
14
+ end
15
+
14
16
  CanTango.configure do |config|
15
- config.users.register :user, :admin
17
+ config.users.register :user, User
18
+ config.users.register :admin, Admin
19
+
16
20
  config.cache_engine.set :off
17
21
  config.permit_engine.set :on
18
22
  end
19
23
 
24
+ # puts "#{CanTango.config.users.registered_classes} : #{CanTango.config.users.registered}"
20
25
 
21
26
  class UserRolePermit < CanTango::RolePermit
22
27
  def initialize ability
@@ -43,8 +48,7 @@ end
43
48
  class Context
44
49
  include CanTango::Api::User::Can
45
50
 
46
- include ::CurrentUsers
47
- extend ::CurrentUsers
51
+ include_and_extend ::CurrentUsers
48
52
  end
49
53
 
50
54
  describe CanTango::Api::User::Can do
@@ -94,7 +98,7 @@ describe CanTango::Api::User::Can do
94
98
 
95
99
  describe 'admin masquerades as user' do
96
100
  before do
97
- Context.current_admin.masquerade_as Context.current_user
101
+ Context.new.current_admin.masquerade_as Context.new.current_user
98
102
  end
99
103
 
100
104
  # admin masquerading as user can do same as user
@@ -1,22 +1,30 @@
1
1
  require 'rspec'
2
2
  require 'cantango'
3
+ require 'simple_roles'
3
4
  require 'fixtures/models'
4
5
  require 'cantango/api/current_users'
6
+ # require 'cantango/configuration/engines/store_engine_shared'
5
7
 
6
- require 'cantango/configuration/engines/store_engine_shared'
8
+ CanTango.configure do |config|
9
+ config.users.register :user, User
10
+ config.users.register :admin, Admin
7
11
 
8
- CanTango.config.users.register :user, :admin
12
+ config.cache_engine.set :off
13
+ config.permit_engine.set :on
14
+ end
15
+
16
+ # puts "#{CanTango.config.users.registered_classes} : #{CanTango.config.users.registered}"
9
17
 
10
18
  class User
11
19
  include CanTango::Users::Masquerade
20
+ include_and_extend ::SimpleRoles
12
21
  end
13
22
 
14
23
  class Context
15
24
  include CanTango::Api::User::Ability
16
25
  include CanTango::Api::User::Scope
17
26
 
18
- include ::CurrentUsers
19
- extend ::CurrentUsers
27
+ include_and_extend ::CurrentUsers
20
28
  end
21
29
 
22
30
  describe CanTango::Api::User::Scope do
@@ -24,7 +32,7 @@ describe CanTango::Api::User::Scope do
24
32
 
25
33
  describe 'scope_user' do
26
34
  before do
27
- Context.current_admin.masquerade_as Context.current_user
35
+ subject.current_admin.masquerade_as subject.current_user
28
36
  end
29
37
 
30
38
  specify do
@@ -43,8 +51,8 @@ describe CanTango::Api::User::Scope do
43
51
 
44
52
  describe 'real_user' do
45
53
  before do
46
- Context.current_user.masquerade_as Context.current_admin
47
- end
54
+ subject.current_user.masquerade_as subject.current_admin
55
+ end
48
56
 
49
57
  specify do
50
58
  subject.real_user(:user) do |user|
@@ -2,16 +2,23 @@ require 'rspec'
2
2
  require 'cantango'
3
3
  require 'fixtures/models'
4
4
  require 'cantango/api/current_user_accounts'
5
- require 'cantango/configuration/engines/store_engine_shared'
5
+ # require 'cantango/configuration/engines/store_engine_shared'
6
6
 
7
- CanTango.config.users.register :user, :admin
8
- CanTango.config.user_accounts.register :user, :admin
7
+ CanTango.configure do |config|
8
+ config.users.register :user, User
9
+ config.users.register :admin, Admin
10
+
11
+ config.user_accounts.register :user, UserAccount
12
+ config.user_accounts.register :admin, AdminAccount
13
+
14
+ config.cache_engine.set :off
15
+ config.permit_engine.set :on
16
+ end
9
17
 
10
18
  class Context
11
19
  include CanTango::Api::UserAccount::Ability
12
20
 
13
- include CurrentUserAccounts
14
- extend CurrentUserAccounts
21
+ include_and_extend ::CurrentUserAccounts
15
22
  end
16
23
 
17
24
  describe CanTango::Api::UserAccount::Ability do
@@ -7,9 +7,14 @@ require 'cantango/api/current_user_accounts'
7
7
  class User
8
8
  include_and_extend SimpleRoles
9
9
  end
10
+
10
11
  CanTango.configure do |config|
11
- config.users.register :user, :admin
12
- config.user_accounts.register :user, :admin
12
+ config.users.register :user, User
13
+ config.users.register :admin, Admin
14
+
15
+ config.user_accounts.register :user, UserAccount
16
+ config.user_accounts.register :admin, AdminAccount
17
+
13
18
  config.cache_engine.set :off
14
19
  config.permit_engine.set :on
15
20
  end
@@ -35,8 +40,7 @@ end
35
40
  class Context
36
41
  include CanTango::Api::UserAccount::Can
37
42
 
38
- include ::CurrentUserAccounts
39
- extend ::CurrentUserAccounts
43
+ include_and_extend ::CurrentUserAccounts
40
44
  end
41
45
 
42
46
  describe CanTango::Api::UserAccount::Can do
File without changes
@@ -0,0 +1,168 @@
1
+ require 'rspec'
2
+ require 'cantango'
3
+ require 'simple_roles'
4
+ require 'fixtures/models'
5
+ require 'cantango/api/current_users'
6
+ require 'cantango/api/current_user_accounts'
7
+
8
+ class User
9
+ include_and_extend SimpleRoles
10
+ end
11
+
12
+ class Admin < User
13
+ end
14
+
15
+ class UserAccount
16
+ tango_account # register
17
+ include_and_extend SimpleRoles
18
+ end
19
+
20
+
21
+ class AdminAccount
22
+ tango_account
23
+ include_and_extend SimpleRoles
24
+ end
25
+
26
+
27
+ CanTango.configure do |config|
28
+ config.users.register :user, User
29
+ config.users.register :admin, Admin
30
+
31
+ config.cache_engine.set :off
32
+ config.permit_engine.set :on
33
+ end
34
+
35
+ class Context
36
+ include CanTango::Api::User::Ability
37
+
38
+ include_and_extend ::CurrentUsers
39
+ include_and_extend ::CurrentUserAccounts
40
+ end
41
+
42
+ class UserRolePermit < CanTango::RolePermit
43
+ def initialize ability
44
+ super
45
+ end
46
+
47
+ def permit_rules
48
+ can :edit, Project
49
+ cannot :publish, Project
50
+ end
51
+ end
52
+
53
+ class AdminRolePermit < CanTango::RolePermit
54
+ def initialize ability
55
+ super
56
+ end
57
+
58
+ def permit_rules
59
+ can :create, Project
60
+ can :show, Project
61
+
62
+ can :has_role?, Project
63
+ can :is_done?, Project
64
+ can :destroy!, Project
65
+
66
+ can :done!, Project
67
+ can :edit, Project
68
+ can :publish, Project
69
+ can :assign_to, Project
70
+ end
71
+ end
72
+
73
+ class Project
74
+ include CanTango::Model::Filter
75
+
76
+ tango_filter :publish, :edit, :DELETE, :is_done?, :done!
77
+ tango_filter :assign_to => [:user], :create => :OPTS, :show => [:ARGS], :has_role? => :role
78
+
79
+ def create options = {}
80
+ options
81
+ end
82
+
83
+ def show *args
84
+ args.flatten.compact
85
+ end
86
+
87
+ def is_done?
88
+ false
89
+ end
90
+
91
+ def has_role? role
92
+ true
93
+ end
94
+
95
+ def done!
96
+ "done"
97
+ end
98
+
99
+ def publish
100
+ "publish"
101
+ end
102
+
103
+ def destroy!
104
+ "destroy!"
105
+ end
106
+
107
+ def edit
108
+ "edit"
109
+ end
110
+
111
+ def assign_to user
112
+ user
113
+ end
114
+ end
115
+
116
+ describe CanTango::Model::Filter do
117
+ let(:context) { Context.new }
118
+
119
+ subject { Project.new }
120
+
121
+ describe '#tango_filter' do
122
+
123
+ describe 'block access to model method due to permission rule' do
124
+ specify { subject.publish_by(context.current_user).should be_nil }
125
+ end
126
+
127
+ describe 'allow access to model method due to permission rule' do
128
+ specify { subject.publish_by(context.current_admin).should == "publish" }
129
+ end
130
+
131
+ describe 'handle method with args' do
132
+ specify { subject.assign_to_by(context.current_admin, context.current_user).should == context.current_user }
133
+ specify { subject.assign_to_by(context.current_user, context.current_admin).should be_nil }
134
+ end
135
+
136
+ describe 'handle method with *args' do
137
+ specify { subject.show_by(context.current_admin, 'love', nil, 'hate').should == ['love', 'hate'] }
138
+ end
139
+
140
+ describe 'handle method with options' do
141
+ specify { subject.create_by(context.current_admin, :love => 5, :hate => 2).should == {:love => 5, :hate => 2} }
142
+ end
143
+
144
+ describe 'handle method with ? postfix' do
145
+ specify { subject.has_role_by?(context.current_admin, 'editor').should be_true }
146
+ specify { subject.is_done_by?(context.current_admin).should be_false }
147
+ end
148
+
149
+ describe 'handle method with ! postfix' do
150
+ specify { subject.done_by!(context.current_admin).should == 'done' }
151
+ end
152
+
153
+ describe 'handle special REST method - DELETE' do
154
+ specify { subject.destroy_by!(context.current_admin).should == 'destroy!' }
155
+ end
156
+ end
157
+
158
+ describe '#tango_account_filter' do
159
+ describe 'block access to model method due to permission rule' do
160
+ specify { subject.publish_by(context.current_user_account).should be_nil }
161
+ end
162
+
163
+ describe 'allow access to model method due to permission rule' do
164
+ specify { subject.publish_by(context.current_admin_account).should == "publish" }
165
+ end
166
+ end
167
+ end
168
+