cantango 0.8.5.1 → 0.8.6

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