Return namespace markdown paths to fine-grained tokens
What does this MR do and why?
A fine-grained personal access token that can read a namespace gets null from markdownPaths, because its three types declare no authorize_granular_token directive. Their parent already checks the token, so each type now declares parent_authorizes: :read_namespace and leaves authorization_todo.txt:
| Types | Returned by | Token checked at |
|---|---|---|
GroupNamespaceMarkdownPaths, ProjectNamespaceMarkdownPaths, UserNamespaceMarkdownPaths |
Namespace.markdownPaths |
read_namespace on the group, project or user |
GroupNamespaceMarkdownPaths |
Group.markdownPaths |
read_group and read_namespace on the group |
The three types share the MarkdownPaths interface, so they declare one permission, and read_group cannot be checked on a project. Through group, markdownPaths therefore needs Namespace: Read as well as Group: Read.
The checks for the user stay as they are.
Why three types stay on the list
GroupNamespaceMetadata, GroupNamespaceLinks and ProjectNamespaceLinks stay on the list: hasProjects runs GroupProjectsFinder as the user, and the links return the user's notification email, RSS and calendar paths with a token derived from the user's feed token, and, for projects, an email address with the user's incoming email token.
This MR no longer changes ProjectNamespaceMetadata, UserNamespaceMetadata and UserNamespaceLinks, which stay on the list for a later MR: since !266839 (merged), gitlab:permissions:validate wants every type of the NamespaceMetadata and NamespacesLinkPaths interfaces to declare the same permission, and both interfaces also have types that stay on the list.
One domain, groups and namespaces, and one pattern, as suggested in !267273 (comment 4150389469).
References
- Part of #638957, the Organizations GraphQL types for fine-grained tokens.
- Related to #593878, the GraphQL gaps for fine-grained tokens.
- !267320 (merged) did the same for
NamespacePlanandGroupStats.
I found this while working on gitlab-mcp-server.
Screenshots or screen recordings
No UI change.
How to set up and validate locally
-
In a private group with a private project, create a fine-grained token with Namespace: Read for the project, and run:
query { namespace(fullPath: "<group>/<project>") { markdownPaths { uploadsPath } } } -
On master
markdownPathsisnull; on this branch it returns the project's uploads path. -
With a token with Group: Read for the group,
group(fullPath: "<group>") { markdownPaths { uploadsPath } }returns the group withmarkdownPathsset tonull. Add Namespace: Read to the token: it now returns the group's uploads path.
I ran these steps as examples of namespace_query_spec.rb and group_query_spec.rb, which also cover a group and a personal namespace through namespace.
Checks I ran (Ruby 3.3.11)
- With the parent's permission and
read_namespace, the paths arenullon master's code and return data on this branch; without them they staynull; throughgroup, a token withread_groupalone gets the group without the paths. - With master's types and todo list, the examples this MR adds give 9 examples, 4 failures: every example that expects the paths fails.
- On this branch, the two changed specs and the markdown paths type specs: 123 examples, 0 failures, and the 3 pending examples master already has.
gitlab:permissions:validate(with both documentation checks), RuboCop and the commit linter pass, and withskip_reason: :parent_authorizesinstead the task fails on the three types; thecompile_docstasks change 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.