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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/forest_liana/actions_controller.rb +5 -3
  3. data/app/controllers/forest_liana/application_controller.rb +15 -0
  4. data/app/controllers/forest_liana/resources_controller.rb +31 -57
  5. data/app/controllers/forest_liana/smart_actions_controller.rb +44 -58
  6. data/app/controllers/forest_liana/stats_controller.rb +14 -58
  7. data/app/services/forest_liana/ability/exceptions/access_denied.rb +16 -0
  8. data/app/services/forest_liana/ability/exceptions/action_condition_error.rb +16 -0
  9. data/app/services/forest_liana/ability/exceptions/require_approval.rb +18 -0
  10. data/app/services/forest_liana/ability/exceptions/trigger_forbidden.rb +16 -0
  11. data/app/services/forest_liana/ability/fetch.rb +23 -0
  12. data/app/services/forest_liana/ability/permission/request_permission.rb +19 -0
  13. data/app/services/forest_liana/ability/permission/smart_action_checker.rb +71 -0
  14. data/app/services/forest_liana/ability/permission.rb +148 -0
  15. data/app/services/forest_liana/ability.rb +24 -0
  16. data/app/services/forest_liana/filters_parser.rb +7 -7
  17. data/app/services/forest_liana/leaderboard_stat_getter.rb +7 -7
  18. data/app/services/forest_liana/line_stat_getter.rb +8 -8
  19. data/app/services/forest_liana/pie_stat_getter.rb +17 -17
  20. data/app/services/forest_liana/stat_getter.rb +1 -2
  21. data/app/services/forest_liana/value_stat_getter.rb +7 -7
  22. data/lib/forest_liana/bootstrapper.rb +1 -1
  23. data/lib/forest_liana/version.rb +1 -1
  24. data/spec/dummy/lib/forest_liana/collections/island.rb +1 -1
  25. data/spec/requests/actions_controller_spec.rb +3 -4
  26. data/spec/requests/count_spec.rb +5 -9
  27. data/spec/requests/resources_spec.rb +55 -11
  28. data/spec/requests/stats_spec.rb +103 -42
  29. data/spec/services/forest_liana/ability/ability_spec.rb +48 -0
  30. data/spec/services/forest_liana/ability/permission/smart_action_checker_spec.rb +357 -0
  31. data/spec/services/forest_liana/ability/permission_spec.rb +332 -0
  32. data/spec/services/forest_liana/filters_parser_spec.rb +0 -12
  33. data/spec/services/forest_liana/line_stat_getter_spec.rb +9 -9
  34. data/spec/services/forest_liana/pie_stat_getter_spec.rb +7 -7
  35. data/spec/services/forest_liana/value_stat_getter_spec.rb +11 -11
  36. data/spec/spec_helper.rb +1 -0
  37. metadata +33 -17
  38. data/app/services/forest_liana/permissions_checker.rb +0 -223
  39. data/app/services/forest_liana/permissions_formatter.rb +0 -52
  40. data/app/services/forest_liana/permissions_getter.rb +0 -59
  41. data/spec/services/forest_liana/permissions_checker_acl_disabled_spec.rb +0 -713
  42. data/spec/services/forest_liana/permissions_checker_acl_enabled_spec.rb +0 -845
  43. data/spec/services/forest_liana/permissions_checker_live_queries_spec.rb +0 -175
  44. data/spec/services/forest_liana/permissions_formatter_spec.rb +0 -222
  45. 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