cantango 0.8.9.5 → 0.9.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.textile +35 -7
- data/VERSION +1 -1
- data/cantango.gemspec +39 -12
- data/lib/cantango.rb +4 -3
- data/lib/cantango/ability.rb +17 -21
- data/lib/cantango/ability/cache/key.rb +32 -4
- data/lib/cantango/ability/cache/rules_cache.rb +9 -2
- data/lib/cantango/ability/cache_helpers.rb +1 -7
- data/lib/cantango/ability/engine_helpers.rb +27 -0
- data/lib/cantango/ability_executor.rb +41 -0
- data/lib/cantango/api/user/ability.rb +8 -12
- data/lib/cantango/api/user/session.rb +2 -1
- data/lib/cantango/api/user_account.rb +2 -2
- data/lib/cantango/api/user_account/ability.rb +19 -14
- data/lib/cantango/api/user_account/can.rb +8 -0
- data/lib/cantango/api/user_account/session.rb +33 -0
- data/lib/cantango/cached_ability.rb +26 -0
- data/lib/cantango/configuration.rb +3 -3
- data/lib/cantango/configuration/ability.rb +1 -0
- data/lib/cantango/configuration/candidate_registry.rb +51 -0
- data/lib/cantango/configuration/categories.rb +2 -2
- data/lib/cantango/configuration/engines.rb +7 -3
- data/lib/cantango/configuration/engines/permission.rb +5 -0
- data/lib/cantango/configuration/engines/permit.rb +1 -0
- data/lib/cantango/configuration/engines/user_ac.rb +19 -0
- data/lib/cantango/configuration/guest.rb +1 -1
- data/lib/cantango/configuration/modes.rb +21 -0
- data/lib/cantango/configuration/permits.rb +1 -1
- data/lib/cantango/configuration/role_groups.rb +1 -2
- data/lib/cantango/configuration/user_accounts.rb +1 -1
- data/lib/cantango/configuration/users.rb +1 -1
- data/lib/cantango/engine.rb +40 -0
- data/lib/cantango/helpers.rb +1 -1
- data/lib/cantango/helpers/debug.rb +9 -0
- data/lib/cantango/model.rb +6 -0
- data/lib/cantango/model/filter.rb +102 -0
- data/lib/cantango/model/scope.rb +57 -0
- data/lib/cantango/permission_engine.rb +14 -3
- data/lib/cantango/permission_engine/loader/base.rb +1 -6
- data/lib/cantango/permission_engine/loader/permissions.rb +10 -16
- data/lib/cantango/permission_engine/store.rb +1 -7
- data/lib/cantango/permission_engine/yaml_store.rb +3 -10
- data/lib/cantango/permit_engine.rb +17 -4
- data/lib/cantango/permit_engine/builder/base.rb +3 -1
- data/lib/cantango/permit_engine/executor/abstract.rb +2 -0
- data/lib/cantango/permit_engine/executor/base.rb +1 -1
- data/lib/cantango/permit_engine/factory.rb +5 -3
- data/lib/cantango/permit_engine/finder.rb +4 -6
- data/lib/cantango/permit_engine/util.rb +1 -1
- data/lib/cantango/permits/permit.rb +25 -0
- data/lib/cantango/permits/role_group_permit/builder.rb +23 -7
- data/lib/cantango/permits/role_permit.rb +1 -2
- data/lib/cantango/rails/helpers/rest_helper.rb +3 -2
- data/lib/cantango/user_ac_engine.rb +40 -0
- data/lib/cantango/user_ac_engine/executor.rb +59 -0
- data/lib/cantango/users/macros.rb +3 -0
- data/lib/cantango/users/user.rb +1 -1
- data/lib/cantango/users/user_account.rb +1 -1
- data/lib/generators/cantango/permission/permission_generator.rb +43 -0
- data/spec/active_record/migrations/008_create_permissions.rb +10 -0
- data/spec/cantango/ability_executor/cached_only_spec.rb +76 -0
- data/spec/cantango/ability_executor_spec.rb +75 -0
- data/spec/cantango/api/attributes_spec.rb +2 -1
- data/spec/cantango/api/current_user_accounts.rb +5 -1
- data/spec/cantango/api/user/ability_api_spec.rb +17 -4
- data/spec/cantango/api/user/can_api_spec.rb +9 -5
- data/spec/cantango/api/user/scope_api_spec.rb +15 -7
- data/spec/cantango/api/user_account/ability_api_spec.rb +12 -5
- data/spec/cantango/api/user_account/can_api_spec.rb +8 -4
- data/spec/cantango/cached_ability_spec.rb +0 -0
- data/spec/cantango/model/filter_spec.rb +168 -0
- data/spec/cantango/model/scope_spec.rb +107 -0
- data/spec/cantango/permission_engine/loader/permissions/{cantango_permissions_loader.rb → cantango_permissions_loader_spec.rb} +0 -0
- data/spec/cantango/permission_engine/loader/permissions/shared.rb +2 -2
- data/spec/cantango/permission_engine/yaml_store_spec.rb +0 -1
- data/spec/cantango/permit_engine/role_group_permit_spec.rb +2 -2
- data/spec/cantango/permits/permit_spec.rb +2 -2
- data/spec/cantango/rules_spec.rb +6 -6
- data/spec/cantango/user_ac_engine_spec.rb +53 -0
- data/spec/fixtures/config/cantango_permissions.yml +49 -0
- data/spec/fixtures/models/permission.rb +12 -0
- data/spec/fixtures/models/user.rb +8 -0
- data/spec/generators/cantango/permission_generator_spec.rb +44 -0
- metadata +59 -35
@@ -0,0 +1,41 @@
|
|
1
|
+
module CanTango
|
2
|
+
class AbilityExecutor < CanTango::Ability
|
3
|
+
attr_reader :rules
|
4
|
+
|
5
|
+
def initialize candidate, options = {}
|
6
|
+
raise "Candidate must be something!" if !candidate
|
7
|
+
@candidate, @options = [candidate, options]
|
8
|
+
@rules = cached_rules + non_cached_rules
|
9
|
+
end
|
10
|
+
|
11
|
+
def cached_rules
|
12
|
+
cache_mode? ? cached_ability.send(:rules) : []
|
13
|
+
end
|
14
|
+
|
15
|
+
def non_cached_rules
|
16
|
+
no_cache_mode? ? non_cached_ability.send(:rules) : []
|
17
|
+
end
|
18
|
+
|
19
|
+
def cached_ability
|
20
|
+
CanTango::CachedAbility.new candidate, options
|
21
|
+
end
|
22
|
+
|
23
|
+
def non_cached_ability
|
24
|
+
CanTango::Ability.new candidate, options
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
def no_cache_mode?
|
30
|
+
modes.include?(:no_cache)
|
31
|
+
end
|
32
|
+
|
33
|
+
def cache_mode?
|
34
|
+
modes.include?(:cache)
|
35
|
+
end
|
36
|
+
|
37
|
+
def modes
|
38
|
+
CanTango.config.ability.modes
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -17,24 +17,20 @@ module CanTango
|
|
17
17
|
def get_ability_user user_type
|
18
18
|
user_meth = :"current_#{user_type}"
|
19
19
|
return AbilityUser.guest if !respond_to?(user_meth)
|
20
|
+
AbilityUser.resolve_user(send user_meth)
|
21
|
+
end
|
20
22
|
|
21
|
-
|
23
|
+
module AbilityUser
|
22
24
|
# test if current_xxx actually returns an account and not a user instance!
|
23
25
|
# if so call the #user method on the account
|
24
|
-
user = AbilityUser.resolve_user(user)
|
25
|
-
# return guest user if user is nil
|
26
|
-
user ? user : AbilityUser.guest
|
27
|
-
end
|
28
|
-
|
29
|
-
module AbilityUser
|
30
26
|
def self.resolve_user obj
|
31
|
-
return obj if
|
32
|
-
return obj.send(:user) if obj.respond_to? :user
|
33
|
-
|
27
|
+
return obj if is_user?(obj)
|
28
|
+
return resolve_user(obj.send(:user)) if obj.respond_to? :user
|
29
|
+
guest
|
34
30
|
end
|
35
31
|
|
36
|
-
def self.
|
37
|
-
::CanTango.config.users.
|
32
|
+
def self.is_user? user
|
33
|
+
::CanTango.config.users.registered_class? user.class
|
38
34
|
end
|
39
35
|
|
40
36
|
def self.guest
|
@@ -22,7 +22,8 @@ module CanTango
|
|
22
22
|
def any_user *types
|
23
23
|
types = types.flatten.select_labels.map(&:to_sym)
|
24
24
|
c_user = ::CanTango.config.users.registered.each do |user|
|
25
|
-
|
25
|
+
meth = :"current_#{user}"
|
26
|
+
send(meth) if respond_to?(meth) && (types.empty? || types.include?(user))
|
26
27
|
end.compact.first
|
27
28
|
c_user || guest_user
|
28
29
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module CanTango
|
2
2
|
module Api
|
3
3
|
module UserAccount
|
4
|
-
autoload_modules :Ability, :Can, :Scope
|
4
|
+
autoload_modules :Ability, :Can, :Scope, :Session
|
5
5
|
|
6
6
|
module All
|
7
7
|
def self.included base
|
8
|
-
[:Ability, :Can, :Scope].each do |api|
|
8
|
+
[:Ability, :Can, :Scope, :Session].each do |api|
|
9
9
|
base.send :include, clazz(api)
|
10
10
|
end
|
11
11
|
end
|
@@ -5,30 +5,35 @@ module CanTango
|
|
5
5
|
def user_account_ability user_account, options = {}
|
6
6
|
@current_ability ||= create_ability(user_account, ability_options.merge(options))
|
7
7
|
end
|
8
|
+
alias_method :account_ability, :user_account_ability
|
8
9
|
|
9
10
|
def current_account_ability user_type = :user
|
10
|
-
|
11
|
-
return guest_user_account if !respond_to?(account_meth)
|
12
|
-
|
13
|
-
user_account = send(account_meth)
|
14
|
-
return guest_user_account if !user_account
|
15
|
-
|
16
|
-
user_account_ability user_account
|
11
|
+
user_account_ability get_ability_user_account
|
17
12
|
end
|
18
13
|
|
19
14
|
protected
|
20
15
|
|
21
16
|
include CanTango::Api::Common
|
22
17
|
|
23
|
-
def
|
24
|
-
|
25
|
-
return AbilityAccount.guest if !respond_to?(
|
26
|
-
|
27
|
-
|
28
|
-
user_account ? user_account : AbilityAccount.guest
|
29
|
-
end
|
18
|
+
def get_ability_user_account user_type = :user
|
19
|
+
account_meth = :"current_#{user_type}_account"
|
20
|
+
return AbilityAccount.guest if !respond_to?(account_meth)
|
21
|
+
AbilityAccount.resolve_account(send account_meth)
|
22
|
+
end
|
30
23
|
|
31
24
|
module AbilityAccount
|
25
|
+
# test if current_xxx actually returns an account and not a user instance!
|
26
|
+
# if so call the #account method on the user
|
27
|
+
def self.resolve_account obj
|
28
|
+
return obj if AbilityAccount.is_account?(obj)
|
29
|
+
return resolve_account(obj.send(:account)) if obj.respond_to?(:account)
|
30
|
+
guest
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.is_account? account
|
34
|
+
::CanTango.config.user_accounts.registered_class? account.class
|
35
|
+
end
|
36
|
+
|
32
37
|
def self.guest
|
33
38
|
account = CanTango.config.guest.account
|
34
39
|
|
@@ -9,6 +9,14 @@ module CanTango
|
|
9
9
|
# end
|
10
10
|
def self.included(base)
|
11
11
|
::CanTango.config.user_accounts.registered.each do |account|
|
12
|
+
|
13
|
+
# by default alias call to current_xxx_account to current_xxx (devise user method) unless already defined!
|
14
|
+
unless base.methods.include? :"current_#{account}_account"
|
15
|
+
define_method :"current_#{account}_account" do
|
16
|
+
send :"current_#{account}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
12
20
|
base.class_eval %{
|
13
21
|
def #{account}_account_can? *args
|
14
22
|
current_account_ability(:#{account}).can?(*args)
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module CanTango
|
2
|
+
module Api
|
3
|
+
module UserAccount
|
4
|
+
module Session
|
5
|
+
def self.included(base)
|
6
|
+
::CanTango.config.user_accounts.registered.each do |type|
|
7
|
+
base.class_eval %{
|
8
|
+
def session_#{type}_account
|
9
|
+
current_#{type}_account if respond_to? :current_#{type}_account
|
10
|
+
guest_account
|
11
|
+
end
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# give me any logged in user or the guest user
|
17
|
+
def any_account *types
|
18
|
+
types = types.flatten.select_labels.map(&:to_sym)
|
19
|
+
c_account = ::CanTango.config.user_accounts.registered.each do |type|
|
20
|
+
meth = :"current_#{type}_account"
|
21
|
+
send(meth) if respond_to?(meth) && (types.empty? || types.include?(user))
|
22
|
+
end.compact.first
|
23
|
+
c_account || guest_account
|
24
|
+
end
|
25
|
+
|
26
|
+
def guest_account
|
27
|
+
CanTango.config.guest.account
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module CanTango
|
2
|
+
class CachedAbility < Ability
|
3
|
+
# Equivalent to a CanCan Ability#initialize call
|
4
|
+
# which executes all the permission logic
|
5
|
+
def initialize candidate, options = {}
|
6
|
+
raise "Candidate must be something!" if !candidate
|
7
|
+
@candidate, @options = candidate, options
|
8
|
+
|
9
|
+
return if cached_rules?
|
10
|
+
|
11
|
+
clear_rules!
|
12
|
+
permit_rules
|
13
|
+
|
14
|
+
execute_engines! if engines_on?
|
15
|
+
cache_rules!
|
16
|
+
end
|
17
|
+
|
18
|
+
def cached?
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
def permit_rules
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -6,15 +6,15 @@ module CanTango
|
|
6
6
|
autoload_modules :Categories
|
7
7
|
autoload_modules :Models, :Engines, :Ability
|
8
8
|
autoload_modules :User, :Guest, :UserAccount
|
9
|
-
autoload_modules :Roles, :RoleGroups, :Registry, :RoleRegistry, :HashRegistry, :PermitRegistry, :Factory
|
10
|
-
autoload_modules :SpecialPermits, :Autoload, :Adapters, :Permits, :Debug
|
9
|
+
autoload_modules :Roles, :RoleGroups, :Registry, :RoleRegistry, :HashRegistry, :PermitRegistry, :CandidateRegistry, :Factory
|
10
|
+
autoload_modules :SpecialPermits, :Autoload, :Adapters, :Permits, :Debug, :Modes
|
11
11
|
autoload_modules :Users, :UserAccounts
|
12
12
|
|
13
13
|
include Singleton
|
14
14
|
|
15
15
|
def ability
|
16
16
|
@ability ||= conf::Ability.instance
|
17
|
-
@ability.default_class ||= CanTango::
|
17
|
+
@ability.default_class ||= CanTango::AbilityExecutor
|
18
18
|
@ability
|
19
19
|
end
|
20
20
|
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'sugar-high/kind_of'
|
3
|
+
|
4
|
+
module CanTango
|
5
|
+
class Configuration
|
6
|
+
class CandidateRegistry
|
7
|
+
def register name, clazz
|
8
|
+
raise "first arg must be a label" if !name.kind_of_label?
|
9
|
+
raise "second arg must be a Class" if !clazz.kind_of? Class
|
10
|
+
name_registry.register name.to_sym
|
11
|
+
class_registry.register clazz
|
12
|
+
end
|
13
|
+
|
14
|
+
def registered
|
15
|
+
name_registry.registered
|
16
|
+
end
|
17
|
+
|
18
|
+
def registered_classes
|
19
|
+
class_registry.registered
|
20
|
+
end
|
21
|
+
|
22
|
+
def registered? name
|
23
|
+
name_registry.registered? name
|
24
|
+
end
|
25
|
+
|
26
|
+
def registered_class? name
|
27
|
+
class_registry.registered? name
|
28
|
+
end
|
29
|
+
|
30
|
+
def name_registry
|
31
|
+
NameRegistry.instance
|
32
|
+
end
|
33
|
+
|
34
|
+
def class_registry
|
35
|
+
ClassRegistry.instance
|
36
|
+
end
|
37
|
+
|
38
|
+
class NameRegistry < Registry
|
39
|
+
include Singleton
|
40
|
+
end
|
41
|
+
|
42
|
+
class ClassRegistry < Registry
|
43
|
+
include Singleton
|
44
|
+
|
45
|
+
def types
|
46
|
+
[Class]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module CanTango
|
2
2
|
class Configuration
|
3
3
|
class Categories < HashRegistry
|
4
|
-
|
4
|
+
|
5
5
|
include Singleton
|
6
6
|
|
7
7
|
def [] label
|
@@ -9,7 +9,7 @@ module CanTango
|
|
9
9
|
raise "Category '#{label}' either not exists or invalid!" if !models.kind_of?(Array)
|
10
10
|
models
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def category label, &block
|
14
14
|
cat = Category.new self[label]
|
15
15
|
yield cat if block
|
@@ -3,7 +3,7 @@ require 'singleton'
|
|
3
3
|
module CanTango
|
4
4
|
class Configuration
|
5
5
|
class Engines
|
6
|
-
autoload_modules :Permission, :Permit, :Cache, :Store, :Engine
|
6
|
+
autoload_modules :Permission, :Permit, :UserAc, :Cache, :Store, :Engine
|
7
7
|
|
8
8
|
include Singleton
|
9
9
|
include Enumerable
|
@@ -29,7 +29,7 @@ module CanTango
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def default_register
|
32
|
-
{:permit => CanTango::PermitEngine, :permission => CanTango::PermissionEngine }
|
32
|
+
{:permit => CanTango::PermitEngine, :permission => CanTango::PermissionEngine, :user_ac => CanTango::UserAcEngine }
|
33
33
|
end
|
34
34
|
|
35
35
|
# defines the order of execution of engine in ability
|
@@ -60,7 +60,7 @@ module CanTango
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def self.default_available
|
63
|
-
[:cache, :permission , :permit]
|
63
|
+
[:cache, :permission , :permit, :user_ac]
|
64
64
|
end
|
65
65
|
|
66
66
|
def default_available
|
@@ -79,6 +79,10 @@ module CanTango
|
|
79
79
|
available.each {|engine| send(engine).set state }
|
80
80
|
end
|
81
81
|
|
82
|
+
def any? state
|
83
|
+
available.any? {|engine| send(engine).send(:"#{state}?") if respond_to?(engine) }
|
84
|
+
end
|
85
|
+
|
82
86
|
def clear!
|
83
87
|
each {|engine| engine.reset! }
|
84
88
|
@registered = nil
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module CanTango
|
4
|
+
class Configuration
|
5
|
+
class Engines
|
6
|
+
class UserAc < Engine
|
7
|
+
include Singleton
|
8
|
+
include CanTango::Configuration::Modes
|
9
|
+
|
10
|
+
def modes
|
11
|
+
@modes ||= [:no_cache]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module CanTango
|
2
|
+
class Configuration
|
3
|
+
module Modes
|
4
|
+
def modes
|
5
|
+
@modes ||= [:cache, :no_cache]
|
6
|
+
end
|
7
|
+
|
8
|
+
def mode= mode_name
|
9
|
+
mode_name = mode_name.to_sym
|
10
|
+
raise ArgumentException, "Not a valid mode name" if !valid_mode_names.include? mode_name
|
11
|
+
@modes = (mode_name == :both) ? [:cache, :no_cache] : [mode_name]
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def valid_mode_names
|
17
|
+
[:cache, :no_cache, :both]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|