feat(api-token): allow org-level tokens to manage project-scoped tokens#2811
feat(api-token): allow org-level tokens to manage project-scoped tokens#2811Piskoo wants to merge 4 commits intochainloop-dev:mainfrom
Conversation
Signed-off-by: Sylwester Piskozub <sylwesterpiskozub@gmail.com>
Signed-off-by: Sylwester Piskozub <sylwesterpiskozub@gmail.com>
There was a problem hiding this comment.
1 issue found across 5 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="app/controlplane/internal/service/apitoken_test.go">
<violation number="1" location="app/controlplane/internal/service/apitoken_test.go:70">
P2: This test duplicates the service's authorization logic inline rather than calling `svc.List()`. It will pass even if the actual `List` method is broken or its authorization logic changes, providing false confidence. The same issue applies to `TestAPITokenService_Revoke_OrgTokenCannotRevokeOrgTokens` below. Consider using mocks for `APITokenUseCase` (e.g., via an interface or testify mock) so the tests exercise the real service methods end-to-end.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| ctx := context.Background() | ||
| ctx = entities.WithCurrentAPIToken(ctx, tc.token) | ||
|
|
||
| scope := mapTokenScope(pb.APITokenServiceListRequest_SCOPE_UNSPECIFIED) |
There was a problem hiding this comment.
P2: This test duplicates the service's authorization logic inline rather than calling svc.List(). It will pass even if the actual List method is broken or its authorization logic changes, providing false confidence. The same issue applies to TestAPITokenService_Revoke_OrgTokenCannotRevokeOrgTokens below. Consider using mocks for APITokenUseCase (e.g., via an interface or testify mock) so the tests exercise the real service methods end-to-end.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At app/controlplane/internal/service/apitoken_test.go, line 70:
<comment>This test duplicates the service's authorization logic inline rather than calling `svc.List()`. It will pass even if the actual `List` method is broken or its authorization logic changes, providing false confidence. The same issue applies to `TestAPITokenService_Revoke_OrgTokenCannotRevokeOrgTokens` below. Consider using mocks for `APITokenUseCase` (e.g., via an interface or testify mock) so the tests exercise the real service methods end-to-end.</comment>
<file context>
@@ -0,0 +1,132 @@
+ ctx := context.Background()
+ ctx = entities.WithCurrentAPIToken(ctx, tc.token)
+
+ scope := mapTokenScope(pb.APITokenServiceListRequest_SCOPE_UNSPECIFIED)
+ if token := entities.CurrentAPIToken(ctx); token != nil && token.ProjectID == nil {
+ scope = biz.APITokenScopeProject
</file context>
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="app/controlplane/pkg/biz/apitoken_integration_test.go">
<violation number="1" location="app/controlplane/pkg/biz/apitoken_integration_test.go:153">
P2: Unsafe `append` may mutate `s.APIToken.DefaultAuthzPolicies`. In Go, `append` reuses the underlying array when capacity permits, which would silently corrupt the shared `DefaultAuthzPolicies` field. The production code already has a safe helper `withOrgLevelPolicies` (apitoken.go:47) — consider using it here, or copy the slice first.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| } | ||
|
|
||
| // Org-level API tokens can only create project-scoped tokens | ||
| if token := entities.CurrentAPIToken(ctx); token != nil && token.ProjectID == nil { |
There was a problem hiding this comment.
how come we didn't need to change anything in the middleware or in authz.go?
|
|
||
| // OrgLevelAPITokenPolicies are additional policies granted only to org-level tokens. | ||
| // They allow managing project-scoped tokens. | ||
| var OrgLevelAPITokenPolicies = []*authz.Policy{ |
| } | ||
|
|
||
| // withOrgLevelPolicies returns a new slice with OrgLevelAPITokenPolicies appended. | ||
| func withOrgLevelPolicies(policies []*authz.Policy) []*authz.Policy { |
There was a problem hiding this comment.
this doesn't look that useful?
|
|
||
| // Org-level tokens additionally get project-level API token management policies | ||
| if projectID == nil && orgUUID != nil { | ||
| policies = withOrgLevelPolicies(policies) |
There was a problem hiding this comment.
I'd personally just add the policies here, being very explicit saying that org level API tokens can manage project tokens.
| // OrgLevelAPITokenPolicies are additional policies granted only to org-level tokens. | ||
| // They allow managing project-scoped tokens. | ||
| var OrgLevelAPITokenPolicies = []*authz.Policy{ | ||
| authz.PolicyAPITokenCreate, |
There was a problem hiding this comment.
I'd call this PolicyProjectLevelAPITokenCreate since it's only project level tokens
| } | ||
|
|
||
| // Org-level API tokens can only create project-scoped tokens | ||
| if token := entities.CurrentAPIToken(ctx); token != nil && token.ProjectID == nil { |
There was a problem hiding this comment.
this is something that could be done with Enforce otherwise the policies are worthless no?
Org-level API tokens can now create, list, and revoke project-scoped API tokens.
🟢 Create project-scoped token with org-scoped token
🔴 Create project-scoped token with project-scoped token
🔴 Create org-scoped token with project-scoped token
🟢 List tokens with org-scoped token
🔴 List tokens with project-scoped token
🔴 Revoke project-scoped token with project-scoped token
🟢 Revoke project-scoped token with org-scoped token
🟢 Create project-scoped token with org-scoped token that was created in the past (List and revoke also works)
Closes #2808