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.
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