Self-service API for consent management - #302
Conversation
|
Warning Review limit reached
More reviews will be available in 26 minutes and 12 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more credits in the billing tab to continue. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughThis PR adds a new consent API module with parent and child Maven POMs, OpenAPI 2.0 definitions for Sequence Diagram(s)sequenceDiagram
participant Client
participant MeApiServiceImpl
participant UserConsentService
participant PrivilegedConsentManager
Client->>MeApiServiceImpl: REST request on /me/consents/*
MeApiServiceImpl->>UserConsentService: invoke consent operation
UserConsentService->>PrivilegedConsentManager: consent management call
PrivilegedConsentManager-->>UserConsentService: result
UserConsentService-->>MeApiServiceImpl: DTO or API error
MeApiServiceImpl-->>Client: HTTP response
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.common/pom.xml (1)
30-35: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDeclare the carbon context dependency directly.
ConsentManagementServiceHolderusesorg.wso2.carbon.context.PrivilegedCarbonContextincomponents/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.common/src/main/java/org/wso2/carbon/identity/api/user/consent/common/util/ConsentManagementServiceHolder.java(Lines 22-45), but this module only declaresorg.wso2.carbon.consent.mgt.core. Depending on a transitive dependency for a directly imported type makes this module brittle to upstream dependency changes. Add the owning carbon core artifact here withprovidedscope.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.common/pom.xml` around lines 30 - 35, The consent common module is importing PrivilegedCarbonContext directly in ConsentManagementServiceHolder, but the POM only declares the consent management core dependency and relies on a transitive carbon context class. Update the dependencies in this module to explicitly add the owning carbon core artifact with provided scope so ConsentManagementServiceHolder has a direct, stable dependency and does not depend on upstream transitive resolution.components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/main/java/org/wso2/carbon/identity/api/user/consent/v1/impl/core/UserConsentService.java (1)
170-174: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse a locale-aware case conversion instead of suppressing the finding.
node.getOperation().toLowerCase()relies on the default locale (theDM_CONVERT_CASEfinding suppressed infindbugs-exclude-filter.xml). Fixing the root cause withtoLowerCase(Locale.ENGLISH)makes the comparison deterministic and lets you drop the corresponding FindBugs exclusion (Lines 65-72 offindbugs-exclude-filter.xml).Proposed change
- String op = node.getOperation() != null ? node.getOperation().toLowerCase() : ""; + String op = node.getOperation() != null + ? node.getOperation().toLowerCase(Locale.ENGLISH) : "";Add
import java.util.Locale;.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/main/java/org/wso2/carbon/identity/api/user/consent/v1/impl/core/UserConsentService.java` around lines 170 - 174, The consent filter validation in UserConsentService uses a locale-dependent case conversion when normalizing node.getOperation(), so update that comparison to use a fixed locale such as Locale.ENGLISH and add the needed import. After fixing the root cause in the UserConsentService operation check, remove the corresponding DM_CONVERT_CASE suppression from findbugs-exclude-filter.xml since it should no longer be necessary.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/main/resources/consent.yaml`:
- Around line 577-585: The limit query parameter in limitQueryParam only
enforces a minimum, so add a maximum bound to cap the page size and prevent
oversized fetches. Update the OpenAPI parameter definition for limit in
consent.yaml to include an appropriate maximum, and make sure the value remains
consistent with how listReceipts(..., resolvedLimit + 1) consumes the parameter.
---
Nitpick comments:
In
`@components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.common/pom.xml`:
- Around line 30-35: The consent common module is importing
PrivilegedCarbonContext directly in ConsentManagementServiceHolder, but the POM
only declares the consent management core dependency and relies on a transitive
carbon context class. Update the dependencies in this module to explicitly add
the owning carbon core artifact with provided scope so
ConsentManagementServiceHolder has a direct, stable dependency and does not
depend on upstream transitive resolution.
In
`@components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/main/java/org/wso2/carbon/identity/api/user/consent/v1/impl/core/UserConsentService.java`:
- Around line 170-174: The consent filter validation in UserConsentService uses
a locale-dependent case conversion when normalizing node.getOperation(), so
update that comparison to use a fixed locale such as Locale.ENGLISH and add the
needed import. After fixing the root cause in the UserConsentService operation
check, remove the corresponding DM_CONVERT_CASE suppression from
findbugs-exclude-filter.xml since it should no longer be necessary.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 0c2cdcc0-b0b6-4cf8-8724-b3dffefea6da
⛔ Files ignored due to path filters (15)
components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/gen/java/org/wso2/carbon/identity/api/user/consent/v1/MeApi.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/gen/java/org/wso2/carbon/identity/api/user/consent/v1/MeApiService.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/gen/java/org/wso2/carbon/identity/api/user/consent/v1/factories/MeApiServiceFactory.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/gen/java/org/wso2/carbon/identity/api/user/consent/v1/model/AuthorizationRequest.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/gen/java/org/wso2/carbon/identity/api/user/consent/v1/model/AuthorizationResponse.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/gen/java/org/wso2/carbon/identity/api/user/consent/v1/model/ConsentCreateResponse.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/gen/java/org/wso2/carbon/identity/api/user/consent/v1/model/ConsentInput.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/gen/java/org/wso2/carbon/identity/api/user/consent/v1/model/ConsentPurposeInput.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/gen/java/org/wso2/carbon/identity/api/user/consent/v1/model/ConsentPurposeResponse.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/gen/java/org/wso2/carbon/identity/api/user/consent/v1/model/ConsentResponse.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/gen/java/org/wso2/carbon/identity/api/user/consent/v1/model/ConsentSummary.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/gen/java/org/wso2/carbon/identity/api/user/consent/v1/model/ConsentValidationResponse.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/gen/java/org/wso2/carbon/identity/api/user/consent/v1/model/ConsentedElement.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/gen/java/org/wso2/carbon/identity/api/user/consent/v1/model/ElementRef.javais excluded by!**/gen/**components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/gen/java/org/wso2/carbon/identity/api/user/consent/v1/model/Error.javais excluded by!**/gen/**
📒 Files selected for processing (10)
components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.common/pom.xmlcomponents/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.common/src/main/java/org/wso2/carbon/identity/api/user/consent/common/util/ConsentManagementServiceHolder.javacomponents/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/pom.xmlcomponents/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/main/java/org/wso2/carbon/identity/api/user/consent/v1/impl/MeApiServiceImpl.javacomponents/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/main/java/org/wso2/carbon/identity/api/user/consent/v1/impl/core/UserConsentService.javacomponents/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/main/java/org/wso2/carbon/identity/api/user/consent/v1/impl/factories/UserConsentServiceFactory.javacomponents/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/main/resources/consent.yamlcomponents/org.wso2.carbon.identity.api.user.consent/pom.xmlfindbugs-exclude-filter.xmlpom.xml
There was a problem hiding this comment.
Pull request overview
This pull request adds a new user self-service consent management component to identity-api-user, exposing /me/consents REST endpoints (Swagger + generated JAX-RS stubs) and implementing consent lifecycle operations via PrivilegedConsentManager.
Changes:
- Adds a new
org.wso2.carbon.identity.api.user.consentcomponent (common + v1) and wires it into the parent build. - Introduces a Swagger 2.0 API definition (
consent.yaml) and generated REST API/model classes for consent operations. - Implements core consent logic in
UserConsentService, including ownership checks, authorization flows, filtering, and pagination parameters.
Reviewed changes
Copilot reviewed 25 out of 25 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| pom.xml | Adds consent-management dependency/version and registers the new consent component module. |
| findbugs-exclude-filter.xml | Adds a suppression for locale-sensitive case conversion warnings in listConsents. |
| components/org.wso2.carbon.identity.api.user.consent/pom.xml | Defines the new consent parent component (common + v1 modules). |
| components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/main/resources/consent.yaml | Defines the self-service consent REST API contract (paths, operations, schemas, params). |
| components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/main/java/.../MeApiServiceImpl.java | Implements the REST layer by delegating to UserConsentService. |
| components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/main/java/.../factories/UserConsentServiceFactory.java | Creates and exposes a singleton UserConsentService backed by PrivilegedConsentManager. |
| components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/main/java/.../core/UserConsentService.java | Core consent lifecycle logic (create/list/get/revoke/authorize/validate) scoped to logged-in user. |
| components/.../src/gen/java/.../model/Error.java | Generated API error model for consent endpoints. |
| components/.../src/gen/java/.../model/ElementRef.java | Generated model for PII element references in consent requests. |
| components/.../src/gen/java/.../model/ConsentValidationResponse.java | Generated model for consent validation response. |
| components/.../src/gen/java/.../model/ConsentSummary.java | Generated model for consent list summary items. |
| components/.../src/gen/java/.../model/ConsentResponse.java | Generated model for detailed consent retrieval response. |
| components/.../src/gen/java/.../model/ConsentPurposeResponse.java | Generated model for purposes in consent responses. |
| components/.../src/gen/java/.../model/ConsentPurposeInput.java | Generated model for purposes in consent create requests. |
| components/.../src/gen/java/.../model/ConsentInput.java | Generated request model for creating consents. |
| components/.../src/gen/java/.../model/ConsentedElement.java | Generated model for consented elements in responses. |
| components/.../src/gen/java/.../model/ConsentCreateResponse.java | Generated model for consent create response payload. |
| components/.../src/gen/java/.../model/AuthorizationResponse.java | Generated model for authorization entries in consent responses. |
| components/.../src/gen/java/.../model/AuthorizationRequest.java | Generated model for authorize request payload. |
| components/.../src/gen/java/.../MeApiService.java | Generated service interface for consent /me endpoints. |
| components/.../src/gen/java/.../MeApi.java | Generated JAX-RS resource for consent /me endpoints. |
| components/.../src/gen/java/.../factories/MeApiServiceFactory.java | Generated factory wiring the REST resource to the implementation. |
| components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/pom.xml | Builds the v1 consent REST API module and includes generated sources. |
| components/.../consent.common/src/main/java/.../ConsentManagementServiceHolder.java | Locates PrivilegedConsentManager from the OSGi context. |
| components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.common/pom.xml | Declares the common consent module and its dependency on consent management core. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (subjectId.equals(receipt.getPiiPrincipalId())) { | ||
| return; | ||
| } | ||
| if (findUserAuthorization(authorizations, subjectId) != null) { | ||
| return; | ||
| } |
There was a problem hiding this comment.
Code is correct, description need to fix
| throw handleClientException(ERROR_CODE_INVALID_FILTER_EXPRESSION, | ||
| "Only 'properties.<key>' attributes are supported in consent filter. Got: " + attr); | ||
| } | ||
| String op = node.getOperation() != null ? node.getOperation().toLowerCase() : ""; |
| <Match> | ||
| <Class name="org.wso2.carbon.identity.api.user.consent.v1.impl.core.UserConsentService" /> | ||
| <Method name="listConsents" /> | ||
| <Or> | ||
| <Bug pattern="IMPROPER_UNICODE" /> | ||
| <Bug pattern="DM_CONVERT_CASE" /> | ||
| </Or> | ||
| </Match> |
| public MeApiServiceImpl() { | ||
|
|
||
| userConsentService = UserConsentServiceFactory.getUserConsentService(); | ||
| } |
Purpose
Related issue wso2/product-is#26859
Introduces a self-service REST API that enables authenticated users to manage their own consent records directly, without requiring admin-level access. This fills the gap where users had no programmatic way to create, list, retrieve, revoke, or authorize consents on their own behalf.
Goals
/me/consentsendpoint set that allows the authenticated user to fully manage their consent lifecycle.ACTIVE.Approach
A new component
org.wso2.carbon.identity.api.user.consentis added under theidentity-api-userrepository, following the existing module structure (common + v1 sub-modules). The API surface is defined inconsent.yaml(Swagger 2.0) and covers six operations:POST/me/consentsGET/me/consentsGET/me/consents/{consent-id}DELETE/me/consents/{consent-id}POST/me/consents/{consent-id}/authorizeGET/me/consents/{consent-id}/validateThe implementation delegates to
UserConsentService, which wrapsPrivilegedConsentManager(fromcarbon-consent-management) via an OSGi service holder. Cursor-based pagination (after/beforequery params) is supported for listing consents. The API enforces that only the consent subject can retrieve or revoke their own consents (returns 403 otherwise).User stories
Developer Checklist (Mandatory)
product-isissue to track any behavioral change or migration impact.Release note
Adds a new self-service REST API (
/api/users/v1/me/consents) that allows authenticated users to create, list, retrieve, revoke, and authorize their own consent records without requiring administrative privileges.Documentation
Training
Certification
Marketing
Automation tests
Security checks
Samples
Related PRs
Migrations (if applicable)
Test environment
Learning