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 CHANGED
@@ -49,8 +49,8 @@ group :test do
49
49
  end
50
50
 
51
51
  group :development, :test do
52
- # gem 'rspec-rails', '2.6.1' # needed in development to expose the rails generators
53
- # gem 'forgery', '0.3.10' # needed in development when using rake db:seed
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_ rules in a permission store, including a YAML file, for easy administration
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 supports "sugar-high 0.6":https://github.com/kristianmandrup/sugar-high.git' where "sweetloader":https://github.com/kristianmandrup/sweet_loader.git' has been extracted into its own gem.
42
+ CanTango now:
43
43
 
44
- * The Cache has been refactored
45
- * Engines are now run in correct order (and only if active)
46
- * The Cache Kompiler (for dynamic rules caching) and Moneta cache are now optional (via adapters)
47
- * Permits are found and loaded via pre-registratio via the @#inherited@ method for the base permits. You can also use the _tango_permit_ macro.
48
- * Better visibility of the @Ability@ flow, to allow one to see which rules are triggered by which permits (likely via a special :debug config mode, since it would affect performance).
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. Access Control via Permits and Permissions
76
+ h3. Abilities via Permits and Permissions
77
77
 
78
- AC rules can be defined in both:
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
- AC rules can be defined for the following conceptual entities:
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 ability pattern is simple.
124
+ The default CanTango Ability pattern is simple.
94
125
 
95
- 1. Return cached rules for ability candidate if available
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
- An ability candidate is typically either a user or an account instance.
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
- - Main architect
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.5.1
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 = %q{cantango}
8
- s.version = "0.8.5.1"
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 = [%q{Kristian Mandrup}, %q{Stanislaw Pankevich}]
12
- s.date = %q{2011-09-02}
13
- s.description = %q{Define your permission rules as role- or role group specific permits.
14
- Integrates well with multiple Devise user acounts.
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 = %q{http://github.com/kristianmandrup/cantango}
638
- s.licenses = [%q{MIT}]
639
- s.require_paths = [%q{lib}]
640
- s.rubygems_version = %q{1.8.8}
641
- s.summary = %q{CanCan extension with role oriented permission management and more}
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 "#{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)
14
- @value ||= [user_key, subject_roles_hash].hash
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.send(user_key_field)
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
- [subject.roles_list, subject.role_groups_list].hash
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
@@ -4,7 +4,7 @@ require 'sugar-high/kind_of'
4
4
  module CanTango
5
5
  class Configuration
6
6
  class Registry
7
-
7
+
8
8
  attr_writer :default
9
9
  attr_accessor :registered
10
10
 
@@ -7,7 +7,7 @@ module CanTango
7
7
  end
8
8
 
9
9
  def execute!
10
- # raise NotImplementedError
10
+ # raise NotImplementedError
11
11
  end
12
12
  end
13
13
  end
@@ -9,7 +9,6 @@ module CanTango
9
9
  end
10
10
 
11
11
  def execute!
12
- puts "permissions"
13
12
  permissions.each do |permission|
14
13
  permission.evaluate! user
15
14
  end
@@ -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 rules
76
- ability.send :rules
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
@@ -3,21 +3,6 @@ module CanTango
3
3
  autoload_modules :Adaptor, :UserRelation, :Dsl, :Scope, :RuleClass
4
4
 
5
5
  include Dsl
6
- include CanTango::Rules::RuleClass
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.5.1
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-02 00:00:00.000000000Z
13
+ date: 2011-09-16 00:00:00.000000000Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rails
17
- requirement: &2158261060 !ruby/object:Gem::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: *2158261060
25
+ version_requirements: *2158759980
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: cancan
28
- requirement: &2158260560 !ruby/object:Gem::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: *2158260560
36
+ version_requirements: *2158759180
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: sugar-high
39
- requirement: &2158260080 !ruby/object:Gem::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: *2158260080
47
+ version_requirements: *2158752840
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: sweetloader
50
- requirement: &2158259560 !ruby/object:Gem::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: *2158259560
58
+ version_requirements: *2158751900
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: sqlite3
61
- requirement: &2158259060 !ruby/object:Gem::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: *2158259060
69
+ version_requirements: *2158749860
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: hashie
72
- requirement: &2158258580 !ruby/object:Gem::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: *2158258580
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: &2158258080 !ruby/object:Gem::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: *2158258080
113
+ version_requirements: *2158729700
92
114
  - !ruby/object:Gem::Dependency
93
115
  name: sourcify
94
- requirement: &2158257580 !ruby/object:Gem::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: *2158257580
124
+ version_requirements: *2158728640
103
125
  - !ruby/object:Gem::Dependency
104
126
  name: dkastner-moneta
105
- requirement: &2158257080 !ruby/object:Gem::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: *2158257080
135
+ version_requirements: *2158727540
114
136
  - !ruby/object:Gem::Dependency
115
137
  name: rspec
116
- requirement: &2158256600 !ruby/object:Gem::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: *2158256600
146
+ version_requirements: *2158726640
125
147
  - !ruby/object:Gem::Dependency
126
148
  name: jeweler
127
- requirement: &2158256100 !ruby/object:Gem::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: *2158256100
157
+ version_requirements: *2158725840
136
158
  - !ruby/object:Gem::Dependency
137
159
  name: bundler
138
- requirement: &2158255580 !ruby/object:Gem::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: *2158255580
168
+ version_requirements: *2158724960
147
169
  - !ruby/object:Gem::Dependency
148
170
  name: rdoc
149
- requirement: &2158255080 !ruby/object:Gem::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: *2158255080
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: -2626615460253562025
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.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
@@ -1,3 +0,0 @@
1
- h1. README
2
-
3
- This folder is for creating specs to test the internals of CanTango.