forest_liana 7.8.0 → 8.0.0.beta.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/forest_liana/actions_controller.rb +5 -3
- data/app/controllers/forest_liana/application_controller.rb +15 -0
- data/app/controllers/forest_liana/resources_controller.rb +31 -57
- data/app/controllers/forest_liana/smart_actions_controller.rb +44 -58
- data/app/controllers/forest_liana/stats_controller.rb +14 -58
- data/app/services/forest_liana/ability/exceptions/access_denied.rb +16 -0
- data/app/services/forest_liana/ability/exceptions/action_condition_error.rb +16 -0
- data/app/services/forest_liana/ability/exceptions/require_approval.rb +18 -0
- data/app/services/forest_liana/ability/exceptions/trigger_forbidden.rb +16 -0
- data/app/services/forest_liana/ability/fetch.rb +23 -0
- data/app/services/forest_liana/ability/permission/request_permission.rb +19 -0
- data/app/services/forest_liana/ability/permission/smart_action_checker.rb +71 -0
- data/app/services/forest_liana/ability/permission.rb +148 -0
- data/app/services/forest_liana/ability.rb +24 -0
- data/app/services/forest_liana/filters_parser.rb +7 -7
- data/app/services/forest_liana/leaderboard_stat_getter.rb +7 -7
- data/app/services/forest_liana/line_stat_getter.rb +8 -8
- data/app/services/forest_liana/pie_stat_getter.rb +17 -17
- data/app/services/forest_liana/stat_getter.rb +1 -2
- data/app/services/forest_liana/value_stat_getter.rb +7 -7
- data/lib/forest_liana/bootstrapper.rb +1 -1
- data/lib/forest_liana/version.rb +1 -1
- data/spec/dummy/lib/forest_liana/collections/island.rb +1 -1
- data/spec/requests/actions_controller_spec.rb +3 -4
- data/spec/requests/count_spec.rb +5 -9
- data/spec/requests/resources_spec.rb +55 -11
- data/spec/requests/stats_spec.rb +103 -42
- data/spec/services/forest_liana/ability/ability_spec.rb +48 -0
- data/spec/services/forest_liana/ability/permission/smart_action_checker_spec.rb +357 -0
- data/spec/services/forest_liana/ability/permission_spec.rb +332 -0
- data/spec/services/forest_liana/filters_parser_spec.rb +0 -12
- data/spec/services/forest_liana/line_stat_getter_spec.rb +9 -9
- data/spec/services/forest_liana/pie_stat_getter_spec.rb +7 -7
- data/spec/services/forest_liana/value_stat_getter_spec.rb +11 -11
- data/spec/spec_helper.rb +1 -0
- metadata +33 -17
- data/app/services/forest_liana/permissions_checker.rb +0 -223
- data/app/services/forest_liana/permissions_formatter.rb +0 -52
- data/app/services/forest_liana/permissions_getter.rb +0 -59
- data/spec/services/forest_liana/permissions_checker_acl_disabled_spec.rb +0 -713
- data/spec/services/forest_liana/permissions_checker_acl_enabled_spec.rb +0 -845
- data/spec/services/forest_liana/permissions_checker_live_queries_spec.rb +0 -175
- data/spec/services/forest_liana/permissions_formatter_spec.rb +0 -222
- data/spec/services/forest_liana/permissions_getter_spec.rb +0 -83
@@ -1,223 +0,0 @@
|
|
1
|
-
module ForestLiana
|
2
|
-
class PermissionsChecker
|
3
|
-
@@permissions_cached = Hash.new
|
4
|
-
@@renderings_cached = Hash.new
|
5
|
-
@@roles_acl_activated = false
|
6
|
-
|
7
|
-
@@expiration_in_seconds = (ENV['FOREST_PERMISSIONS_EXPIRATION_IN_SECONDS'] || 3600).to_i
|
8
|
-
|
9
|
-
ALLOWED_PERMISSION_LEVELS = %w[admin editor developer]
|
10
|
-
|
11
|
-
def initialize(resource, permission_name, rendering_id, user: nil, smart_action_request_info: nil, collection_list_parameters: Hash.new, query_request_info: nil)
|
12
|
-
@collection_name = resource.present? ? ForestLiana.name_for(resource) : nil
|
13
|
-
@permission_name = permission_name
|
14
|
-
@rendering_id = rendering_id
|
15
|
-
|
16
|
-
@user = user
|
17
|
-
@smart_action_request_info = smart_action_request_info
|
18
|
-
@collection_list_parameters = collection_list_parameters
|
19
|
-
@query_request_info = query_request_info
|
20
|
-
end
|
21
|
-
|
22
|
-
def is_authorized?
|
23
|
-
# User is still authorized if he already was and the permission has not expire
|
24
|
-
# if !have_permissions_expired && is_allowed
|
25
|
-
return true unless have_permissions_expired? || !is_allowed
|
26
|
-
|
27
|
-
fetch_permissions
|
28
|
-
is_allowed
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def fetch_permissions
|
34
|
-
permissions = ForestLiana::PermissionsGetter::get_permissions_for_rendering(@rendering_id)
|
35
|
-
@@roles_acl_activated = permissions['meta']['rolesACLActivated']
|
36
|
-
permissions['last_fetch'] = Time.now
|
37
|
-
if @@roles_acl_activated
|
38
|
-
@@permissions_cached = permissions
|
39
|
-
else
|
40
|
-
permissions['data'] = ForestLiana::PermissionsFormatter.convert_to_new_format(permissions['data'], @rendering_id)
|
41
|
-
@@permissions_cached[@rendering_id] = permissions
|
42
|
-
end
|
43
|
-
|
44
|
-
# NOTICE: Add stats permissions to the RenderingPermissions
|
45
|
-
permissions['data']['renderings'][@rendering_id]['stats'] = permissions['stats']
|
46
|
-
add_rendering_permissions_to_cache(permissions)
|
47
|
-
end
|
48
|
-
|
49
|
-
def add_rendering_permissions_to_cache(permissions)
|
50
|
-
permissions['data']['renderings'].keys.each { |rendering_id|
|
51
|
-
@@renderings_cached[rendering_id] = permissions['data']['renderings'][rendering_id]
|
52
|
-
@@renderings_cached[rendering_id]['last_fetch'] = Time.now
|
53
|
-
} if permissions['data']['renderings']
|
54
|
-
end
|
55
|
-
|
56
|
-
def is_allowed
|
57
|
-
permissions = get_permissions_content
|
58
|
-
|
59
|
-
# NOTICE: check liveQueries permissions
|
60
|
-
if @permission_name === 'liveQueries'
|
61
|
-
return ALLOWED_PERMISSION_LEVELS.include?(@user['permission_level']) || live_query_allowed?
|
62
|
-
elsif @permission_name === 'statWithParameters'
|
63
|
-
return ALLOWED_PERMISSION_LEVELS.include?(@user['permission_level']) || stat_with_parameters_allowed?
|
64
|
-
end
|
65
|
-
|
66
|
-
if permissions && permissions[@collection_name] &&
|
67
|
-
permissions[@collection_name]['collection']
|
68
|
-
if @permission_name === 'actions'
|
69
|
-
return smart_action_allowed?(permissions[@collection_name]['actions'])
|
70
|
-
else
|
71
|
-
if @permission_name === 'browseEnabled'
|
72
|
-
refresh_rendering_cache if rendering_cache_expired?
|
73
|
-
|
74
|
-
# NOTICE: In this case we need to check that that query is allowed
|
75
|
-
if @collection_list_parameters[:segmentQuery].present?
|
76
|
-
return false unless segment_query_allowed?
|
77
|
-
end
|
78
|
-
end
|
79
|
-
return is_user_allowed(permissions[@collection_name]['collection'][@permission_name])
|
80
|
-
end
|
81
|
-
else
|
82
|
-
false
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def get_segments_in_permissions
|
87
|
-
@@renderings_cached[@rendering_id] &&
|
88
|
-
@@renderings_cached[@rendering_id][@collection_name] &&
|
89
|
-
@@renderings_cached[@rendering_id][@collection_name]['segments']
|
90
|
-
end
|
91
|
-
|
92
|
-
def rendering_cache_expired?
|
93
|
-
return true unless @@renderings_cached[@rendering_id] && @@renderings_cached[@rendering_id]['last_fetch']
|
94
|
-
|
95
|
-
elapsed_seconds = date_difference_in_seconds(Time.now, @@renderings_cached[@rendering_id]['last_fetch'])
|
96
|
-
elapsed_seconds >= @@expiration_in_seconds
|
97
|
-
end
|
98
|
-
|
99
|
-
# This will happen only on rolesACLActivated (as segments cache will always be up to date on disabled)
|
100
|
-
def refresh_rendering_cache
|
101
|
-
permissions = ForestLiana::PermissionsGetter::get_permissions_for_rendering(@rendering_id, rendering_specific_only: true)
|
102
|
-
|
103
|
-
# NOTICE: Add stats permissions to the RenderingPermissions
|
104
|
-
permissions['data']['renderings'][@rendering_id]['stats'] = permissions['stats']
|
105
|
-
|
106
|
-
add_rendering_permissions_to_cache(permissions)
|
107
|
-
end
|
108
|
-
|
109
|
-
# When acl disabled permissions are stored and retrieved by rendering
|
110
|
-
def get_permissions
|
111
|
-
@@roles_acl_activated ? @@permissions_cached : @@permissions_cached[@rendering_id]
|
112
|
-
end
|
113
|
-
|
114
|
-
def get_permissions_content
|
115
|
-
permissions = get_permissions
|
116
|
-
permissions && permissions['data'] && permissions['data']['collections']
|
117
|
-
end
|
118
|
-
|
119
|
-
def get_live_query_permissions_content
|
120
|
-
permissions = @@renderings_cached[@rendering_id]
|
121
|
-
permissions && permissions['stats'] && permissions['stats']['queries']
|
122
|
-
end
|
123
|
-
|
124
|
-
def get_stat_with_parameters_content(statPermissionType)
|
125
|
-
permissions = @@renderings_cached[@rendering_id]
|
126
|
-
permissions && permissions['stats'] && permissions['stats'][statPermissionType]
|
127
|
-
end
|
128
|
-
|
129
|
-
def get_last_fetch
|
130
|
-
permissions = get_permissions
|
131
|
-
permissions && permissions['last_fetch']
|
132
|
-
end
|
133
|
-
|
134
|
-
def get_smart_action_permissions(smart_actions_permissions)
|
135
|
-
endpoint = @smart_action_request_info[:endpoint]
|
136
|
-
http_method = @smart_action_request_info[:http_method]
|
137
|
-
|
138
|
-
return nil unless endpoint && http_method
|
139
|
-
|
140
|
-
schema_smart_action = ForestLiana::Utils::BetaSchemaUtils.find_action_from_endpoint(@collection_name, endpoint, http_method)
|
141
|
-
|
142
|
-
schema_smart_action &&
|
143
|
-
schema_smart_action.name &&
|
144
|
-
smart_actions_permissions &&
|
145
|
-
smart_actions_permissions[schema_smart_action.name]
|
146
|
-
end
|
147
|
-
|
148
|
-
def is_user_allowed(permission_value)
|
149
|
-
return false if permission_value.nil?
|
150
|
-
return permission_value if permission_value.in? [true, false]
|
151
|
-
permission_value.include?(@user['id'].to_i)
|
152
|
-
end
|
153
|
-
|
154
|
-
def smart_action_allowed?(smart_actions_permissions)
|
155
|
-
smart_action_permissions = get_smart_action_permissions(smart_actions_permissions)
|
156
|
-
|
157
|
-
return false unless smart_action_permissions
|
158
|
-
|
159
|
-
is_user_allowed(smart_action_permissions['triggerEnabled'])
|
160
|
-
end
|
161
|
-
|
162
|
-
def segment_query_allowed?
|
163
|
-
segments_queries_permissions = get_segments_in_permissions
|
164
|
-
# NOTICE: The segmentQuery should be in the segments_queries_permissions
|
165
|
-
return false unless segments_queries_permissions
|
166
|
-
|
167
|
-
# Handle UNION queries made by the FRONT to display available actions on details view
|
168
|
-
unionQueries = @collection_list_parameters[:segmentQuery].split('/*MULTI-SEGMENTS-QUERIES-UNION*/ UNION ');
|
169
|
-
if unionQueries.length > 1
|
170
|
-
# Are unionQueries all included only in the allowed queries
|
171
|
-
return unionQueries.all? { |unionQuery| segments_queries_permissions.select { |query| query.gsub(/;\s*/i, '') === unionQuery }.length > 0 };
|
172
|
-
end
|
173
|
-
|
174
|
-
# NOTICE: @query_request_info matching an existing segment query
|
175
|
-
return segments_queries_permissions.include? @collection_list_parameters[:segmentQuery]
|
176
|
-
end
|
177
|
-
|
178
|
-
def live_query_allowed?
|
179
|
-
live_queries_permissions = get_live_query_permissions_content
|
180
|
-
|
181
|
-
return false unless live_queries_permissions
|
182
|
-
|
183
|
-
# NOTICE: @query_request_info matching an existing live query
|
184
|
-
return live_queries_permissions.include? @query_request_info
|
185
|
-
end
|
186
|
-
|
187
|
-
def stat_with_parameters_allowed?
|
188
|
-
permissionType = @query_request_info['type'].downcase + 's'
|
189
|
-
pool_permissions = get_stat_with_parameters_content(permissionType)
|
190
|
-
|
191
|
-
return false unless pool_permissions
|
192
|
-
|
193
|
-
# NOTICE: equivalent to Object.values in js & removes nil values
|
194
|
-
array_permission_infos = @query_request_info.values.select{ |x| !x.nil? }
|
195
|
-
|
196
|
-
# NOTICE: Is there any pool_permissions containing the array_permission_infos
|
197
|
-
return pool_permissions.any? {
|
198
|
-
|statPermission|
|
199
|
-
(array_permission_infos.all? { |info| statPermission.values.include?(info) });
|
200
|
-
}
|
201
|
-
end
|
202
|
-
|
203
|
-
def date_difference_in_seconds(date1, date2)
|
204
|
-
(date1 - date2).to_i
|
205
|
-
end
|
206
|
-
|
207
|
-
def have_permissions_expired?
|
208
|
-
last_fetch = get_last_fetch
|
209
|
-
return true unless last_fetch
|
210
|
-
|
211
|
-
elapsed_seconds = date_difference_in_seconds(Time.now, last_fetch)
|
212
|
-
elapsed_seconds >= @@expiration_in_seconds
|
213
|
-
end
|
214
|
-
|
215
|
-
# Used only for testing purpose
|
216
|
-
def self.empty_cache
|
217
|
-
@@permissions_cached = Hash.new
|
218
|
-
@@renderings_cached = Hash.new
|
219
|
-
@@roles_acl_activated = false
|
220
|
-
@@expiration_in_seconds = (ENV['FOREST_PERMISSIONS_EXPIRATION_IN_SECONDS'] || 3600).to_i
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
module ForestLiana
|
2
|
-
class PermissionsFormatter
|
3
|
-
class << PermissionsFormatter
|
4
|
-
# Convert old format permissions to unify PermissionsGetter code
|
5
|
-
def convert_to_new_format(permissions, rendering_id)
|
6
|
-
permissions_new_format = Hash.new
|
7
|
-
permissions_new_format['collections'] = Hash.new
|
8
|
-
permissions_new_format['renderings'] = Hash.new
|
9
|
-
permissions_new_format['renderings'][rendering_id] = Hash.new
|
10
|
-
permissions.keys.each { |collection_name|
|
11
|
-
permissions_new_format['collections'][collection_name] = {
|
12
|
-
'collection' => convert_collection_permissions_to_new_format(permissions[collection_name]['collection']),
|
13
|
-
'actions' => convert_actions_permissions_to_new_format(permissions[collection_name]['actions'])
|
14
|
-
}
|
15
|
-
|
16
|
-
permissions_new_format['renderings'][rendering_id][collection_name] = { 'segments' => permissions[collection_name]['segments'] }
|
17
|
-
}
|
18
|
-
|
19
|
-
permissions_new_format
|
20
|
-
end
|
21
|
-
|
22
|
-
def convert_collection_permissions_to_new_format(collection_permissions)
|
23
|
-
{
|
24
|
-
'browseEnabled' => collection_permissions['list'] || collection_permissions['searchToEdit'],
|
25
|
-
'readEnabled' => collection_permissions['show'],
|
26
|
-
'addEnabled' => collection_permissions['create'],
|
27
|
-
'editEnabled' => collection_permissions['update'],
|
28
|
-
'deleteEnabled' => collection_permissions['delete'],
|
29
|
-
'exportEnabled' => collection_permissions['export']
|
30
|
-
}
|
31
|
-
end
|
32
|
-
|
33
|
-
def convert_actions_permissions_to_new_format(actions_permissions)
|
34
|
-
return nil unless actions_permissions
|
35
|
-
|
36
|
-
actions_permissions_new_format = Hash.new
|
37
|
-
|
38
|
-
actions_permissions.keys.each { |action_name|
|
39
|
-
allowed = actions_permissions[action_name]['allowed']
|
40
|
-
users = actions_permissions[action_name]['users']
|
41
|
-
|
42
|
-
actions_permissions_new_format[action_name] = Hash.new
|
43
|
-
actions_permissions_new_format[action_name] = {
|
44
|
-
'triggerEnabled' => allowed && (users.nil? || users)
|
45
|
-
}
|
46
|
-
}
|
47
|
-
|
48
|
-
actions_permissions_new_format
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
module ForestLiana
|
2
|
-
class PermissionsGetter
|
3
|
-
class << PermissionsGetter
|
4
|
-
def get_permissions_api_route
|
5
|
-
'/liana/v3/permissions'
|
6
|
-
end
|
7
|
-
|
8
|
-
# Permission format example:
|
9
|
-
# collections => {
|
10
|
-
# {model_name} => {
|
11
|
-
# collection => {
|
12
|
-
# browseEnabled => true,
|
13
|
-
# readEnabled => true,
|
14
|
-
# editEnabled => true,
|
15
|
-
# addEnabled => true,
|
16
|
-
# deleteEnabled => true,
|
17
|
-
# exportEnabled => true,
|
18
|
-
# },
|
19
|
-
# actions => {
|
20
|
-
# {action_name} => {
|
21
|
-
# triggerEnabled => true,
|
22
|
-
# },
|
23
|
-
# },
|
24
|
-
# },
|
25
|
-
# },
|
26
|
-
# renderings => {
|
27
|
-
# {rendering_id} => {
|
28
|
-
# {collection_id} => {
|
29
|
-
# segments => ['query1', 'query2']
|
30
|
-
# }
|
31
|
-
# }
|
32
|
-
# }
|
33
|
-
# }
|
34
|
-
# With `rendering_specific_only` this returns only the permissions related data specific to the provided rendering
|
35
|
-
# For now this only includes scopes (but scopes are not used anymore in permissions)
|
36
|
-
def get_permissions_for_rendering(rendering_id, rendering_specific_only: false)
|
37
|
-
begin
|
38
|
-
query_parameters = { 'renderingId' => rendering_id }
|
39
|
-
query_parameters['renderingSpecificOnly'] = rendering_specific_only if rendering_specific_only
|
40
|
-
|
41
|
-
api_route = get_permissions_api_route
|
42
|
-
response = ForestLiana::ForestApiRequester.get(api_route, query: query_parameters)
|
43
|
-
|
44
|
-
if response.is_a?(Net::HTTPOK)
|
45
|
-
JSON.parse(response.body)
|
46
|
-
else
|
47
|
-
raise "Forest API returned an #{ForestLiana::Errors::HTTPErrorHelper.format(response)}"
|
48
|
-
end
|
49
|
-
rescue => exception
|
50
|
-
FOREST_REPORTER.report exception
|
51
|
-
FOREST_LOGGER.error 'Cannot retrieve the permissions from the Forest server.'
|
52
|
-
FOREST_LOGGER.error 'Which was caused by:'
|
53
|
-
ForestLiana::Errors::ExceptionHelper.recursively_print(exception, margin: ' ', is_error: true)
|
54
|
-
nil
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|