Skip to content

Self-service API for consent management - #302

Merged
hwupathum merged 7 commits into
wso2:masterfrom
hwupathum:consent-me-api
Jun 26, 2026
Merged

Self-service API for consent management#302
hwupathum merged 7 commits into
wso2:masterfrom
hwupathum:consent-me-api

Conversation

@hwupathum

Copy link
Copy Markdown
Contributor

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

  • Provide a /me/consents endpoint set that allows the authenticated user to fully manage their consent lifecycle.
  • Support multi-party consent flows where a consent may require authorization from multiple users before becoming ACTIVE.
  • Enable consent filtering and cursor-based pagination for scalable consent retrieval.

Approach

A new component org.wso2.carbon.identity.api.user.consent is added under the identity-api-user repository, following the existing module structure (common + v1 sub-modules). The API surface is defined in consent.yaml (Swagger 2.0) and covers six operations:

Method Path Operation
POST /me/consents Create a consent record
GET /me/consents List consents with optional filters
GET /me/consents/{consent-id} Get a specific consent
DELETE /me/consents/{consent-id} Revoke a consent
POST /me/consents/{consent-id}/authorize Authorize a pending consent
GET /me/consents/{consent-id}/validate Validate current consent state

The implementation delegates to UserConsentService, which wraps PrivilegedConsentManager (from carbon-consent-management) via an OSGi service holder. Cursor-based pagination (after/before query 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

  • As an authenticated user, I want to record my consent for specific purposes so that services can use my data in accordance with my preferences.
  • As an authenticated user, I want to view and revoke my previously given consents so that I can exercise my privacy rights.
  • As an authenticated user participating in a multi-party consent, I want to approve or reject a pending consent so that the flow can proceed correctly.

Developer Checklist (Mandatory)

  • Complete the Developer Checklist in the related product-is issue 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

Link(s) to product documentation that addresses the changes of this PR. If no doc impact, enter "N/A" plus brief explanation of why there's no doc impact

Training

N/A

Certification

N/A

Marketing

N/A

Automation tests

  • Unit tests

    Core service logic in UserConsentService should be covered. Coverage TBD.

  • Integration tests

    End-to-end tests for all six endpoints covering create, list, get, revoke, authorize, and validate flows, including 403/404/409 error scenarios.

Security checks

Samples

N/A

Related PRs

List any related PRs in carbon-consent-management or carbon-identity-framework if applicable.

Migrations (if applicable)

No schema or configuration migrations required. The new endpoints are additive.

Test environment

JDK 11, macOS, WSO2 IS 7.x

Learning

Followed the existing identity-api-user module patterns (e.g., org.wso2.carbon.identity.api.user.mfa) for module layout, OSGi wiring, and Swagger code generation.

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@hwupathum, we couldn't start this review because you've reached your PR review rate limit.

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 @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 396f6c7d-fc96-4600-9165-fcc7be62ecc1

📥 Commits

Reviewing files that changed from the base of the PR and between 22c954e and 320236a.

📒 Files selected for processing (4)
  • 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
  • components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/main/resources/consent.yaml
  • findbugs-exclude-filter.xml
  • pom.xml
📝 Walkthrough

Walkthrough

This PR adds a new consent API module with parent and child Maven POMs, OpenAPI 2.0 definitions for /me/consents, OSGi access to PrivilegedConsentManager, a MeApiServiceImpl JAX-RS adapter, and a UserConsentService implementation for create, list, get, revoke, authorize, and validate operations.

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
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the new self-service consent management API.
Description check ✅ Passed The description mostly matches the template and covers purpose, goals, approach, tests, and release notes; a few sections remain unfilled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

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 win

Declare the carbon context dependency directly.

ConsentManagementServiceHolder uses org.wso2.carbon.context.PrivilegedCarbonContext in components/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 declares org.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 with provided scope.

🤖 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 win

Use a locale-aware case conversion instead of suppressing the finding.

node.getOperation().toLowerCase() relies on the default locale (the DM_CONVERT_CASE finding suppressed in findbugs-exclude-filter.xml). Fixing the root cause with toLowerCase(Locale.ENGLISH) makes the comparison deterministic and lets you drop the corresponding FindBugs exclusion (Lines 65-72 of findbugs-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

📥 Commits

Reviewing files that changed from the base of the PR and between 32d8c76 and 22c954e.

⛔ 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.java is 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.java is 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.java is 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.java is 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.java is 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.java is 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.java is 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.java is 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.java is 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.java is 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.java is 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.java is 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.java is 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.java is 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.java is 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.xml
  • components/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
  • components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/pom.xml
  • 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/MeApiServiceImpl.java
  • 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
  • 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/factories/UserConsentServiceFactory.java
  • components/org.wso2.carbon.identity.api.user.consent/org.wso2.carbon.identity.api.user.consent.v1/src/main/resources/consent.yaml
  • components/org.wso2.carbon.identity.api.user.consent/pom.xml
  • findbugs-exclude-filter.xml
  • pom.xml

Copilot AI 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.

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.consent component (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.

Comment on lines +308 to +313
if (subjectId.equals(receipt.getPiiPrincipalId())) {
return;
}
if (findUserAuthorization(authorizations, subjectId) != null) {
return;
}

@hwupathum hwupathum Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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() : "";
Comment on lines +65 to +72
<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>
Comment on lines +42 to +45
public MeApiServiceImpl() {

userConsentService = UserConsentServiceFactory.getUserConsentService();
}
sadilchamishka
sadilchamishka previously approved these changes Jun 26, 2026
@hwupathum
hwupathum merged commit a322137 into wso2:master Jun 26, 2026
2 checks passed
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.

3 participants