Support wildcard values for content scope dimensions - #6114
Conversation
9f936dc to
a55dff9
Compare
a5b4639 to
ee0b3df
Compare
| // FIXME: this counts a wildcard content scope ("*") as a single scope and therefore under-reports the number of | ||
| // scopes a user can access. Replaced by a per-dimension summary in a follow-up pull request. |
There was a problem hiding this comment.
When merging this, we shouldn't release a new version until #6135 has been merged as well.
b444cca to
92b6d41
Compare
9caabab to
6364c63
Compare
6364c63 to
6e32162
Compare
6e32162 to
c5c3d5f
Compare
|
Needs human review — touches auth/permission logic. This introduces wildcard ( Generated by Claude Code |
e3da3d3 to
bdd9ce8
Compare
Allow getContentScopesForUser to return the wildcard value "*" as the value of a single content scope dimension to grant access to any value for that dimension. The wildcard is matched during the content scope check and does not need to be part of availableContentScopes. contentScopesCount still counts a wildcard as a single scope; that is corrected in a follow-up pull request. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JVwZJtKmfrQq2VZmPAB76j
Content scope checks compared scopes with a strict deep-equality check, so a
wildcard dimension ("*") was not handled. As a result:
- Impersonation broke: a user with a wildcard scope, or with access to all
content scopes (UserPermissions.allContentScopes, which was expanded to the
concrete available scopes), could not impersonate other users. getImpersonatedUser
returned undefined and the UI silently stayed on the current user.
- The allowed content scopes (scope picker) and the warnings scope check did not
recognize wildcard scopes either.
Handle the wildcard consistently:
- Represent access to all content scopes as a single scope that grants any value
("*") of every available dimension in the current user's permissions
(getPermissionsAndContentScopes), instead of expanding it to the concrete
available scopes. The content scopes list in the user permissions panel keeps
the concrete scopes.
- Introduce isScopeWithin as the wildcard-aware content scope check and use it for
isAllowed, the allowed content scopes, and the warnings scope check.
- Compare content scopes for impersonation (isEqualOrMorePermissions) with a
stricter check that also requires the current user's scope not to be narrower on
any dimension it constrains beyond the target.
- Make the admin's client-side isAllowed wildcard-aware as well.
bdd9ce8 to
e5a27dc
Compare
| "@comet/cms-api": minor | ||
| "@comet/cms-admin": minor |
There was a problem hiding this comment.
We must change the changeset from @comet/* to @dextinity/*:
| "@comet/cms-api": minor | |
| "@comet/cms-admin": minor | |
| "@dextinity/cms-api": minor | |
| "@dextinity/cms-admin": minor |
| const userContentScopes = await this.filterContentScopesForUser({ | ||
| user, | ||
| availableContentScopes, | ||
| includeContentScopesManual: true, | ||
| representAllContentScopesAsWildcard: true, | ||
| }); |
There was a problem hiding this comment.
For users with allContentScopes the API now returns [{ domain: "*", language: "*" }] instead of the concrete scopes. Should we mention this in the changeset?
| for (const contentScope of permission.contentScopes) { | ||
| if (!currentUserPermission.contentScopes.find((cs) => isEqual(cs, contentScope))) { | ||
| // The current user must have at least as much access as the target for this content scope. Unlike | ||
| // isScopeInTargetScope, the current user's scope must not be narrower on any dimension it constrains |
There was a problem hiding this comment.
nit: There is no isScopeInTargetScope, the function is called isScopeWithin.
| // isScopeInTargetScope, the current user's scope must not be narrower on any dimension it constrains | |
| // isScopeWithin, the current user's scope must not be narrower on any dimension it constrains |
Problem
Content scopes could only grant access to concrete dimension values that are part of
availableContentScopes. There was no way to grant a user access to any value of a single dimension (e.g. every language within a domain, or every product) without enumerating all values — which is not feasible for dimensions with many (potentially thousands) of values.Solution
getContentScopesForUsercan now use the wildcard value"*"as the value of a single content scope dimension to grant access to any value for that dimension. The wildcard is matched during the content scope check, so it does not need to be part ofavailableContentScopes.Example
Stacked pull request
This is layer 1 of 4 of a stacked pull request. Review and merge bottom-up (each layer targets the one above it):
main(Support wildcard values for content scope dimensions #6114)🤖 Generated with Claude Code