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.
Related Issues
Closes #581861
Edited by Ayush Billore