Let fine-grained tokens read blame and CODEOWNERS validation in GraphQL

What does this MR do and why?

A fine-grained personal access token gets null for RepositoryBlob.blame and Repository.validateCodeownerFile even when it can read the repository: the five types below them declare no authorize_granular_token directive, which denies them to any fine-grained token.

Each type is returned by one field only, under a parent that already authorizes the token, so each now declares skip_reason: :parent_authorizes and leaves authorization_todo.txt:

Type Returned only by Token checked at
Blame RepositoryBlob.blame RepositoryBlob, read_repository_blob
Groups Blame.groups RepositoryBlob, read_repository_blob
CommitData Groups.commitData RepositoryBlob, read_repository_blob
RepositoryCodeownerValidation (EE) Repository.validateCodeownerFile Repository, read_code
RepositoryCodeownerError (EE) RepositoryCodeownerValidation.validationErrors Repository, read_code

BlameResolver and Repository still check read_code for the user. REST blame takes read_repository_file_blame, in the same assignable permission as read_repository_blob, so a separate permission would not narrow anything.

References

  • Related to #593878, the remaining GraphQL gaps for fine-grained tokens.
  • !266025 (merged) gave QuickActionsStatus the same annotation.

I found this while working on gitlab-mcp-server.

Screenshots or screen recordings

Not applicable: no UI change.

How to set up and validate locally

  1. In a project with a CODEOWNERS file, create a fine-grained token with Project: Read, Code: Read and Repository: Read.

  2. Run with it:

    query { project(fullPath: "<path>") { repository {
      blobs(paths: ["README.md"]) { nodes { blame { groups { commitData { ageMapClass } } } } }
      validateCodeownerFile { total validationErrors { code } } } } }
  3. On master blame and validateCodeownerFile are null; on this branch they return data.

I ran steps 2 and 3 as the new examples in spec/requests/api/graphql/project/repository/blame_spec.rb and ee/spec/requests/api/graphql/project/repository/validate_codeowner_file_spec.rb, request specs that post step 2's blame and validateCodeownerFile fields with a fine-grained token: one that reads the project's code gets no data and no error on master's code and the data on this branch, and one with no permission gets no data on both.

Checks I ran (Ruby 3.3.11)
  • With master's types and todo list, the two changed specs give 10 examples, 2 failures: the two new examples.
  • Removing any one directive fails the example that reads its type.
  • On this branch, with the blobs, repository and CODEOWNERS validation specs: 81 examples, 0 failures, 5 pending.
  • gitlab:permissions:validate, RuboCop and the commit linter pass; gitlab:permissions:graphql:compile_docs changes nothing. Left to the pipeline: Ruby 3.4.10 and the FOSS run.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by José M. Requena Plens

Merge request reports

Loading
Loading