diff --git a/packages/forest_admin_agent/lib/forest_admin_agent/utils/caller_parser.rb b/packages/forest_admin_agent/lib/forest_admin_agent/utils/caller_parser.rb new file mode 100644 index 000000000..1946265b3 --- /dev/null +++ b/packages/forest_admin_agent/lib/forest_admin_agent/utils/caller_parser.rb @@ -0,0 +1,68 @@ +require 'jwt' +require 'active_support' +require 'active_support/time' + +module ForestAdminAgent + module Utils + class CallerParser + include ForestAdminDatasourceToolkit::Exceptions + + def initialize(args) + @args = args + @token_data = {} + end + + def parse + validate_headers + @token_data = decode_token + @token_data[:timezone] = extract_timezone + @token_data[:request] = { ip: @args[:headers]['action_dispatch.remote_ip'].to_s } + project, environment = extract_forest_context + @token_data[:project] = project + @token_data[:environment] = environment + + ForestAdminDatasourceToolkit::Components::Caller.new(**@token_data.transform_keys(&:to_sym)) + end + + private + + def validate_headers + return if @args.dig(:headers, 'HTTP_AUTHORIZATION') + + raise Http::Exceptions::HttpException.new( + 401, + 'You must be logged in to access at this resource.' + ) + end + + def extract_timezone + timezone = @args[:params]['timezone'] + raise ForestException, 'Missing timezone' unless timezone + raise ForestException, "Invalid timezone: #{timezone}" unless Time.find_zone(timezone) + + timezone + end + + def decode_token + token = @args[:headers]['HTTP_AUTHORIZATION'].split[1] + JWT.decode( + token, + Facades::Container.cache(:auth_secret), + true, + { algorithm: 'HS256' } + )[0].tap { |data| data.delete('exp') } + end + + def extract_forest_context + match_data = %r{https://[^/]*/([^/]*)/([^/]*)/([^/]*)}.match(@args[:headers]['HTTP_FOREST_CONTEXT_URL']) + return [nil, nil] unless match_data + + project = match_data[1] + environment = match_data[2] + [project, environment] + rescue StandardError + [nil, nil] + end + end + end +end diff --git a/packages/forest_admin_agent/lib/forest_admin_agent/utils/query_string_parser.rb b/packages/forest_admin_agent/lib/forest_admin_agent/utils/query_string_parser.rb index af88332ff..3771bd1af 100644 --- a/packages/forest_admin_agent/lib/forest_admin_agent/utils/query_string_parser.rb +++ b/packages/forest_admin_agent/lib/forest_admin_agent/utils/query_string_parser.rb @@ -1,7 +1,3 @@ -require 'jwt' -require 'active_support' -require 'active_support/time' - module ForestAdminAgent module Utils class QueryStringParser @@ -31,30 +27,7 @@ def self.parse_condition_tree(collection, args) end def self.parse_caller(args) - unless args.dig(:headers, 'HTTP_AUTHORIZATION') - raise Http::Exceptions::HttpException.new( - 401, - 'You must be logged in to access at this resource.' - ) - end - - timezone = args[:params]['timezone'] - raise ForestException, 'Missing timezone' unless timezone - - raise ForestException, "Invalid timezone: #{timezone}" unless Time.find_zone(timezone) - - token = args[:headers]['HTTP_AUTHORIZATION'].split[1] - token_data = JWT.decode( - token, - Facades::Container.cache(:auth_secret), - true, - { algorithm: 'HS256' } - )[0] - token_data.delete('exp') - token_data[:timezone] = timezone - token_data[:request] = { ip: args[:headers]['action_dispatch.remote_ip'].to_s } - - Caller.new(**token_data.transform_keys(&:to_sym)) + CallerParser.new(args).parse end def self.parse_projection(collection, args) diff --git a/packages/forest_admin_datasource_customizer/spec/shared/caller.rb b/packages/forest_admin_datasource_customizer/spec/shared/caller.rb index 69f3ec8a1..16f3ef6b8 100644 --- a/packages/forest_admin_datasource_customizer/spec/shared/caller.rb +++ b/packages/forest_admin_datasource_customizer/spec/shared/caller.rb @@ -11,7 +11,9 @@ timezone: 'Europe/Paris', permission_level: 'admin', role: 'dev', - request: { ip: '127.0.0.1' } + request: { ip: '127.0.0.1' }, + project: 'terminator', + environment: 'Development' ) end end diff --git a/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/caller.rb b/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/caller.rb index c44eaf2ac..a67347390 100644 --- a/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/caller.rb +++ b/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/caller.rb @@ -14,7 +14,9 @@ def initialize( timezone:, permission_level:, role: nil, - request: {} + request: {}, + project: nil, + environment: nil ) @id = id @email = email @@ -27,6 +29,8 @@ def initialize( @permission_level = permission_level @role = role @request = request + @project = project + @environment = environment end end end diff --git a/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/query/aggregation.rb b/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/query/aggregation.rb index 30cf67ace..331d3b075 100644 --- a/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/query/aggregation.rb +++ b/packages/forest_admin_datasource_toolkit/lib/forest_admin_datasource_toolkit/components/query/aggregation.rb @@ -46,7 +46,12 @@ def replace_fields end def override(**args) - Aggregation.new(**to_h, **args) + params = to_h.merge(args) + Aggregation.new( + operation: params[:operation], + field: params[:field], + groups: params[:groups] + ) end def apply(records, timezone, limit = nil) diff --git a/packages/forest_admin_datasource_toolkit/spec/lib/forest_admin_datasource_toolkit/components/contracts/collection_contract_spec.rb b/packages/forest_admin_datasource_toolkit/spec/lib/forest_admin_datasource_toolkit/components/contracts/collection_contract_spec.rb index 4d46d0671..da05e7ae8 100644 --- a/packages/forest_admin_datasource_toolkit/spec/lib/forest_admin_datasource_toolkit/components/contracts/collection_contract_spec.rb +++ b/packages/forest_admin_datasource_toolkit/spec/lib/forest_admin_datasource_toolkit/components/contracts/collection_contract_spec.rb @@ -19,7 +19,9 @@ module Contracts timezone: 'Europe/Paris', role: 1, permission_level: 'admin', - request: { ip: '127.0.0.1' } + request: { ip: '127.0.0.1' }, + project: 'foo', + environment: 'Development' ) end diff --git a/packages/forest_admin_datasource_toolkit/spec/shared/caller.rb b/packages/forest_admin_datasource_toolkit/spec/shared/caller.rb index 69f3ec8a1..16f3ef6b8 100644 --- a/packages/forest_admin_datasource_toolkit/spec/shared/caller.rb +++ b/packages/forest_admin_datasource_toolkit/spec/shared/caller.rb @@ -11,7 +11,9 @@ timezone: 'Europe/Paris', permission_level: 'admin', role: 'dev', - request: { ip: '127.0.0.1' } + request: { ip: '127.0.0.1' }, + project: 'terminator', + environment: 'Development' ) end end