1# frozen_string_literal: true 2 3module Routing 4 module PseudonymizationHelper 5 class MaskHelper 6 QUERY_PARAMS_TO_NOT_MASK = %w[ 7 scope 8 state 9 ].freeze 10 11 def initialize(request_object, group, project) 12 @request = request_object 13 @group = group 14 @project = project 15 end 16 17 def mask_params 18 return default_root_url + @request.original_fullpath unless has_maskable_params? 19 20 masked_params = @request.path_parameters.to_h do |key, value| 21 case key 22 when :project_id 23 [key, "project#{@project&.id}"] 24 when :namespace_id, :group_id 25 namespace = @group || @project&.namespace 26 [key, "namespace#{namespace&.id}"] 27 when :id 28 [key, mask_id(value)] 29 else 30 [key, value] 31 end 32 end 33 34 Gitlab::Routing.url_helpers.url_for(masked_params.merge(params: masked_query_params)) 35 end 36 37 private 38 39 def mask_id(value) 40 if @request.path_parameters[:controller] == 'projects/blob' 41 ':repository_path' 42 elsif @request.path_parameters[:controller] == 'projects' 43 "project#{@project&.id}" 44 elsif @request.path_parameters[:controller] == 'groups' 45 "namespace#{@group&.id}" 46 else 47 value 48 end 49 end 50 51 def has_maskable_params? 52 request_params = @request.path_parameters.to_h 53 request_params.key?(:namespace_id) || request_params.key?(:group_id) || request_params.key?(:project_id) || request_params.key?(:id) || @request.query_string.present? 54 end 55 56 def masked_query_params 57 return {} unless @request.query_string.present? 58 59 query_string_hash = Rack::Utils.parse_nested_query(@request.query_string) 60 61 query_string_hash.keys.each do |key| 62 next if QUERY_PARAMS_TO_NOT_MASK.include?(key) 63 64 query_string_hash[key] = "masked_#{key}" 65 end 66 67 query_string_hash 68 end 69 70 def default_root_url 71 Gitlab::Routing.url_helpers.root_url(only_path: false) 72 end 73 end 74 75 def masked_page_url(group:, project:) 76 return unless Feature.enabled?(:mask_page_urls, type: :ops) 77 78 mask_helper = MaskHelper.new(request, group, project) 79 mask_helper.mask_params 80 81 # We rescue all exception for time being till we test this helper extensively. 82 # Check https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72864#note_711515501 83 rescue => e # rubocop:disable Style/RescueStandardError 84 Gitlab::ErrorTracking.track_exception(e, url: request.original_fullpath) 85 nil 86 end 87 end 88end 89