cantango 0.8.5.1 → 0.8.6
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 +2 -2
- data/README.textile +49 -28
- data/VERSION +1 -1
- data/cantango.gemspec +19 -15
- data/lib/cantango.rb +16 -0
- data/lib/cantango/ability/cache/key.rb +22 -6
- data/lib/cantango/configuration.rb +2 -2
- data/lib/cantango/configuration/adapters.rb +2 -3
- data/lib/cantango/configuration/debug.rb +25 -0
- data/lib/cantango/configuration/permits.rb +45 -2
- data/lib/cantango/configuration/registry.rb +1 -1
- data/lib/cantango/engine.rb +1 -1
- data/lib/cantango/permission_engine.rb +0 -1
- data/lib/cantango/permit_engine.rb +3 -1
- data/lib/cantango/permits/permit.rb +12 -5
- data/lib/cantango/rules.rb +1 -16
- data/spec/cantango/configuration/debug_spec.rb +68 -0
- data/spec/cantango/configuration/permits_spec.rb +60 -0
- metadata +54 -31
- data/spec/cantango/README.textile +0 -3
data/Gemfile
CHANGED
@@ -49,8 +49,8 @@ group :test do
|
|
49
49
|
end
|
50
50
|
|
51
51
|
group :development, :test do
|
52
|
-
|
53
|
-
|
52
|
+
gem "rspec-rails", '>= 2.6.1' # needed in development to expose the rails generators
|
53
|
+
gem 'forgery', '>= 0.3' # needed in development when using rake db:seed
|
54
54
|
gem 'factory_girl'
|
55
55
|
|
56
56
|
# Adapters
|
data/README.textile
CHANGED
@@ -2,10 +2,10 @@ h1. CanTango
|
|
2
2
|
|
3
3
|
CanTango is an advanced Access Control (permissions) system for Rails 3. It:
|
4
4
|
|
5
|
-
* extends "CanCan":http://github.com/ryanb/cancan and offers a role oriented design
|
5
|
+
* extends "CanCan":http://github.com/ryanb/cancan and offers a more role oriented design
|
6
6
|
* integrates with _role_ and _authentication_ systems in a non-intrusive manner
|
7
|
-
* can _cache_ rules between requests for increased performance
|
8
|
-
* can _store_
|
7
|
+
* can _cache_ ability rules between requests for increased performance
|
8
|
+
* can _store_ abilites in a permission store, including a YAML file, for easy administration
|
9
9
|
* works well with multiple user accounts and sub applications
|
10
10
|
* supports multiple "Devise":https://github.com/plataformatec/devise users
|
11
11
|
|
@@ -37,15 +37,15 @@ Run bundler in a terminal/console from the folder of your Gemfile (root folder o
|
|
37
37
|
|
38
38
|
h2. Update Sept 1, 2011
|
39
39
|
|
40
|
-
Version *0.8.5* has been released.
|
40
|
+
Version *0.8.5.1* has been released.
|
41
41
|
|
42
|
-
CanTango now
|
42
|
+
CanTango now:
|
43
43
|
|
44
|
-
*
|
45
|
-
*
|
46
|
-
*
|
47
|
-
*
|
48
|
-
*
|
44
|
+
* supports "sugar-high 0.6":https://github.com/kristianmandrup/sugar-high.
|
45
|
+
* The ability cache has been refactored
|
46
|
+
* Activated engines are now run in specified order
|
47
|
+
* The ability cache rules compiler (for dynamic rules caching) and Moneta cache/store are now optional (enabled via adapters)
|
48
|
+
* Permits are found and loaded using pre-registration via inheritance. You can also use the _tango_permit_ macro for more control.
|
49
49
|
|
50
50
|
The wiki will soon be updated to reflect these improvements and changes.
|
51
51
|
|
@@ -73,14 +73,16 @@ h3. Rails 3 configuration
|
|
73
73
|
|
74
74
|
The CanTango "Configuration":https://github.com/kristianmandrup/cantango/wiki/Configuration consists of a nice DSL that let's you configure most of the things we imagine you would want to customize. Feel free to suggest more configuration options!
|
75
75
|
|
76
|
-
h3.
|
76
|
+
h3. Abilities via Permits and Permissions
|
77
77
|
|
78
|
-
|
78
|
+
Abilities are Access Control rules. With CanTango, these can be defined in both:
|
79
79
|
|
80
80
|
* "Permissions":https://github.com/kristianmandrup/cantango/wiki/Permissions (fx a yaml file)
|
81
81
|
* "Permits":https://github.com/kristianmandrup/cantango/wiki/Permits (special classes)
|
82
82
|
|
83
|
-
|
83
|
+
Note: For the simplest cases, you can define a @#permit_rules@ instance method directly in _CanTango::Ability_
|
84
|
+
|
85
|
+
Abilities can be defined for the following conceptual entities:
|
84
86
|
|
85
87
|
* User models
|
86
88
|
* User Account models
|
@@ -88,15 +90,44 @@ AC rules can be defined for the following conceptual entities:
|
|
88
90
|
* Role groups
|
89
91
|
* Users
|
90
92
|
|
93
|
+
h3. Debugging Abilities and Permits
|
94
|
+
|
95
|
+
Each Permit is in effect an Ability on its own. This lets you easily investigate which Permits allowed or denied a certain action for a specific ability candidate (typically a user or user account).
|
96
|
+
|
97
|
+
Debugging Example:
|
98
|
+
|
99
|
+
<pre>
|
100
|
+
# First you must enable debug mode
|
101
|
+
CanTango.debug!
|
102
|
+
|
103
|
+
# And have the permit engine execute at least once
|
104
|
+
user_can? :read, Article
|
105
|
+
|
106
|
+
# Then you can debug the permits execution
|
107
|
+
CanTango.permits_allowed current_user, :read, Article
|
108
|
+
|
109
|
+
admin_can? :read, Article
|
110
|
+
CanTango.permits_denied admin_user, :publish, [Article, Post]
|
111
|
+
CanTango.permits_allowed admin_user, :write, Article
|
112
|
+
|
113
|
+
CanTango.clear_executed_permits! # reset as if no permits have been executed
|
114
|
+
|
115
|
+
user_can? :publish, Article
|
116
|
+
CanTango.permits_denied current_user, [:write, publish], [Article, Post]
|
117
|
+
|
118
|
+
guest_account_can? :publish, Article
|
119
|
+
CanTango.permits_denied guest_account, :publish, [Article, Post], options
|
120
|
+
</pre>
|
121
|
+
|
91
122
|
h3. Design overview
|
92
123
|
|
93
|
-
The default CanTango
|
124
|
+
The default CanTango Ability pattern is simple.
|
94
125
|
|
95
|
-
1. Return cached rules for
|
126
|
+
1. Return cached ability rules for candidate if available
|
96
127
|
2. Generate rules for candidate
|
97
128
|
3. Cache rules for candidate
|
98
129
|
|
99
|
-
|
130
|
+
A candidate is typically either a user or an account instance.
|
100
131
|
|
101
132
|
Caching can be enabled or disabled. To generate the rules, one or more engines are executed.
|
102
133
|
|
@@ -141,18 +172,8 @@ If you encounter bugs, raise an issue or:
|
|
141
172
|
|
142
173
|
h2. Contributors
|
143
174
|
|
144
|
-
*Kristian Mandrup
|
145
|
-
|
146
|
-
- Designer of structure
|
147
|
-
- Feature ideas
|
148
|
-
- Initiator of project
|
149
|
-
- Devise app integration specs
|
150
|
-
|
151
|
-
"Stanislaw Pankevich":https://github.com/stanislaw
|
152
|
-
- Main contributor of permissions engine
|
153
|
-
- Caching of Procs for caching engine
|
154
|
-
- Lots of bug fixes and specs
|
155
|
-
- Tireless "worker" ;)
|
175
|
+
* Kristian Mandrup
|
176
|
+
* "Stanislaw Pankevich":https://github.com/stanislaw
|
156
177
|
|
157
178
|
h3. Copyright
|
158
179
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.8.
|
1
|
+
0.8.6
|
data/cantango.gemspec
CHANGED
@@ -4,17 +4,14 @@
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
|
-
s.name =
|
8
|
-
s.version = "0.8.
|
7
|
+
s.name = "cantango"
|
8
|
+
s.version = "0.8.6"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors = [
|
12
|
-
s.date =
|
13
|
-
s.description =
|
14
|
-
|
15
|
-
Includes rules caching.
|
16
|
-
Store permissions in yaml file or key-value store}
|
17
|
-
s.email = %q{kmandrup@gmail.com, s.pankevich@gmail.com}
|
11
|
+
s.authors = ["Kristian Mandrup", "Stanislaw Pankevich"]
|
12
|
+
s.date = "2011-09-16"
|
13
|
+
s.description = "Define your permission rules as role- or role group specific permits.\nIntegrates well with multiple Devise user acounts.\nIncludes rules caching.\nStore permissions in yaml file or key-value store"
|
14
|
+
s.email = "kmandrup@gmail.com, s.pankevich@gmail.com"
|
18
15
|
s.extra_rdoc_files = [
|
19
16
|
"LICENSE.txt",
|
20
17
|
"README.textile"
|
@@ -71,6 +68,7 @@ Store permissions in yaml file or key-value store}
|
|
71
68
|
"lib/cantango/configuration/adapters.rb",
|
72
69
|
"lib/cantango/configuration/autoload.rb",
|
73
70
|
"lib/cantango/configuration/categories.rb",
|
71
|
+
"lib/cantango/configuration/debug.rb",
|
74
72
|
"lib/cantango/configuration/engines.rb",
|
75
73
|
"lib/cantango/configuration/engines/cache.rb",
|
76
74
|
"lib/cantango/configuration/engines/engine.rb",
|
@@ -274,7 +272,6 @@ Store permissions in yaml file or key-value store}
|
|
274
272
|
"spec/active_record/scenarios/user_accounts/permits/user_account_permit.rb",
|
275
273
|
"spec/active_record/scenarios/user_accounts/user_account_spec.rb",
|
276
274
|
"spec/active_record/spec_helper.rb",
|
277
|
-
"spec/cantango/README.textile",
|
278
275
|
"spec/cantango/ability/cache/key_spec.rb",
|
279
276
|
"spec/cantango/ability/cache/kompiler_spec.rb",
|
280
277
|
"spec/cantango/ability/cache/reader_compile_spec.rb",
|
@@ -300,6 +297,7 @@ Store permissions in yaml file or key-value store}
|
|
300
297
|
"spec/cantango/configuration/adapter_spec.rb",
|
301
298
|
"spec/cantango/configuration/autoload_spec.rb",
|
302
299
|
"spec/cantango/configuration/categories_spec.rb",
|
300
|
+
"spec/cantango/configuration/debug_spec.rb",
|
303
301
|
"spec/cantango/configuration/engines/cache_spec.rb",
|
304
302
|
"spec/cantango/configuration/engines/engine_shared.rb",
|
305
303
|
"spec/cantango/configuration/engines/permission_spec.rb",
|
@@ -634,11 +632,11 @@ Store permissions in yaml file or key-value store}
|
|
634
632
|
"wiki/when_to_use.markdown",
|
635
633
|
"wiki/why_to_use.markdown"
|
636
634
|
]
|
637
|
-
s.homepage =
|
638
|
-
s.licenses = [
|
639
|
-
s.require_paths = [
|
640
|
-
s.rubygems_version =
|
641
|
-
s.summary =
|
635
|
+
s.homepage = "http://github.com/kristianmandrup/cantango"
|
636
|
+
s.licenses = ["MIT"]
|
637
|
+
s.require_paths = ["lib"]
|
638
|
+
s.rubygems_version = "1.8.10"
|
639
|
+
s.summary = "CanCan extension with role oriented permission management and more"
|
642
640
|
|
643
641
|
if s.respond_to? :specification_version then
|
644
642
|
s.specification_version = 3
|
@@ -650,6 +648,8 @@ Store permissions in yaml file or key-value store}
|
|
650
648
|
s.add_runtime_dependency(%q<sweetloader>, ["~> 0.1.0"])
|
651
649
|
s.add_runtime_dependency(%q<sqlite3>, [">= 0"])
|
652
650
|
s.add_runtime_dependency(%q<hashie>, [">= 0.4"])
|
651
|
+
s.add_development_dependency(%q<rspec-rails>, [">= 2.6.1"])
|
652
|
+
s.add_development_dependency(%q<forgery>, [">= 0.3"])
|
653
653
|
s.add_development_dependency(%q<factory_girl>, [">= 0"])
|
654
654
|
s.add_development_dependency(%q<sourcify>, [">= 0"])
|
655
655
|
s.add_development_dependency(%q<dkastner-moneta>, [">= 1.0"])
|
@@ -664,6 +664,8 @@ Store permissions in yaml file or key-value store}
|
|
664
664
|
s.add_dependency(%q<sweetloader>, ["~> 0.1.0"])
|
665
665
|
s.add_dependency(%q<sqlite3>, [">= 0"])
|
666
666
|
s.add_dependency(%q<hashie>, [">= 0.4"])
|
667
|
+
s.add_dependency(%q<rspec-rails>, [">= 2.6.1"])
|
668
|
+
s.add_dependency(%q<forgery>, [">= 0.3"])
|
667
669
|
s.add_dependency(%q<factory_girl>, [">= 0"])
|
668
670
|
s.add_dependency(%q<sourcify>, [">= 0"])
|
669
671
|
s.add_dependency(%q<dkastner-moneta>, [">= 1.0"])
|
@@ -679,6 +681,8 @@ Store permissions in yaml file or key-value store}
|
|
679
681
|
s.add_dependency(%q<sweetloader>, ["~> 0.1.0"])
|
680
682
|
s.add_dependency(%q<sqlite3>, [">= 0"])
|
681
683
|
s.add_dependency(%q<hashie>, [">= 0.4"])
|
684
|
+
s.add_dependency(%q<rspec-rails>, [">= 2.6.1"])
|
685
|
+
s.add_dependency(%q<forgery>, [">= 0.3"])
|
682
686
|
s.add_dependency(%q<factory_girl>, [">= 0"])
|
683
687
|
s.add_dependency(%q<sourcify>, [">= 0"])
|
684
688
|
s.add_dependency(%q<dkastner-moneta>, [">= 1.0"])
|
data/lib/cantango.rb
CHANGED
@@ -22,6 +22,22 @@ module CanTango
|
|
22
22
|
end
|
23
23
|
|
24
24
|
alias_method :config, :configure
|
25
|
+
|
26
|
+
def permits_allowed candidate, actions, subjects, *extra_args
|
27
|
+
config.permits.allowed candidate, actions, subjects, *extra_args
|
28
|
+
end
|
29
|
+
|
30
|
+
def permits_denied candidate, actions, subjects, *extra_args
|
31
|
+
config.permits.denied candidate, actions, subjects, *extra_args
|
32
|
+
end
|
33
|
+
|
34
|
+
def clear_permits_executed!
|
35
|
+
config.permits.clear_executed!
|
36
|
+
end
|
37
|
+
|
38
|
+
def debug!
|
39
|
+
config.debug.set :on
|
40
|
+
end
|
25
41
|
end
|
26
42
|
end
|
27
43
|
|
@@ -4,14 +4,18 @@ module CanTango
|
|
4
4
|
class Key
|
5
5
|
attr_reader :user, :subject
|
6
6
|
|
7
|
-
def initialize user, subject
|
7
|
+
def initialize user, subject = nil
|
8
8
|
@user = user
|
9
|
-
@subject = subject
|
9
|
+
@subject = subject || user
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.create_for ability
|
13
|
+
self.new ability.user, ability.subject
|
10
14
|
end
|
11
15
|
|
12
16
|
def value
|
13
|
-
raise "
|
14
|
-
@value ||=
|
17
|
+
raise "No key could be generated for #{user} and #{subject}" if hash_values.empty?
|
18
|
+
@value ||= hash_values.hash
|
15
19
|
end
|
16
20
|
|
17
21
|
def same? session
|
@@ -21,8 +25,13 @@ module CanTango
|
|
21
25
|
|
22
26
|
protected
|
23
27
|
|
28
|
+
def hash_values
|
29
|
+
@hash_values ||= [user_key, subject_roles_hash].compact
|
30
|
+
end
|
31
|
+
|
24
32
|
def user_key
|
25
|
-
user.
|
33
|
+
# raise "#{user.class} must have a method ##{user_key_field}. You can configure this with CanTango.config#user.unique_key_field" if !user.respond_to?(user_key_field)
|
34
|
+
user.send(user_key_field) if user.respond_to? user_key_field
|
26
35
|
end
|
27
36
|
|
28
37
|
def user_key_field
|
@@ -30,7 +39,14 @@ module CanTango
|
|
30
39
|
end
|
31
40
|
|
32
41
|
def subject_roles_hash
|
33
|
-
|
42
|
+
role_hash_values.empty? ? nil : role_hash_values.hash
|
43
|
+
end
|
44
|
+
|
45
|
+
def role_hash_values
|
46
|
+
@role_hash_values ||= [:roles_list, :role_groups_list].inject([]) do |result, meth|
|
47
|
+
result << subject.send(meth) if subject.respond_to? meth
|
48
|
+
result
|
49
|
+
end
|
34
50
|
end
|
35
51
|
end
|
36
52
|
end
|
@@ -7,7 +7,7 @@ module CanTango
|
|
7
7
|
autoload_modules :Models, :Engines, :Ability
|
8
8
|
autoload_modules :User, :Guest, :UserAccount
|
9
9
|
autoload_modules :Roles, :RoleGroups, :Registry, :RoleRegistry, :HashRegistry, :PermitRegistry, :Factory
|
10
|
-
autoload_modules :SpecialPermits, :Autoload, :Adapters, :Permits
|
10
|
+
autoload_modules :SpecialPermits, :Autoload, :Adapters, :Permits, :Debug
|
11
11
|
autoload_modules :Users, :UserAccounts
|
12
12
|
|
13
13
|
include Singleton
|
@@ -21,7 +21,7 @@ module CanTango
|
|
21
21
|
def self.components
|
22
22
|
[
|
23
23
|
:guest, :autoload, :user, :user_account, :models, :roles, :role_groups,
|
24
|
-
:engines, :users, :user_accounts, :categories, :adapters, :permits
|
24
|
+
:engines, :users, :user_accounts, :categories, :adapters, :permits, :debug
|
25
25
|
]
|
26
26
|
end
|
27
27
|
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module CanTango
|
2
2
|
class Configuration
|
3
3
|
class Adapters < Registry
|
4
|
-
|
4
|
+
|
5
5
|
include Singleton
|
6
|
-
|
6
|
+
|
7
7
|
def adapter name
|
8
8
|
raise "Unknown adapter #{name}" if !available_adapters.include? name.to_sym
|
9
9
|
require "cantango/adapter/#{name}"
|
@@ -16,7 +16,6 @@ module CanTango
|
|
16
16
|
def available_adapters
|
17
17
|
[:moneta, :compiler]
|
18
18
|
end
|
19
|
-
|
20
19
|
end
|
21
20
|
end
|
22
21
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module CanTango
|
2
|
+
class Configuration
|
3
|
+
# Note: This config feature is currently not used, but could potentially be of use in the future
|
4
|
+
class Debug
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
def set state = :on
|
8
|
+
raise ArgumentError, "Must be :on or :off" unless !state || [:on, :off].include?(state)
|
9
|
+
@state = state || :on
|
10
|
+
end
|
11
|
+
|
12
|
+
def on?
|
13
|
+
@state == :on
|
14
|
+
end
|
15
|
+
|
16
|
+
def off?
|
17
|
+
!on?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
|
@@ -1,10 +1,9 @@
|
|
1
1
|
module CanTango
|
2
|
-
class Configuration
|
2
|
+
class Configuration
|
3
3
|
class Permits < PermitRegistry
|
4
4
|
include Singleton
|
5
5
|
|
6
6
|
attr_reader :accounts
|
7
|
-
# CanTango.config.permits.accounts[:admin].role => {}
|
8
7
|
|
9
8
|
def accounts
|
10
9
|
@accounts ||= Hash.new
|
@@ -22,6 +21,50 @@ module CanTango
|
|
22
21
|
registry = account_name ? self.send(account_name.to_sym) : self
|
23
22
|
registry.send(permit_type)[permit_name] = permit_clazz
|
24
23
|
end
|
24
|
+
|
25
|
+
def allowed candidate, actions, subjects, *extra_args
|
26
|
+
executed_for(candidate).inject([]) do |result, permit|
|
27
|
+
result << permit.class if permit.can? actions, subjects, *extra_args
|
28
|
+
result
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def denied candidate, actions, subjects, *extra_args
|
33
|
+
executed_for(candidate).inject([]) do |result, permit|
|
34
|
+
result << permit.class if permit.cannot? actions, subjects, *extra_args
|
35
|
+
result
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def was_executed permit, ability
|
40
|
+
executed_for(ability) << permit
|
41
|
+
end
|
42
|
+
|
43
|
+
def executed_for ability
|
44
|
+
executed[hash_key_for(ability)] ||= []
|
45
|
+
end
|
46
|
+
|
47
|
+
def executed
|
48
|
+
@executed ||= {}
|
49
|
+
end
|
50
|
+
|
51
|
+
def clear_executed!
|
52
|
+
@executed = nil
|
53
|
+
end
|
54
|
+
|
55
|
+
protected
|
56
|
+
|
57
|
+
def hash_key_for subject
|
58
|
+
key_for(subject).value
|
59
|
+
end
|
60
|
+
|
61
|
+
def key_for subject
|
62
|
+
subject.kind_of?(CanTango::Ability) ? key_maker.create_for(subject) : key_maker.new(subject)
|
63
|
+
end
|
64
|
+
|
65
|
+
def key_maker
|
66
|
+
CanTango::Ability::Cache::Key
|
67
|
+
end
|
25
68
|
end
|
26
69
|
end
|
27
70
|
end
|
data/lib/cantango/engine.rb
CHANGED
@@ -8,7 +8,9 @@ module CanTango
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def execute!
|
11
|
+
# CanTango.config.permits.clear_executed! # should there be an option clear before each execution?
|
11
12
|
permits.each do |permit|
|
13
|
+
CanTango.config.permits.was_executed(permit, ability) if CanTango.config.debug.on?
|
12
14
|
break if permit.execute == :break
|
13
15
|
end
|
14
16
|
end
|
@@ -17,7 +19,7 @@ module CanTango
|
|
17
19
|
# has a role or a role group
|
18
20
|
# also execute any permit marked as special
|
19
21
|
def permits
|
20
|
-
permit_factory.build!
|
22
|
+
@permits ||= permit_factory.build!
|
21
23
|
end
|
22
24
|
|
23
25
|
def permit_class_names
|
@@ -30,12 +30,14 @@ module CanTango
|
|
30
30
|
# executes the permit
|
31
31
|
def execute
|
32
32
|
executor.execute!
|
33
|
+
ability_sync!
|
33
34
|
end
|
34
35
|
|
35
36
|
def category label
|
36
37
|
config.models.by_category label
|
37
38
|
end
|
38
39
|
|
40
|
+
|
39
41
|
def any reg_exp
|
40
42
|
config.models.by_reg_exp reg_exp
|
41
43
|
end
|
@@ -72,11 +74,16 @@ module CanTango
|
|
72
74
|
ability.user_account
|
73
75
|
end
|
74
76
|
|
75
|
-
def
|
76
|
-
ability.send
|
77
|
+
def ability_rules
|
78
|
+
ability.send(:rules)
|
79
|
+
end
|
80
|
+
|
81
|
+
def ability_sync!
|
82
|
+
ability_rules << (rules - ability_rules)
|
83
|
+
ability_rules.flatten!
|
77
84
|
end
|
78
85
|
|
79
|
-
# In a specific Role based Permit you can use
|
86
|
+
# In a specific Role based Permit you can use
|
80
87
|
# def permit? user, options = {}
|
81
88
|
# return if !super(user, :in_role)
|
82
89
|
# ... permission logic follows
|
@@ -103,7 +110,7 @@ module CanTango
|
|
103
110
|
end
|
104
111
|
end
|
105
112
|
|
106
|
-
include CanTango::Rules
|
113
|
+
include CanTango::Rules # also makes a Permit a subclass of CanCan::Ability
|
107
114
|
|
108
115
|
protected
|
109
116
|
|
@@ -117,7 +124,7 @@ module CanTango
|
|
117
124
|
raise "License #{clazz} could not be enforced using #{self.inspect}"
|
118
125
|
end
|
119
126
|
|
120
|
-
# This method will contain the actual rules
|
127
|
+
# This method will contain the actual rules
|
121
128
|
# can be implemented in the subclass
|
122
129
|
|
123
130
|
def permit_rules
|
data/lib/cantango/rules.rb
CHANGED
@@ -3,21 +3,6 @@ module CanTango
|
|
3
3
|
autoload_modules :Adaptor, :UserRelation, :Dsl, :Scope, :RuleClass
|
4
4
|
|
5
5
|
include Dsl
|
6
|
-
include
|
7
|
-
# Examples:
|
8
|
-
# can :read, Project
|
9
|
-
# can [:read, :create], [Project, Post]
|
10
|
-
# can :read, Project, :active => true, :user_id => user.id
|
11
|
-
def can(action, subject, conditions = nil, &block)
|
12
|
-
rules << rule_class.new(true, action, subject, conditions, block)
|
13
|
-
end
|
14
|
-
|
15
|
-
# Examples:
|
16
|
-
# cannot :read, Project
|
17
|
-
# cannot [:read, :create], [Project, Post]
|
18
|
-
# cannot :read, Project, :active => true, :user_id => user.id
|
19
|
-
def cannot(action, subject, conditions = nil, &block)
|
20
|
-
rules << rule_class.new(false, action, subject, conditions, block)
|
21
|
-
end
|
6
|
+
include CanCan::Ability
|
22
7
|
end
|
23
8
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Menu
|
4
|
+
end
|
5
|
+
|
6
|
+
class WaiterRolePermit < CanTango::RolePermit
|
7
|
+
def initialize ability
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def permit_rules
|
14
|
+
can :read, Menu
|
15
|
+
cannot :write, Menu
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class ChefRolePermit < CanTango::RolePermit
|
20
|
+
def initialize ability
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def permit_rules
|
27
|
+
can :publish, Menu
|
28
|
+
can :write, Menu
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Context
|
33
|
+
include CanTango::Api::User::Ability
|
34
|
+
end
|
35
|
+
|
36
|
+
# Note: This config feature is currently not used, but could potentially be of use in the future
|
37
|
+
describe CanTango::Configuration::Debug do
|
38
|
+
let(:context) { Context.new }
|
39
|
+
subject { CanTango.config.debug }
|
40
|
+
|
41
|
+
describe 'should set debug mode :on' do
|
42
|
+
before do
|
43
|
+
subject.set :on
|
44
|
+
end
|
45
|
+
|
46
|
+
its(:on?) { should be_true }
|
47
|
+
its(:off?) { should be_false }
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'should set debug mode :off' do
|
51
|
+
before do
|
52
|
+
subject.set :on
|
53
|
+
end
|
54
|
+
|
55
|
+
its(:on?) { should be_true }
|
56
|
+
its(:off?) { should be_false }
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'debug! should set debug mode :on' do
|
60
|
+
before do
|
61
|
+
CanTango.debug!
|
62
|
+
end
|
63
|
+
|
64
|
+
its(:on?) { should be_true }
|
65
|
+
its(:off?) { should be_false }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
@@ -1,5 +1,38 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
class Menu
|
4
|
+
end
|
5
|
+
|
6
|
+
class WaiterRolePermit < CanTango::RolePermit
|
7
|
+
def initialize ability
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def permit_rules
|
14
|
+
can :read, Menu
|
15
|
+
cannot :write, Menu
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class ChefRolePermit < CanTango::RolePermit
|
20
|
+
def initialize ability
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def permit_rules
|
27
|
+
can :publish, Menu
|
28
|
+
can :write, Menu
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Context
|
33
|
+
include CanTango::Api::User::Ability
|
34
|
+
end
|
35
|
+
|
3
36
|
describe CanTango::Configuration::Permits do
|
4
37
|
before do
|
5
38
|
@permit_registry = CanTango::Configuration::Permits.instance
|
@@ -22,4 +55,31 @@ describe CanTango::Configuration::Permits do
|
|
22
55
|
end
|
23
56
|
end
|
24
57
|
end
|
58
|
+
|
59
|
+
describe 'debugging permits' do
|
60
|
+
let(:context) { Context.new }
|
61
|
+
let (:user) do
|
62
|
+
User.new 'kris', 'kris@gmail.com', :role => :waiter
|
63
|
+
end
|
64
|
+
|
65
|
+
before do
|
66
|
+
CanTango.config.debug.set :on
|
67
|
+
context.user_ability(user).can? :read, Menu
|
68
|
+
end
|
69
|
+
|
70
|
+
describe 'should tell which permits allowe :read' do
|
71
|
+
it 'should show WaiterRolePermit as the permit that allowed :read of Menu' do
|
72
|
+
CanTango.permits_allowed(user, :read, Menu).should include(WaiterRolePermit)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe 'should tell which permits denied :write' do
|
77
|
+
it 'should show WaiterRolePermit as the permit that denied :write of Menu' do
|
78
|
+
CanTango.permits_denied(user, :write, Menu).should include(WaiterRolePermit)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
25
82
|
end
|
83
|
+
|
84
|
+
|
85
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cantango
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2011-09-
|
13
|
+
date: 2011-09-16 00:00:00.000000000Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rails
|
17
|
-
requirement: &
|
17
|
+
requirement: &2158759980 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: 3.0.1
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *2158759980
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: cancan
|
28
|
-
requirement: &
|
28
|
+
requirement: &2158759180 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ! '>='
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: '1.4'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *2158759180
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: sugar-high
|
39
|
-
requirement: &
|
39
|
+
requirement: &2158752840 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ! '>='
|
@@ -44,10 +44,10 @@ dependencies:
|
|
44
44
|
version: 0.6.0
|
45
45
|
type: :runtime
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *2158752840
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: sweetloader
|
50
|
-
requirement: &
|
50
|
+
requirement: &2158751900 !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
52
52
|
requirements:
|
53
53
|
- - ~>
|
@@ -55,10 +55,10 @@ dependencies:
|
|
55
55
|
version: 0.1.0
|
56
56
|
type: :runtime
|
57
57
|
prerelease: false
|
58
|
-
version_requirements: *
|
58
|
+
version_requirements: *2158751900
|
59
59
|
- !ruby/object:Gem::Dependency
|
60
60
|
name: sqlite3
|
61
|
-
requirement: &
|
61
|
+
requirement: &2158749860 !ruby/object:Gem::Requirement
|
62
62
|
none: false
|
63
63
|
requirements:
|
64
64
|
- - ! '>='
|
@@ -66,10 +66,10 @@ dependencies:
|
|
66
66
|
version: '0'
|
67
67
|
type: :runtime
|
68
68
|
prerelease: false
|
69
|
-
version_requirements: *
|
69
|
+
version_requirements: *2158749860
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: hashie
|
72
|
-
requirement: &
|
72
|
+
requirement: &2158748240 !ruby/object:Gem::Requirement
|
73
73
|
none: false
|
74
74
|
requirements:
|
75
75
|
- - ! '>='
|
@@ -77,10 +77,32 @@ dependencies:
|
|
77
77
|
version: '0.4'
|
78
78
|
type: :runtime
|
79
79
|
prerelease: false
|
80
|
-
version_requirements: *
|
80
|
+
version_requirements: *2158748240
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: rspec-rails
|
83
|
+
requirement: &2158734040 !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ! '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 2.6.1
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: *2158734040
|
92
|
+
- !ruby/object:Gem::Dependency
|
93
|
+
name: forgery
|
94
|
+
requirement: &2158732460 !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ! '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0.3'
|
100
|
+
type: :development
|
101
|
+
prerelease: false
|
102
|
+
version_requirements: *2158732460
|
81
103
|
- !ruby/object:Gem::Dependency
|
82
104
|
name: factory_girl
|
83
|
-
requirement: &
|
105
|
+
requirement: &2158729700 !ruby/object:Gem::Requirement
|
84
106
|
none: false
|
85
107
|
requirements:
|
86
108
|
- - ! '>='
|
@@ -88,10 +110,10 @@ dependencies:
|
|
88
110
|
version: '0'
|
89
111
|
type: :development
|
90
112
|
prerelease: false
|
91
|
-
version_requirements: *
|
113
|
+
version_requirements: *2158729700
|
92
114
|
- !ruby/object:Gem::Dependency
|
93
115
|
name: sourcify
|
94
|
-
requirement: &
|
116
|
+
requirement: &2158728640 !ruby/object:Gem::Requirement
|
95
117
|
none: false
|
96
118
|
requirements:
|
97
119
|
- - ! '>='
|
@@ -99,10 +121,10 @@ dependencies:
|
|
99
121
|
version: '0'
|
100
122
|
type: :development
|
101
123
|
prerelease: false
|
102
|
-
version_requirements: *
|
124
|
+
version_requirements: *2158728640
|
103
125
|
- !ruby/object:Gem::Dependency
|
104
126
|
name: dkastner-moneta
|
105
|
-
requirement: &
|
127
|
+
requirement: &2158727540 !ruby/object:Gem::Requirement
|
106
128
|
none: false
|
107
129
|
requirements:
|
108
130
|
- - ! '>='
|
@@ -110,10 +132,10 @@ dependencies:
|
|
110
132
|
version: '1.0'
|
111
133
|
type: :development
|
112
134
|
prerelease: false
|
113
|
-
version_requirements: *
|
135
|
+
version_requirements: *2158727540
|
114
136
|
- !ruby/object:Gem::Dependency
|
115
137
|
name: rspec
|
116
|
-
requirement: &
|
138
|
+
requirement: &2158726640 !ruby/object:Gem::Requirement
|
117
139
|
none: false
|
118
140
|
requirements:
|
119
141
|
- - ! '>='
|
@@ -121,10 +143,10 @@ dependencies:
|
|
121
143
|
version: 2.4.0
|
122
144
|
type: :development
|
123
145
|
prerelease: false
|
124
|
-
version_requirements: *
|
146
|
+
version_requirements: *2158726640
|
125
147
|
- !ruby/object:Gem::Dependency
|
126
148
|
name: jeweler
|
127
|
-
requirement: &
|
149
|
+
requirement: &2158725840 !ruby/object:Gem::Requirement
|
128
150
|
none: false
|
129
151
|
requirements:
|
130
152
|
- - ! '>='
|
@@ -132,10 +154,10 @@ dependencies:
|
|
132
154
|
version: 1.6.4
|
133
155
|
type: :development
|
134
156
|
prerelease: false
|
135
|
-
version_requirements: *
|
157
|
+
version_requirements: *2158725840
|
136
158
|
- !ruby/object:Gem::Dependency
|
137
159
|
name: bundler
|
138
|
-
requirement: &
|
160
|
+
requirement: &2158724960 !ruby/object:Gem::Requirement
|
139
161
|
none: false
|
140
162
|
requirements:
|
141
163
|
- - ! '>='
|
@@ -143,10 +165,10 @@ dependencies:
|
|
143
165
|
version: 1.0.1
|
144
166
|
type: :development
|
145
167
|
prerelease: false
|
146
|
-
version_requirements: *
|
168
|
+
version_requirements: *2158724960
|
147
169
|
- !ruby/object:Gem::Dependency
|
148
170
|
name: rdoc
|
149
|
-
requirement: &
|
171
|
+
requirement: &2158724140 !ruby/object:Gem::Requirement
|
150
172
|
none: false
|
151
173
|
requirements:
|
152
174
|
- - ! '>='
|
@@ -154,7 +176,7 @@ dependencies:
|
|
154
176
|
version: '0'
|
155
177
|
type: :development
|
156
178
|
prerelease: false
|
157
|
-
version_requirements: *
|
179
|
+
version_requirements: *2158724140
|
158
180
|
description: ! 'Define your permission rules as role- or role group specific permits.
|
159
181
|
|
160
182
|
Integrates well with multiple Devise user acounts.
|
@@ -220,6 +242,7 @@ files:
|
|
220
242
|
- lib/cantango/configuration/adapters.rb
|
221
243
|
- lib/cantango/configuration/autoload.rb
|
222
244
|
- lib/cantango/configuration/categories.rb
|
245
|
+
- lib/cantango/configuration/debug.rb
|
223
246
|
- lib/cantango/configuration/engines.rb
|
224
247
|
- lib/cantango/configuration/engines/cache.rb
|
225
248
|
- lib/cantango/configuration/engines/engine.rb
|
@@ -423,7 +446,6 @@ files:
|
|
423
446
|
- spec/active_record/scenarios/user_accounts/permits/user_account_permit.rb
|
424
447
|
- spec/active_record/scenarios/user_accounts/user_account_spec.rb
|
425
448
|
- spec/active_record/spec_helper.rb
|
426
|
-
- spec/cantango/README.textile
|
427
449
|
- spec/cantango/ability/cache/key_spec.rb
|
428
450
|
- spec/cantango/ability/cache/kompiler_spec.rb
|
429
451
|
- spec/cantango/ability/cache/reader_compile_spec.rb
|
@@ -449,6 +471,7 @@ files:
|
|
449
471
|
- spec/cantango/configuration/adapter_spec.rb
|
450
472
|
- spec/cantango/configuration/autoload_spec.rb
|
451
473
|
- spec/cantango/configuration/categories_spec.rb
|
474
|
+
- spec/cantango/configuration/debug_spec.rb
|
452
475
|
- spec/cantango/configuration/engines/cache_spec.rb
|
453
476
|
- spec/cantango/configuration/engines/engine_shared.rb
|
454
477
|
- spec/cantango/configuration/engines/permission_spec.rb
|
@@ -797,7 +820,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
797
820
|
version: '0'
|
798
821
|
segments:
|
799
822
|
- 0
|
800
|
-
hash: -
|
823
|
+
hash: -2544503821884776922
|
801
824
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
802
825
|
none: false
|
803
826
|
requirements:
|
@@ -806,7 +829,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
806
829
|
version: '0'
|
807
830
|
requirements: []
|
808
831
|
rubyforge_project:
|
809
|
-
rubygems_version: 1.8.
|
832
|
+
rubygems_version: 1.8.10
|
810
833
|
signing_key:
|
811
834
|
specification_version: 3
|
812
835
|
summary: CanCan extension with role oriented permission management and more
|