fix(attachmentV4): allow elevated users to access attchment endpoint#2699
fix(attachmentV4): allow elevated users to access attchment endpoint#2699Junjiequan wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- The repeated
can(Action.Attachment*Endpoint, Attachment)calls in each branch could be consolidated (e.g., compute a single boolean for attachment endpoint access and then apply the threecanrules once) to reduce duplication and risk of divergence between branches. - The condition
this.accessGroups?.attachment.includes("#all")will throw ifaccessGroupsexists butattachmentis undefined; consider using optional chaining onattachmentas well (e.g.,this.accessGroups?.attachment?.includes("#all")) or normalizingattachmentto an empty array.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The repeated `can(Action.Attachment*Endpoint, Attachment)` calls in each branch could be consolidated (e.g., compute a single boolean for attachment endpoint access and then apply the three `can` rules once) to reduce duplication and risk of divergence between branches.
- The condition `this.accessGroups?.attachment.includes("#all")` will throw if `accessGroups` exists but `attachment` is undefined; consider using optional chaining on `attachment` as well (e.g., `this.accessGroups?.attachment?.includes("#all")`) or normalizing `attachment` to an empty array.
## Individual Comments
### Comment 1
<location path="src/casl/casl-ability.factory.ts" line_range="426" />
<code_context>
can(Action.AttachmentCreateEndpoint, Attachment);
can(Action.AttachmentUpdateEndpoint, Attachment);
can(Action.AttachmentDeleteEndpoint, Attachment);
+ } else if (
+ user.currentGroups.some((g) =>
+ this.accessGroups?.attachmentPrivileged.includes(g),
</code_context>
<issue_to_address>
**issue (complexity):** Consider consolidating the three repeated group-check branches into a single attachment-access predicate and shared capability block to simplify the authorization logic and remove duplication.
You can reduce branching complexity by factoring the three equivalent branches into a single predicate and a single capability block.
Currently:
```ts
if (user.currentGroups.some((g) => this.accessGroups?.admin.includes(g))) {
can(Action.AttachmentCreateEndpoint, Attachment);
can(Action.AttachmentUpdateEndpoint, Attachment);
can(Action.AttachmentDeleteEndpoint, Attachment);
} else if (
user.currentGroups.some((g) =>
this.accessGroups?.attachmentPrivileged.includes(g),
)
) {
can(Action.AttachmentCreateEndpoint, Attachment);
can(Action.AttachmentUpdateEndpoint, Attachment);
can(Action.AttachmentDeleteEndpoint, Attachment);
} else if (
user.currentGroups.some((g) =>
this.accessGroups?.attachment.includes(g),
) ||
this.accessGroups?.attachment.includes("#all")
) {
can(Action.AttachmentCreateEndpoint, Attachment);
can(Action.AttachmentUpdateEndpoint, Attachment);
can(Action.AttachmentDeleteEndpoint, Attachment);
}
```
Suggested refactor (same behavior, less duplication):
```ts
const hasAttachmentAccess =
user.currentGroups.some((g) => this.accessGroups?.admin.includes(g)) ||
user.currentGroups.some((g) =>
this.accessGroups?.attachmentPrivileged.includes(g),
) ||
user.currentGroups.some((g) =>
this.accessGroups?.attachment.includes(g),
) ||
this.accessGroups?.attachment.includes("#all");
if (hasAttachmentAccess) {
can(Action.AttachmentCreateEndpoint, Attachment);
can(Action.AttachmentUpdateEndpoint, Attachment);
can(Action.AttachmentDeleteEndpoint, Attachment);
}
```
If you want to keep the comments about which groups grant access, you can move that into a small helper for readability:
```ts
private hasAttachmentAccess(user: User): boolean {
const { admin, attachmentPrivileged, attachment } = this.accessGroups ?? {};
return (
user.currentGroups.some((g) => admin?.includes(g)) || // ADMIN_GROUPS
user.currentGroups.some((g) => attachmentPrivileged?.includes(g)) || // ATTACHMENT_PRIVILEGED_GROUPS
user.currentGroups.some((g) => attachment?.includes(g)) || // ATTACHMENT_GROUPS
attachment?.includes("#all")
);
}
// usage:
if (this.hasAttachmentAccess(user)) {
can(Action.AttachmentCreateEndpoint, Attachment);
can(Action.AttachmentUpdateEndpoint, Attachment);
can(Action.AttachmentDeleteEndpoint, Attachment);
}
```
This keeps all existing functionality while making the authorization logic easier to scan and maintain.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
|
Are there tests for these endpoints with normal user accounts? It seems like you should have caught this bug without my help. |
|
@jl-wynen |
Co-authored-by: Copilot <copilot@github.com>
f88611b to
866074b
Compare
| // | ||
| can(Action.AttachmentCreateEndpoint, Attachment); | ||
| can(Action.AttachmentUpdateEndpoint, Attachment); | ||
| can(Action.AttachmentDeleteEndpoint, Attachment); |
There was a problem hiding this comment.
Shouldn't this be cannot?
As it is now, attachment privileged and attachment do not have difference.
There was a problem hiding this comment.
Endpoint wise there shouldnt be differences, both group users should be able to access the endpoint. The difference should be in the instance level
There was a problem hiding this comment.
OK.
I will consolidate the two if branches.
There was a problem hiding this comment.
I suggeste we open a new PR and consolidates all of the ifs that has same permission logic. Instead of just do it for the attachmentEndpointAccess
Description
This PR adds back the missing CASL ability check for elevated attachment group users to access attachment endpoints.
Motivation
Fixes
Changes:
Tests included
Documentation
official documentation info
Summary by Sourcery
Bug Fixes: