Skip to content

Commit 571f889

Browse files
authored
feat(security): secure segments queries (#495)
1 parent 846e6fb commit 571f889

File tree

9 files changed

+115
-170
lines changed

9 files changed

+115
-170
lines changed

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
forest_liana (7.0.0-beta.2)
4+
forest_liana (7.0.0.pre.beta.2)
55
arel-helpers
66
bcrypt
77
forestadmin-jsonapi-serializers (>= 0.14.0)

app/controllers/forest_liana/resources_controller.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ def get_collection_list_permission_info(user, collection_list_request)
249249
{
250250
user_id: user['id'],
251251
filters: collection_list_request[:filters],
252+
segmentQuery: collection_list_request[:segmentQuery],
252253
}
253254
end
254255
end

app/services/forest_liana/permissions_checker.rb

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ class PermissionsChecker
33
@@permissions_cached = Hash.new
44
@@renderings_cached = Hash.new
55
@@roles_acl_activated = false
6-
# TODO: handle cache scopes per rendering
6+
77
@@expiration_in_seconds = (ENV['FOREST_PERMISSIONS_EXPIRATION_IN_SECONDS'] || 3600).to_i
88

9-
def initialize(resource, permission_name, rendering_id, user_id: nil, smart_action_request_info: nil, collection_list_parameters: nil, query_request_info: nil)
9+
def initialize(resource, permission_name, rendering_id, user_id: nil, smart_action_request_info: nil, collection_list_parameters: Hash.new, query_request_info: nil)
1010

1111
@collection_name = resource.present? ? ForestLiana.name_for(resource) : nil
1212
@permission_name = permission_name
@@ -42,10 +42,10 @@ def fetch_permissions
4242

4343
# NOTICE: Add stats permissions to the RenderingPermissions
4444
permissions['data']['renderings'][@rendering_id]['stats'] = permissions['stats']
45-
add_scopes_to_cache(permissions)
45+
add_rendering_permissions_to_cache(permissions)
4646
end
4747

48-
def add_scopes_to_cache(permissions)
48+
def add_rendering_permissions_to_cache(permissions)
4949
permissions['data']['renderings'].keys.each { |rendering_id|
5050
@@renderings_cached[rendering_id] = permissions['data']['renderings'][rendering_id]
5151
@@renderings_cached[rendering_id]['last_fetch'] = Time.now
@@ -68,12 +68,11 @@ def is_allowed
6868
return smart_action_allowed?(permissions[@collection_name]['actions'])
6969
else
7070
if @permission_name === 'browseEnabled'
71-
refresh_scope_cache if scope_cache_expired?
72-
scope_permissions = get_scope_in_permissions
73-
if scope_permissions
74-
# NOTICE: current_scope will either contains conditions filter and
75-
# dynamic user values definition, or null for collection that does not use scopes
76-
return false unless are_scopes_valid?(scope_permissions)
71+
refresh_rendering_cache if rendering_cache_expired?
72+
73+
# NOTICE: In this case we need to check that that query is allowed
74+
if @collection_list_parameters[:segmentQuery].present?
75+
return false unless segment_query_allowed?
7776
end
7877
end
7978
return is_user_allowed(permissions[@collection_name]['collection'][@permission_name])
@@ -83,27 +82,27 @@ def is_allowed
8382
end
8483
end
8584

86-
def get_scope_in_permissions
85+
def get_segments_in_permissions
8786
@@renderings_cached[@rendering_id] &&
8887
@@renderings_cached[@rendering_id][@collection_name] &&
89-
@@renderings_cached[@rendering_id][@collection_name]['scope']
88+
@@renderings_cached[@rendering_id][@collection_name]['segments']
9089
end
9190

92-
def scope_cache_expired?
91+
def rendering_cache_expired?
9392
return true unless @@renderings_cached[@rendering_id] && @@renderings_cached[@rendering_id]['last_fetch']
9493

9594
elapsed_seconds = date_difference_in_seconds(Time.now, @@renderings_cached[@rendering_id]['last_fetch'])
9695
elapsed_seconds >= @@expiration_in_seconds
9796
end
9897

99-
# This will happen only on rolesACLActivated (as scope cache will always be up to date on disabled)
100-
def refresh_scope_cache
98+
# This will happen only on rolesACLActivated (as segments cache will always be up to date on disabled)
99+
def refresh_rendering_cache
101100
permissions = ForestLiana::PermissionsGetter::get_permissions_for_rendering(@rendering_id, rendering_specific_only: true)
102101

103102
# NOTICE: Add stats permissions to the RenderingPermissions
104103
permissions['data']['renderings'][@rendering_id]['stats'] = permissions['stats']
105104

106-
add_scopes_to_cache(permissions)
105+
add_rendering_permissions_to_cache(permissions)
107106
end
108107

109108
# When acl disabled permissions are stored and retrieved by rendering
@@ -159,11 +158,13 @@ def smart_action_allowed?(smart_actions_permissions)
159158
is_user_allowed(smart_action_permissions['triggerEnabled'])
160159
end
161160

162-
def are_scopes_valid?(scope_permissions)
163-
return ForestLiana::ScopeValidator.new(
164-
scope_permissions['filter'],
165-
scope_permissions['dynamicScopesValues']['users']
166-
).is_scope_in_request?(@collection_list_parameters)
161+
def segment_query_allowed?
162+
segments_queries_permissions = get_segments_in_permissions
163+
164+
return false unless segments_queries_permissions
165+
166+
# NOTICE: @query_request_info matching an existing segment query
167+
return segments_queries_permissions.include? @collection_list_parameters[:segmentQuery]
167168
end
168169

169170
def live_query_allowed?

app/services/forest_liana/permissions_formatter.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def convert_to_new_format(permissions, rendering_id)
1313
'actions' => convert_actions_permissions_to_new_format(permissions[collection_name]['actions'])
1414
}
1515

16-
permissions_new_format['renderings'][rendering_id][collection_name] = { 'scope' => permissions[collection_name]['scope'] }
16+
permissions_new_format['renderings'][rendering_id][collection_name] = { 'segments' => permissions[collection_name]['segments'] }
1717
}
1818

1919
permissions_new_format

app/services/forest_liana/permissions_getter.rb

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,7 @@ def get_permissions_api_route
2626
# rederings => {
2727
# {rendering_id} => {
2828
# {collection_id} => {
29-
# scope => {
30-
# dynamicScopesValues => {},
31-
# filter => {}
32-
# }
29+
# segments => ['query1', 'query2']
3330
# }
3431
# }
3532
# }

0 commit comments

Comments
 (0)