zuul 0.2.7 → 0.2.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/zuul/action_controller.rb +8 -4
- data/lib/zuul/action_controller/dsl.rb +6 -378
- data/lib/zuul/action_controller/dsl/actionable.rb +19 -0
- data/lib/zuul/action_controller/dsl/actions.rb +8 -0
- data/lib/zuul/action_controller/dsl/base.rb +254 -0
- data/lib/zuul/action_controller/dsl/permissions.rb +45 -0
- data/lib/zuul/action_controller/dsl/roles.rb +77 -0
- data/lib/zuul/active_record.rb +34 -35
- data/lib/zuul/active_record/context_accessors.rb +23 -0
- data/lib/zuul/active_record/permission.rb +2 -3
- data/lib/zuul/active_record/permission_role.rb +2 -3
- data/lib/zuul/active_record/permission_subject.rb +2 -3
- data/lib/zuul/active_record/role.rb +60 -15
- data/lib/zuul/active_record/role_subject.rb +2 -3
- data/lib/zuul/active_record/scope.rb +41 -1
- data/lib/zuul/active_record/subject.rb +213 -39
- data/lib/zuul/context.rb +15 -1
- data/lib/zuul/version.rb +1 -1
- data/spec/support/models.rb +11 -20
- data/spec/zuul/active_record/permission_role_spec.rb +1 -1
- data/spec/zuul/active_record/permission_subject_spec.rb +1 -1
- data/spec/zuul/active_record/role_spec.rb +10 -7
- data/spec/zuul/active_record/role_subject_spec.rb +1 -1
- data/spec/zuul/active_record/subject_spec.rb +14 -8
- data/spec/zuul/active_record_spec.rb +4 -4
- data/spec/zuul/context_spec.rb +350 -3
- metadata +66 -60
@@ -0,0 +1,23 @@
|
|
1
|
+
module Zuul
|
2
|
+
module ActiveRecord
|
3
|
+
# These are included in roles & permissions objects and assigned roles & permissions objects
|
4
|
+
# to provide easy access to the context for that object.
|
5
|
+
module ContextAccessors
|
6
|
+
def self.included(base)
|
7
|
+
base.send :attr_accessible, :context if ::Zuul.should_whitelist?
|
8
|
+
end
|
9
|
+
|
10
|
+
# Return a Zuul::Context object representing the context for the role
|
11
|
+
def context
|
12
|
+
Zuul::Context.new context_type, context_id
|
13
|
+
end
|
14
|
+
|
15
|
+
# Parse a context into an Zuul::Context and set the type and id
|
16
|
+
def context=(context)
|
17
|
+
context = Zuul::Context.parse(context)
|
18
|
+
self.context_type = context.klass
|
19
|
+
self.context_id = context.id
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -3,14 +3,13 @@ module Zuul
|
|
3
3
|
module Permission
|
4
4
|
def self.included(base)
|
5
5
|
base.send :extend, ClassMethods
|
6
|
-
base.send :include,
|
6
|
+
base.send :include, ContextAccessors
|
7
7
|
base.send :include, InstanceMethods
|
8
8
|
end
|
9
9
|
|
10
10
|
module ClassMethods
|
11
11
|
def self.extended(base)
|
12
|
-
base.send :attr_accessible, :context, :context_id, :context_type, :slug if ::Zuul
|
13
|
-
.should_whitelist?
|
12
|
+
base.send :attr_accessible, :context, :context_id, :context_type, :slug if ::Zuul.should_whitelist?
|
14
13
|
add_validations base
|
15
14
|
add_associations base
|
16
15
|
end
|
@@ -3,13 +3,12 @@ module Zuul
|
|
3
3
|
module PermissionRole
|
4
4
|
def self.included(base)
|
5
5
|
base.send :extend, ClassMethods
|
6
|
-
base.send :include,
|
6
|
+
base.send :include, ContextAccessors
|
7
7
|
end
|
8
8
|
|
9
9
|
module ClassMethods
|
10
10
|
def self.extended(base)
|
11
|
-
base.send :attr_accessible, :context, :context_id, :context_type, base.auth_scope.permission_foreign_key.to_sym, base.auth_scope.role_foreign_key.to_sym if ::Zuul
|
12
|
-
.should_whitelist?
|
11
|
+
base.send :attr_accessible, :context, :context_id, :context_type, base.auth_scope.permission_foreign_key.to_sym, base.auth_scope.role_foreign_key.to_sym if ::Zuul.should_whitelist?
|
13
12
|
add_validations base
|
14
13
|
add_associations base
|
15
14
|
end
|
@@ -3,13 +3,12 @@ module Zuul
|
|
3
3
|
module PermissionSubject
|
4
4
|
def self.included(base)
|
5
5
|
base.send :extend, ClassMethods
|
6
|
-
base.send :include,
|
6
|
+
base.send :include, ContextAccessors
|
7
7
|
end
|
8
8
|
|
9
9
|
module ClassMethods
|
10
10
|
def self.extended(base)
|
11
|
-
base.send :attr_accessible, :context, :context_id, :context_type, base.auth_scope.permission_foreign_key.to_sym, base.auth_scope.subject_foreign_key.to_sym if ::Zuul
|
12
|
-
.should_whitelist?
|
11
|
+
base.send :attr_accessible, :context, :context_id, :context_type, base.auth_scope.permission_foreign_key.to_sym, base.auth_scope.subject_foreign_key.to_sym if ::Zuul.should_whitelist?
|
13
12
|
add_validations base
|
14
13
|
add_associations base
|
15
14
|
end
|
@@ -3,15 +3,14 @@ module Zuul
|
|
3
3
|
module Role
|
4
4
|
def self.included(base)
|
5
5
|
base.send :extend, ClassMethods
|
6
|
-
base.send :include,
|
6
|
+
base.send :include, ContextAccessors
|
7
7
|
base.send :include, InstanceMethods
|
8
8
|
base.send :include, PermissionMethods if base.auth_scope.config.with_permissions
|
9
9
|
end
|
10
10
|
|
11
11
|
module ClassMethods
|
12
12
|
def self.extended(base)
|
13
|
-
base.send :attr_accessible, :context_id, :context_type, :level, :slug if ::Zuul
|
14
|
-
.should_whitelist?
|
13
|
+
base.send :attr_accessible, :context_id, :context_type, :level, :slug if ::Zuul.should_whitelist?
|
15
14
|
add_validations base
|
16
15
|
add_associations base
|
17
16
|
end
|
@@ -53,9 +52,9 @@ module Zuul
|
|
53
52
|
auth_scope do
|
54
53
|
context = Zuul::Context.parse(context)
|
55
54
|
target = target_permission(permission, context, force_context)
|
56
|
-
return false unless verify_target_context(target, context, force_context) && verify_target_context(self, context, false)
|
55
|
+
return false unless verify_target_context(target, context, force_context) && verify_target_context(self, context, false)
|
57
56
|
|
58
|
-
return permission_role_class.
|
57
|
+
return permission_role_class.find_or_create_by(role_foreign_key.to_sym => id, permission_foreign_key.to_sym => target.id, :context_type => context.class_name, :context_id => context.id)
|
59
58
|
end
|
60
59
|
end
|
61
60
|
|
@@ -70,7 +69,7 @@ module Zuul
|
|
70
69
|
target = target_permission(permission, context, force_context)
|
71
70
|
return false if target.nil?
|
72
71
|
|
73
|
-
assigned_permission =
|
72
|
+
assigned_permission = permission_role_for(target, context)
|
74
73
|
return false if assigned_permission.nil?
|
75
74
|
return assigned_permission.destroy
|
76
75
|
end
|
@@ -85,20 +84,18 @@ module Zuul
|
|
85
84
|
#
|
86
85
|
# The assigned context behaves the same way, in that if the permission is not found
|
87
86
|
# to belong to the role with the specified context, we look up the context chain.
|
88
|
-
#
|
89
|
-
# TODO add options to force context, not go up the chain
|
90
87
|
def has_permission?(permission, context=nil, force_context=nil)
|
91
88
|
auth_scope do
|
92
89
|
force_context ||= config.force_context
|
93
90
|
context = Zuul::Context.parse(context)
|
94
91
|
target = target_permission(permission, context, force_context)
|
95
92
|
return false if target.nil?
|
93
|
+
return permission_role_for?(target, context) if force_context
|
96
94
|
|
97
|
-
return true
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
end
|
95
|
+
return true if permission_role_for?(target, context)
|
96
|
+
return true if context.instance? && permission_role_for?(target, Zuul::Context.new(context.klass))
|
97
|
+
return true if !context.global? && permission_role_for?(target, Zuul::Context.new)
|
98
|
+
return false
|
102
99
|
end
|
103
100
|
end
|
104
101
|
alias_method :permission?, :has_permission?
|
@@ -111,9 +108,9 @@ module Zuul
|
|
111
108
|
force_context ||= config.force_context
|
112
109
|
context = Zuul::Context.parse(context)
|
113
110
|
if force_context
|
114
|
-
return
|
111
|
+
return role_permissions_for(context)
|
115
112
|
else
|
116
|
-
return
|
113
|
+
return role_permissions_within(context)
|
117
114
|
end
|
118
115
|
end
|
119
116
|
end
|
@@ -122,6 +119,54 @@ module Zuul
|
|
122
119
|
def permissions_for?(context=nil, force_context=nil)
|
123
120
|
permissions_for(context, force_context).count > 0
|
124
121
|
end
|
122
|
+
|
123
|
+
# Looks up a single permission_role based on the passed target and context
|
124
|
+
def permission_role_for(target, context)
|
125
|
+
auth_scope do
|
126
|
+
return permission_role_class.find_by(role_foreign_key.to_sym => id, permission_foreign_key.to_sym => target.id, :context_type => context.class_name, :context_id => context.id)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def permission_role_for?(target, context)
|
131
|
+
!permission_role_for(target, context).nil?
|
132
|
+
end
|
133
|
+
|
134
|
+
# Looks up all permissions for this role for the passed context
|
135
|
+
def role_permissions_for(context)
|
136
|
+
auth_scope do
|
137
|
+
return permission_class.joins(permission_role_plural_key).where(permission_role_plural_key => {role_foreign_key.to_sym => id, :context_type => context.class_name, :context_id => context.id})
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def role_permissions_for?(context)
|
142
|
+
!role_permissions_for(context).empty?
|
143
|
+
end
|
144
|
+
|
145
|
+
# Looks up all permissions for this role within the passed context (within the context chain)
|
146
|
+
def role_permissions_within(context)
|
147
|
+
auth_scope do
|
148
|
+
return permission_class.joins("
|
149
|
+
LEFT JOIN #{permission_roles_table_name}
|
150
|
+
ON #{permission_roles_table_name}.#{permission_foreign_key} = #{permissions_table_name}.id"
|
151
|
+
).where("
|
152
|
+
#{permission_roles_table_name}.#{role_foreign_key} = ?
|
153
|
+
AND (
|
154
|
+
#{permission_roles_table_name}.context_type #{sql_is_or_equal(context.class_name)} ?
|
155
|
+
OR #{permission_roles_table_name}.context_type IS NULL
|
156
|
+
)
|
157
|
+
AND (
|
158
|
+
#{permission_roles_table_name}.context_id #{sql_is_or_equal(context.id)} ?
|
159
|
+
OR #{permission_roles_table_name}.context_id IS NULL
|
160
|
+
)",
|
161
|
+
id,
|
162
|
+
context.class_name,
|
163
|
+
context.id)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def role_permissions_within?(context)
|
168
|
+
!role_permissions_within(context).empty?
|
169
|
+
end
|
125
170
|
end
|
126
171
|
end
|
127
172
|
end
|
@@ -3,13 +3,12 @@ module Zuul
|
|
3
3
|
module RoleSubject
|
4
4
|
def self.included(base)
|
5
5
|
base.send :extend, ClassMethods
|
6
|
-
base.send :include,
|
6
|
+
base.send :include, ContextAccessors
|
7
7
|
end
|
8
8
|
|
9
9
|
module ClassMethods
|
10
10
|
def self.extended(base)
|
11
|
-
base.send :attr_accessible, :context, :context_id, :context_type, base.auth_scope.role_foreign_key.to_sym, base.auth_scope.subject_foreign_key.to_sym if ::Zuul
|
12
|
-
.should_whitelist?
|
11
|
+
base.send :attr_accessible, :context, :context_id, :context_type, base.auth_scope.role_foreign_key.to_sym, base.auth_scope.subject_foreign_key.to_sym if ::Zuul.should_whitelist?
|
13
12
|
add_validations base
|
14
13
|
add_associations base
|
15
14
|
end
|
@@ -9,10 +9,49 @@ module Zuul
|
|
9
9
|
@config = config
|
10
10
|
@name = @config.scope
|
11
11
|
define_reflection_methods
|
12
|
-
super()
|
13
12
|
end
|
14
13
|
|
15
14
|
# Define dynamic reflection methods that reference the config to be used for subjects, roles, permissions and their associations.
|
15
|
+
#
|
16
|
+
# With a standard configuration, this defines the following methods:
|
17
|
+
#
|
18
|
+
# def subject_class : Subject
|
19
|
+
# def role_class : Role
|
20
|
+
# def permission_class : Permission
|
21
|
+
# def role_subject_class : RoleSubject
|
22
|
+
# def permission_role_class : PermissionRole
|
23
|
+
#
|
24
|
+
# def subject_class_name : 'Subject'
|
25
|
+
# def role_class_name : 'Role'
|
26
|
+
# def permission_class_name : 'Permission'
|
27
|
+
# def role_subject_class_name : 'RoleSubject'
|
28
|
+
# def permission_role_class_name : 'PermissionRole'
|
29
|
+
#
|
30
|
+
# def subject_table_name : 'subjects'
|
31
|
+
# def role_table_name : 'roles'
|
32
|
+
# def permission_table_name : 'permissions'
|
33
|
+
# def role_subject_table_name : 'role_subjects'
|
34
|
+
# def permission_role_table_name : 'permission_roles'
|
35
|
+
#
|
36
|
+
# def subject_singular_key : 'subject'
|
37
|
+
# def role_singular_key : 'role'
|
38
|
+
# def permission_singular_key : 'permission'
|
39
|
+
# def role_subject_singular_key : 'role_subject'
|
40
|
+
# def permission_role_singular_key : 'permission_role'
|
41
|
+
#
|
42
|
+
# def subject_plural_key : 'subjects'
|
43
|
+
# def role_plural_key : 'roles'
|
44
|
+
# def permission_plural_key : 'permissions'
|
45
|
+
# def role_subject_plural_key : 'role_subjects'
|
46
|
+
# def permission_role_plural_key : 'permission_roles'
|
47
|
+
#
|
48
|
+
# def subject_foreign_key : 'subject_id'
|
49
|
+
# def role_foreign_key : 'role_id'
|
50
|
+
# def permission_foreign_key : 'permission_id'
|
51
|
+
#
|
52
|
+
# All methods are also aliased to pluralized versions, so you can use `subject_class` or `subjects_class`, and
|
53
|
+
# when custom class names are used the methods are prefixed with those classes and aliased, so `user_class_name`
|
54
|
+
# is aliased to `subject_class_name`
|
16
55
|
def define_reflection_methods
|
17
56
|
|
18
57
|
# *_class_name, *_class, *_table_name methods for all classes
|
@@ -54,6 +93,7 @@ module Zuul
|
|
54
93
|
end
|
55
94
|
alias_method "#{class_type_name.pluralize}_plural_key", "#{class_type_name}_plural_key"
|
56
95
|
|
96
|
+
# These define aliases for custom class names, like user_class and user_table_name aliased to subject_class and subject_table_name
|
57
97
|
unless class_type.to_s.underscore == "#{class_name.to_s.underscore}_class"
|
58
98
|
%w(_class_name _class _table_name _singular_key _plural_key).each do |suffix|
|
59
99
|
alias_method "#{class_name.to_s.underscore.singularize}#{suffix}", "#{class_type_name}#{suffix}"
|
@@ -28,9 +28,8 @@ module Zuul
|
|
28
28
|
auth_scope do
|
29
29
|
context = Zuul::Context.parse(context)
|
30
30
|
target = target_role(role, context, force_context)
|
31
|
-
return false unless verify_target_context(target, context, force_context)
|
32
|
-
|
33
|
-
return role_subject_class.create(subject_foreign_key.to_sym => id, role_foreign_key.to_sym => target.id, :context_type => context.class_name, :context_id => context.id)
|
31
|
+
return false unless verify_target_context(target, context, force_context)
|
32
|
+
return role_subject_class.find_or_create_by(subject_foreign_key.to_sym => id, role_foreign_key.to_sym => target.id, :context_type => context.class_name, :context_id => context.id)
|
34
33
|
end
|
35
34
|
end
|
36
35
|
|
@@ -43,8 +42,8 @@ module Zuul
|
|
43
42
|
context = Zuul::Context.parse(context)
|
44
43
|
target = target_role(role, context, force_context)
|
45
44
|
return false if target.nil?
|
46
|
-
|
47
|
-
assigned_role =
|
45
|
+
|
46
|
+
assigned_role = role_subject_for(target, context)
|
48
47
|
return false if assigned_role.nil?
|
49
48
|
return assigned_role.destroy
|
50
49
|
end
|
@@ -64,11 +63,12 @@ module Zuul
|
|
64
63
|
context = Zuul::Context.parse(context)
|
65
64
|
target = target_role(role, context, force_context)
|
66
65
|
return false if target.nil?
|
66
|
+
return role_subject_for?(target, context) if force_context
|
67
67
|
|
68
|
-
return true
|
69
|
-
return
|
70
|
-
return true
|
71
|
-
return
|
68
|
+
return true if role_subject_for?(target, context)
|
69
|
+
return true if context.instance? && role_subject_for?(target, Zuul::Context.new(context.klass))
|
70
|
+
return true if !context.global? && role_subject_for?(target, Zuul::Context.new)
|
71
|
+
return false
|
72
72
|
end
|
73
73
|
end
|
74
74
|
alias_method :role?, :has_role?
|
@@ -86,12 +86,13 @@ module Zuul
|
|
86
86
|
context = Zuul::Context.parse(context)
|
87
87
|
target = target_role(role, context, force_context)
|
88
88
|
return false if target.nil?
|
89
|
-
|
90
89
|
return true if has_role?(target, context, force_context)
|
91
|
-
|
92
|
-
|
93
|
-
return true
|
94
|
-
return
|
90
|
+
return role_subject_or_higher_for?(target, context) if force_context
|
91
|
+
|
92
|
+
return true if role_subject_or_higher_for?(target, context)
|
93
|
+
return true if context.instance? && role_subject_or_higher_for?(target, Zuul::Context.new(context.klass))
|
94
|
+
return true if !context.global? && role_subject_or_higher_for?(target, Zuul::Context.new)
|
95
|
+
return false
|
95
96
|
end
|
96
97
|
end
|
97
98
|
alias_method :role_or_higher?, :has_role_or_higher?
|
@@ -113,19 +114,89 @@ module Zuul
|
|
113
114
|
force_context ||= config.force_context
|
114
115
|
context = Zuul::Context.parse(context)
|
115
116
|
if force_context
|
116
|
-
return
|
117
|
+
return subject_roles_for(context)
|
117
118
|
else
|
118
|
-
return
|
119
|
+
return subject_roles_within(context)
|
119
120
|
end
|
120
121
|
end
|
121
122
|
end
|
122
|
-
|
123
|
+
|
123
124
|
# Check whether the subject possesses any roles within the specified context.
|
124
125
|
#
|
125
126
|
# This includes any roles found by looking up the context chain.
|
126
127
|
def roles_for?(context=nil, force_context=nil)
|
127
128
|
roles_for(context, force_context).count > 0
|
128
129
|
end
|
130
|
+
|
131
|
+
# Looks up a single role subject based on the passed target and context
|
132
|
+
def role_subject_for(target, context)
|
133
|
+
auth_scope do
|
134
|
+
return role_subject_class.joins(role_table_name.singularize.to_sym).find_by(subject_foreign_key.to_sym => id, role_foreign_key.to_sym => target.id, :context_type => context.class_name, :context_id => context.id)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def role_subject_for?(target, context)
|
139
|
+
!role_subject_for(target, context).nil?
|
140
|
+
end
|
141
|
+
|
142
|
+
# Looks up a single role subject with a level greather than or equal to the target level based on the passed target and context
|
143
|
+
def role_subject_or_higher_for(target, context)
|
144
|
+
auth_scope do
|
145
|
+
return role_subject_class.joins(role_table_name.singularize.to_sym).where(subject_foreign_key.to_sym => id, :context_type => context.class_name, :context_id => context.id).where("
|
146
|
+
#{roles_table_name}.level >= ?
|
147
|
+
AND #{roles_table_name}.context_type #{sql_is_or_equal(target.context_type)} ?
|
148
|
+
AND #{roles_table_name}.context_id #{sql_is_or_equal(target.context_id)} ?",
|
149
|
+
target.level,
|
150
|
+
target.context_type,
|
151
|
+
target.context_id).limit(1).first
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def role_subject_or_higher_for?(target, context)
|
156
|
+
!role_subject_or_higher_for(target, context).nil?
|
157
|
+
end
|
158
|
+
|
159
|
+
# Looks up all roles for the subject for the passed context
|
160
|
+
def subject_roles_for(context)
|
161
|
+
auth_scope do
|
162
|
+
return role_class.joins(role_subject_plural_key).where("
|
163
|
+
#{role_subjects_table_name}.#{subject_foreign_key} = ?
|
164
|
+
AND #{role_subjects_table_name}.context_type #{sql_is_or_equal(context.class_name)} ?
|
165
|
+
AND #{role_subjects_table_name}.context_id #{sql_is_or_equal(context.id)} ?",
|
166
|
+
id,
|
167
|
+
context.class_name,
|
168
|
+
context.id)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def subject_roles_for?(context)
|
173
|
+
!subject_roles_for(context).empty?
|
174
|
+
end
|
175
|
+
|
176
|
+
# Looks up all roles for the subject within the passed context (within the context chain)
|
177
|
+
def subject_roles_within(context)
|
178
|
+
auth_scope do
|
179
|
+
return role_class.joins(role_subject_plural_key).where("
|
180
|
+
#{role_subjects_table_name}.#{subject_foreign_key} = ?
|
181
|
+
AND (
|
182
|
+
(
|
183
|
+
#{role_subjects_table_name}.context_type #{sql_is_or_equal(context.class_name)} ?
|
184
|
+
OR #{role_subjects_table_name}.context_type IS NULL
|
185
|
+
)
|
186
|
+
AND (
|
187
|
+
#{role_subjects_table_name}.context_id #{sql_is_or_equal(context.id)} ?
|
188
|
+
OR #{role_subjects_table_name}.context_id IS NULL
|
189
|
+
)
|
190
|
+
)",
|
191
|
+
id,
|
192
|
+
context.class_name,
|
193
|
+
context.id)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def subject_roles_within?(context)
|
198
|
+
!subject_roles_within(context).empty?
|
199
|
+
end
|
129
200
|
end
|
130
201
|
end
|
131
202
|
|
@@ -146,30 +217,29 @@ module Zuul
|
|
146
217
|
# Assigns a permission to a subject within the provided context.
|
147
218
|
#
|
148
219
|
# If a Permission object is provided it's used directly, otherwise if a
|
149
|
-
# permission slug is provided, the permission is looked up in the context
|
220
|
+
# permission slug is provided, the permission is looked up in the context
|
150
221
|
# chain by target_permission.
|
151
222
|
def assign_permission(permission, context=nil, force_context=nil)
|
152
223
|
auth_scope do
|
153
224
|
context = Zuul::Context.parse(context)
|
154
225
|
target = target_permission(permission, context, force_context)
|
155
|
-
return false unless verify_target_context(target, context, force_context)
|
156
|
-
|
157
|
-
return permission_subject_class.create(subject_foreign_key.to_sym => id, permission_foreign_key.to_sym => target.id, :context_type => context.class_name, :context_id => context.id)
|
226
|
+
return false unless verify_target_context(target, context, force_context)
|
227
|
+
return permission_subject_class.find_or_create_by(subject_foreign_key.to_sym => id, permission_foreign_key.to_sym => target.id, :context_type => context.class_name, :context_id => context.id)
|
158
228
|
end
|
159
229
|
end
|
160
230
|
|
161
231
|
# Removes a permission from a subject within the provided context.
|
162
232
|
#
|
163
233
|
# If a Permission object is provided it's used directly, otherwise if a
|
164
|
-
# permission slug is provided, the permission is looked up in the context
|
234
|
+
# permission slug is provided, the permission is looked up in the context
|
165
235
|
# chain by target_permission.
|
166
236
|
def unassign_permission(permission, context=nil, force_context=nil)
|
167
237
|
auth_scope do
|
168
238
|
context = Zuul::Context.parse(context)
|
169
239
|
target = target_permission(permission, context, force_context)
|
170
240
|
return false if target.nil?
|
171
|
-
|
172
|
-
assigned_permission =
|
241
|
+
|
242
|
+
assigned_permission = permission_subject_for(target, context)
|
173
243
|
return false if assigned_permission.nil?
|
174
244
|
return assigned_permission.destroy
|
175
245
|
end
|
@@ -179,7 +249,7 @@ module Zuul
|
|
179
249
|
# Checks whether a subject has a permission within the provided context.
|
180
250
|
#
|
181
251
|
# If a Permission object is provided it's used directly, otherwise if a
|
182
|
-
# permission slug is provided, the permission is looked up in the context
|
252
|
+
# permission slug is provided, the permission is looked up in the context
|
183
253
|
# chain by target_permission.
|
184
254
|
#
|
185
255
|
# The assigned context behaves the same way, in that if the permission is not found
|
@@ -192,17 +262,12 @@ module Zuul
|
|
192
262
|
context = Zuul::Context.parse(context)
|
193
263
|
target = target_permission(permission, context, force_context)
|
194
264
|
return false if target.nil?
|
265
|
+
return permission_role_or_subject_for?(target, context) if force_context
|
195
266
|
|
196
|
-
return true
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
end
|
201
|
-
|
202
|
-
return true unless (context.id.nil? && !force_context) || permission_role_class.where(role_foreign_key.to_sym => roles_for(context).map(&:id), permission_foreign_key.to_sym => target.id, :context_type => context.class_name, :context_id => context.id).first.nil?
|
203
|
-
return false if force_context
|
204
|
-
return true unless context.class_name.nil? || permission_role_class.where(role_foreign_key.to_sym => roles_for(context).map(&:id), permission_foreign_key.to_sym => target.id, :context_type => context.class_name, :context_id => nil).first.nil?
|
205
|
-
return !permission_role_class.where(role_foreign_key.to_sym => roles_for(context).map(&:id), permission_foreign_key.to_sym => target.id, :context_type => nil, :context_id => nil).first.nil?
|
267
|
+
return true if permission_role_or_subject_for?(target, context)
|
268
|
+
return true if context.instance? && permission_role_or_subject_for?(target, Zuul::Context.new(context.klass))
|
269
|
+
return true if !context.global? && permission_role_or_subject_for?(target, Zuul::Context.new)
|
270
|
+
return false
|
206
271
|
end
|
207
272
|
end
|
208
273
|
alias_method :permission?, :has_permission?
|
@@ -217,21 +282,130 @@ module Zuul
|
|
217
282
|
auth_scope do
|
218
283
|
force_context ||= config.force_context
|
219
284
|
context = Zuul::Context.parse(context)
|
285
|
+
roles = roles_for(context)
|
220
286
|
if force_context
|
221
|
-
return
|
287
|
+
return role_and_subject_permissions_for(context, roles)
|
222
288
|
else
|
223
|
-
return
|
289
|
+
return role_and_subject_permissions_within(context, roles)
|
224
290
|
end
|
225
291
|
end
|
226
292
|
end
|
227
|
-
|
293
|
+
|
228
294
|
# Check whether the subject possesses any permissions within the specified context.
|
229
295
|
#
|
230
296
|
# This includes permissions assigned directly to the subject or any roles possessed by
|
231
297
|
# the subject, as well as all permissions found by looking up the context chain.
|
232
298
|
def permissions_for?(context=nil, force_context=nil)
|
233
|
-
permissions_for(context, force_context).
|
299
|
+
!permissions_for(context, force_context).empty?
|
300
|
+
end
|
301
|
+
|
302
|
+
# Looks up a permission subject based on the passed target and context
|
303
|
+
def permission_subject_for(target, context)
|
304
|
+
auth_scope do
|
305
|
+
return permission_subject_class.find_by(subject_foreign_key.to_sym => id, permission_foreign_key.to_sym => target.id, :context_type => context.class_name, :context_id => context.id)
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def permission_subject_for?(target, context)
|
310
|
+
!permission_subject_for(target, context).nil?
|
311
|
+
end
|
312
|
+
|
313
|
+
# Looks up a permission role based on the passed target and context
|
314
|
+
def permission_role_for(target, context, proles=nil)
|
315
|
+
auth_scope do
|
316
|
+
proles ||= roles_for(context)
|
317
|
+
return permission_role_class.find_by(role_foreign_key.to_sym => proles.map(&:id), permission_foreign_key.to_sym => target.id, :context_type => context.class_name, :context_id => context.id)
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
def permission_role_for?(target, context, proles=nil)
|
322
|
+
!permission_role_for(target, context, proles).nil?
|
323
|
+
end
|
324
|
+
|
325
|
+
# Looks up a permission subject or role based on the passed target and context
|
326
|
+
def permission_role_or_subject_for(target, context, proles=nil)
|
327
|
+
permission_subject_for(target, context) || permission_role_for(target, context, proles)
|
234
328
|
end
|
329
|
+
|
330
|
+
def permission_role_or_subject_for?(target, context, proles=nil)
|
331
|
+
!permission_role_or_subject_for(target, context, proles).nil?
|
332
|
+
end
|
333
|
+
|
334
|
+
def role_and_subject_permissions_for(context, proles=nil)
|
335
|
+
auth_scope do
|
336
|
+
return permission_class.joins("
|
337
|
+
LEFT JOIN #{permission_roles_table_name}
|
338
|
+
ON #{permission_roles_table_name}.#{permission_foreign_key} = #{permissions_table_name}.id
|
339
|
+
LEFT JOIN #{permission_subjects_table_name}
|
340
|
+
ON #{permission_subjects_table_name}.#{permission_foreign_key} = #{permissions_table_name}.id"
|
341
|
+
).where("
|
342
|
+
(
|
343
|
+
#{permission_subjects_table_name}.#{subject_foreign_key} = ?
|
344
|
+
AND #{permission_subjects_table_name}.context_type #{sql_is_or_equal(context.class_name)} ?
|
345
|
+
AND #{permission_subjects_table_name}.context_id #{sql_is_or_equal(context.id)} ?
|
346
|
+
)
|
347
|
+
OR
|
348
|
+
(
|
349
|
+
#{permission_roles_table_name}.#{role_foreign_key} IN (?)
|
350
|
+
AND #{permission_roles_table_name}.context_type #{sql_is_or_equal(context.class_name)} ?
|
351
|
+
AND #{permission_roles_table_name}.context_id #{sql_is_or_equal(context.id)} ?
|
352
|
+
)",
|
353
|
+
id,
|
354
|
+
context.class_name,
|
355
|
+
context.id,
|
356
|
+
(proles || roles_for(context)).map(&:id),
|
357
|
+
context.class_name,
|
358
|
+
context.id)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
def role_and_subject_permissions_for?(context, proles=nil)
|
363
|
+
!role_and_subject_permissions_for(context, proles).empty?
|
364
|
+
end
|
365
|
+
|
366
|
+
def role_and_subject_permissions_within(context, proles=nil)
|
367
|
+
auth_scope do
|
368
|
+
return permission_class.joins("
|
369
|
+
LEFT JOIN #{permission_roles_table_name}
|
370
|
+
ON #{permission_roles_table_name}.#{permission_foreign_key} = #{permissions_table_name}.id
|
371
|
+
LEFT JOIN #{permission_subjects_table_name}
|
372
|
+
ON #{permission_subjects_table_name}.#{permission_foreign_key} = #{permissions_table_name}.id"
|
373
|
+
).where("
|
374
|
+
(
|
375
|
+
#{permission_subjects_table_name}.#{subject_foreign_key} = ?
|
376
|
+
AND (
|
377
|
+
#{permission_subjects_table_name}.context_type #{sql_is_or_equal(context.class_name)} ?
|
378
|
+
OR #{permission_subjects_table_name}.context_type IS NULL
|
379
|
+
)
|
380
|
+
AND (
|
381
|
+
#{permission_subjects_table_name}.context_id #{sql_is_or_equal(context.id)} ?
|
382
|
+
OR #{permission_subjects_table_name}.context_id IS NULL
|
383
|
+
)
|
384
|
+
)
|
385
|
+
OR (
|
386
|
+
#{permission_roles_table_name}.#{role_foreign_key} IN (?)
|
387
|
+
AND (
|
388
|
+
#{permission_roles_table_name}.context_type #{sql_is_or_equal(context.class_name)} ?
|
389
|
+
OR #{permission_roles_table_name}.context_type IS NULL
|
390
|
+
)
|
391
|
+
AND (
|
392
|
+
#{permission_roles_table_name}.context_id #{sql_is_or_equal(context.id)} ?
|
393
|
+
OR #{permission_roles_table_name}.context_id IS NULL
|
394
|
+
)
|
395
|
+
)",
|
396
|
+
id,
|
397
|
+
context.class_name,
|
398
|
+
context.id,
|
399
|
+
(proles || roles_for(context)).map(&:id),
|
400
|
+
context.class_name,
|
401
|
+
context.id)
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
def role_and_subject_permissions_within?(context, proles=nil)
|
406
|
+
!role_and_subject_permissions_within(context, proles).empty?
|
407
|
+
end
|
408
|
+
|
235
409
|
end
|
236
410
|
end
|
237
411
|
end
|