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