forest_liana 7.8.0 → 8.0.0.beta.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.
- 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
|