Add granular pats decorator for project REST endpoints

Summary

This MR enables granular Personal Access Token (PAT) permissions for Projects REST API endpoints.

Endpoints and Permissions

Seq Endpoint Permission Boundary Test Added
1 GET /users/:user_id/projects read_user_project standalone
2 GET /users/:user_id/contributed_projects read_project_contributed standalone
3 GET /users/:user_id/starred_projects read_project_starred standalone
4 POST /projects/:id/restore restore_project project
5 GET /projects read_project standalone
6 POST /projects create_project standalone
7 POST /projects/user/:user_id create_user_project standalone
8 GET /projects/:id/share_locations read_project_share_location project
9 GET /projects/:id read_project project
10 POST /projects/:id/fork create_project_fork project
11 GET /projects/:id/forks read_project_fork project
12 GET /projects/:id/pages_access read_project_page_access project
13 PUT /projects/:id update_project project
14 POST /projects/:id/archive archive_project project
15 POST /projects/:id/unarchive archive_project project
16 POST /projects/:id/star star_project project
17 POST /projects/:id/unstar star_project project
18 GET /projects/:id/starrers read_project_starrer project
19 GET /projects/:id/languages read_project_language project
20 DELETE /projects/:id delete_project project
21 POST /projects/:id/fork/:forked_from_id mark_forked_project project
22 DELETE /projects/:id/fork delete_project_fork project
23 POST /projects/:id/share share_project project
24 DELETE /projects/:id/share/:group_id delete_project_group_share project
25 POST /projects/:id/import_project_members/:project_id import_member_project project
26 GET /projects/:id/users read_project_user project
27 GET /projects/:id/groups read_project_group project
28 GET /projects/:id/invited_groups read_project_invited_group project
29 POST /projects/:id/housekeeping housekeep_project project
30 POST /projects/:id/repository_size recalculate_project_storage project
31 PUT /projects/:id/transfer transfer_project project
32 GET /projects/:id/transfer_locations read_project_transfer_location project
33 GET /projects/:id/storage read_project_storage project

How to set up and validate locally

# Run this in a Rails console
user = User.find_by_username('root')

token = PersonalAccessTokens::CreateService.new(
  current_user: user, target_user: user,
  params: { expires_at: 1.month.from_now, scopes: ['granular'], granular: true, name: 'gPAT' }
).execute[:personal_access_token]

# Get a project
project = user.projects.first

# Create scope with the permission being tested
scope = Authz::GranularScope.new(namespace: project.project_namespace, permissions: [:read_project])

Authz::GranularScopeService.new(token).add_granular_scopes(scope)

# Test the API endpoint
IO.popen('pbcopy', 'w') { |f| f.puts \"curl \"http://#{Gitlab.host_with_port}/api/v4/projects/#{project.id}\" --request GET --header \"PRIVATE-TOKEN: #{token.token}\"\" }

Paste the URL in another terminal. It should succeed.

Closes #581861

Edited by Ayush Billore

Merge request reports

Loading