Skip to content

refactor: casl factory - policies#2811

Open
HayenNico wants to merge 1 commit into
masterfrom
refactor-casl-factory-policies
Open

refactor: casl factory - policies#2811
HayenNico wants to merge 1 commit into
masterfrom
refactor-casl-factory-policies

Conversation

@HayenNico

@HayenNico HayenNico commented Jun 27, 2026

Copy link
Copy Markdown
Member

Description

Subsection of PR #2748 for policies.

This refactors the policyEndpointAccess function in CaslAbilityFactory, extracting the ability builder into a separate module and adding policyAccess in CaslAbilityFactory.

Changes:

  • Replace CaslAbilityFactory.policyEndpointAccess with CaslAbilityFactory.policyAccess
  • Code for CaslAbilityFactory.policyAccess is factored out into new module PolicyAbility

Tests included

  • Included for each change/fix?
  • Passing?

Documentation

  • swagger documentation updated (required for API changes)
  • official documentation updated

Summary by Sourcery

Extract policy access ability building into a dedicated injectable and update consumers to use the new policy access entrypoint.

Enhancements:

  • Refactor policy access logic from CaslAbilityFactory into a dedicated PolicyAbility service used via CaslAbilityFactory.policyAccess.
  • Register PolicyAbility in the CASL module and adjust the policies controller to consume the new policy access method.

@HayenNico HayenNico requested a review from a team as a code owner June 27, 2026 11:58

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • In PolicyAbility, accessGroups is left untyped and initialized from config in the constructor; consider typing it explicitly as AccessGroupsType | undefined to match existing patterns and make the code safer and clearer.
  • The logic change from the previous policyEndpointAccess (which used if/else if) to two independent if blocks in PolicyAbility.buildAbility means users in both delete and admin/policy groups now get both delete and CRUD permissions instead of only delete; double-check that this change in privilege behavior is intentional.
  • Since PolicyAbility currently only exposes buildAbility, you might consider making this a stateless helper (or a pure function taking accessGroups as input) and injecting accessGroups from CaslAbilityFactory instead, which would reduce configuration lookups and keep all CASL wiring in one place.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `PolicyAbility`, `accessGroups` is left untyped and initialized from config in the constructor; consider typing it explicitly as `AccessGroupsType | undefined` to match existing patterns and make the code safer and clearer.
- The logic change from the previous `policyEndpointAccess` (which used `if`/`else if`) to two independent `if` blocks in `PolicyAbility.buildAbility` means users in both delete and admin/policy groups now get both delete and CRUD permissions instead of only delete; double-check that this change in privilege behavior is intentional.
- Since `PolicyAbility` currently only exposes `buildAbility`, you might consider making this a stateless helper (or a pure function taking `accessGroups` as input) and injecting `accessGroups` from `CaslAbilityFactory` instead, which would reduce configuration lookups and keep all CASL wiring in one place.

## Individual Comments

### Comment 1
<location path="src/casl/abilities/policies.ability.ts" line_range="21-25" />
<code_context>
+    this.accessGroups =
+      this.configService.get<AccessGroupsType>("accessGroups");
+  }
+  private accessGroups;
+
+  buildAbility(user: JWTUser): MongoAbility<PossibleAbilities, Conditions> {
</code_context>
<issue_to_address>
**suggestion:** Type the `accessGroups` property to match `AccessGroupsType` for stronger safety.

Declare this as `private accessGroups?: AccessGroupsType;` to match the `ConfigService.get<AccessGroupsType>` call, avoid the implicit `any`, and catch type mismatches at compile time.

```suggestion
  constructor(private configService: ConfigService) {
    this.accessGroups =
      this.configService.get<AccessGroupsType>("accessGroups");
  }

  private accessGroups?: AccessGroupsType;
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +21 to +25
constructor(private configService: ConfigService) {
this.accessGroups =
this.configService.get<AccessGroupsType>("accessGroups");
}
private accessGroups;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Type the accessGroups property to match AccessGroupsType for stronger safety.

Declare this as private accessGroups?: AccessGroupsType; to match the ConfigService.get<AccessGroupsType> call, avoid the implicit any, and catch type mismatches at compile time.

Suggested change
constructor(private configService: ConfigService) {
this.accessGroups =
this.configService.get<AccessGroupsType>("accessGroups");
}
private accessGroups;
constructor(private configService: ConfigService) {
this.accessGroups =
this.configService.get<AccessGroupsType>("accessGroups");
}
private accessGroups?: AccessGroupsType;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant