diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-08-17 12:10:45 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-08-17 12:10:45 +0300 |
commit | d0ed973bd7c3a5c79c2bf9673d9d7260f91dd961 (patch) | |
tree | d207a547e2a91e94027fa2f4118ae54342c624cf /lib/api/helpers.rb | |
parent | 2511fbfa2c2903d7168ff63527b79cb301c14ac0 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'lib/api/helpers.rb')
-rw-r--r-- | lib/api/helpers.rb | 46 |
1 files changed, 42 insertions, 4 deletions
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index b616f1b35b3..e1207e7e222 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -147,7 +147,7 @@ module API if id.is_a?(Integer) || id =~ INTEGER_ID_REGEX projects.find_by(id: id) elsif id.include?("/") - projects.find_by_full_path(id) + projects.find_by_full_path(id, follow_redirects: Feature.enabled?(:api_redirect_moved_projects)) end end # rubocop: enable CodeReuse/ActiveRecord @@ -157,10 +157,23 @@ module API return forbidden! unless authorized_project_scope?(project) - return project if can?(current_user, :read_project, project) - return unauthorized! if authenticate_non_public? + unless can?(current_user, read_project_ability, project) + return unauthorized! if authenticate_non_public? + + return not_found!('Project') + end + + if project_moved?(id, project) + return not_allowed!('Non GET methods are not allowed for moved projects') unless request.get? + + return redirect!(url_with_project_id(project)) + end + + project + end - not_found!('Project') + def read_project_ability + :read_project end def authorized_project_scope?(project) @@ -438,6 +451,13 @@ module API order_options end + # An error is raised to interrupt user's request and redirect them to the right route. + # The error! helper behaves similarly, but it cannot be used because it formats the + # response message. + def redirect!(location_url) + raise ::API::API::MovedPermanentlyError, location_url + end + # error helpers def forbidden!(reason = nil) @@ -837,6 +857,24 @@ module API def sanitize_id_param(id) id.present? ? id.to_i : nil end + + def project_moved?(id, project) + return false unless Feature.enabled?(:api_redirect_moved_projects) + return false unless id.is_a?(String) && id.include?('/') + return false if project.blank? || id == project.full_path + return false unless params[:id] == id + + true + end + + def url_with_project_id(project) + new_params = params.merge(id: project.id.to_s).transform_values { |v| v.is_a?(String) ? CGI.escape(v) : v } + new_path = GrapePathHelpers::DecoratedRoute.new(route).path_segments_with_values(new_params).join('/') + + Rack::Request.new(env).tap do |r| + r.path_info = "/#{new_path}" + end.url + end end end |