Skip to content

Conversation

@NipuniBhagya
Copy link
Contributor

@NipuniBhagya NipuniBhagya commented Oct 1, 2025

This pull request introduces a new common module for credential management in the WSO2 Identity Server API, providing foundational interfaces, DTOs, constants, and exception handling for credential management operations. The changes establish a clear contract for handling different credential types (such as passkeys and push authentication), standardize error handling, and facilitate integration with relevant backend services.

Key additions and changes include:

Core Interfaces and DTOs

  • Added the CredentialManagementService and CredentialHandler interfaces, defining methods for retrieving and deleting user credentials, and introduced the CredentialDTO class for transferring credential data. [1] [2] [3]

Constants and Credential Types

  • Introduced CredentialManagementConstants, which defines supported credential types (e.g., passkey, push-auth) and standardized error messages for both server and client errors.

Exception Handling Framework

  • Implemented a hierarchy of custom exceptions for credential management, including a base CredentialMgtException and specialized client and server exceptions (CredentialMgtClientException, CredentialMgtServerException). [1] [2] [3]

Service Integration

  • Added CredentialManagementServiceDataHolder to provide access to backend services (e.g., WebAuthn and Push Device Handler) required for credential operations.

Build Configuration

  • Created a new Maven pom.xml for the common module, specifying dependencies on required WSO2 and test libraries.## Purpose

Describe the problems, issues, or needs driving this feature/fix and include links to related issues in the following format: Resolves issue1, issue2, etc.

Goals

Describe the solutions that this feature/fix will introduce to resolve the problems described above

Approach

Describe how you are implementing the solutions. Include an animated GIF or screenshot if the change affects the UI (email documentation@wso2.com to review all UI text). Include a link to a Markdown file or Google doc if the feature write-up is too long to paste here.

User stories

Summary of user stories addressed by this change>

Developer Checklist (Mandatory)

  • Complete the Developer Checklist in the related product-is issue to track any behavioral change or migration impact.

Release note

Brief description of the new feature or bug fix as it will appear in the release notes

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

Link to the PR for changes to the training content in https://github.com/wso2/WSO2-Training, if applicable

Certification

Type “Sent” when you have provided new/updated certification questions, plus four answers for each question (correct answer highlighted in bold), based on this change. Certification questions/answers should be sent to certification@wso2.com and NOT pasted in this PR. If there is no impact on certification exams, type “N/A” and explain why.

Marketing

Link to drafts of marketing content that will describe and promote this feature, including product page changes, technical articles, blog posts, videos, etc., if applicable

Automation tests

  • Unit tests

    Code coverage information

  • Integration tests

    Details about the test cases and coverage

Security checks

Samples

Provide high-level details about the samples related to this feature

Related PRs

List any other related PRs

Related Issues

wso2/product-is#25666

Migrations (if applicable)

Describe migration steps and platforms on which migration has been tested

Test environment

List all JDK versions, operating systems, databases, and browser/versions on which this feature/fix was tested

Learning

Describe the research phase and any blog posts, patterns, libraries, or add-ons you used to solve the problem.

Summary by CodeRabbit

  • New Features

    • REST endpoints to list and delete user credentials (GET, DELETE)
    • Support for passkey and push-auth credential types
  • Documentation

    • Added OpenAPI specification for credential management API
  • Improvements

    • Centralized error handling, validation and clearer error codes for credential operations
  • Tests

    • Comprehensive unit tests covering credential listing, deletion and error scenarios

✏️ Tip: You can customize this high-level summary in your review settings.

Comment on lines 67 to 69
CredentialMgtEndpointUtils.validateUserId(userId);
CredentialMgtEndpointUtils.validateCredentialId(credentialId);
CredentialMgtEndpointUtils.validateCredentialType(type);

Choose a reason for hiding this comment

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

Log Improvement Suggestion No: 18

Suggested change
CredentialMgtEndpointUtils.validateUserId(userId);
CredentialMgtEndpointUtils.validateCredentialId(credentialId);
CredentialMgtEndpointUtils.validateCredentialType(type);
CredentialMgtEndpointUtils.validateCredentialId(credentialId);
CredentialMgtEndpointUtils.validateCredentialType(type);
log.info("Deleting credential of type: {} for user: {}", type, userId);
adminCredentialManagementService.deleteCredentialForUser(userId, type, credentialId);

*/
public static void validateCredentialType(String value) throws CredentialMgtClientException {

if (StringUtils.isBlank(value) || !CredentialTypes.fromString(value).isPresent()) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Suggested change
if (StringUtils.isBlank(value) || !CredentialTypes.fromString(value).isPresent()) {
if (!CredentialTypes.fromString(value).isPresent()) {

* @param userId User ID.
* @throws CredentialMgtClientException Invalid user ID.
*/
public static void validateUserId(String userId) throws CredentialMgtClientException {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Remove this util

try {
this.adminServerCredentialManagementService = ServerCredentialManagementServiceFactory
.getServerCredentialManagementService();
} catch (IllegalStateException e) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Remove this

}

@Override
public void deleteCredentialForUser(String userId, String credentialId) throws CredentialMgtException {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Introduce a data model and extract as necessary

@coderabbitai
Copy link

coderabbitai bot commented Nov 25, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds a new credential-management multi-module (common + v1) implementing credential retrieval and deletion for passkey (FIDO2) and push-auth devices: service interfaces, handlers, DTOs, exceptions, endpoint utils, OpenAPI spec, factory, REST impl, Maven configs, and unit tests.

Changes

Cohort / File(s) Summary
Maven module & root POMs
pom.xml, components/org.wso2.carbon.identity.api.server.credential.management/pom.xml, components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/pom.xml, components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/pom.xml
Add new multi-module credential-management project and module POMs; declare dependencies (FIDO2, push device handler), test deps, build plugins, and generated-sources config.
Common — Core interfaces & data holder
...common/src/main/java/.../CredentialHandler.java, ...common/src/main/java/.../CredentialManagementService.java, ...common/src/main/java/.../CredentialManagementServiceDataHolder.java
Add CredentialHandler and CredentialManagementService interfaces and a data holder exposing WebAuthnService, DeviceHandlerService, and RealmService accessors.
Common — DTOs
...common/src/main/java/.../dto/CredentialDTO.java, ...common/src/main/java/.../dto/CredentialDeletionRequestDTO.java
Add immutable DTOs with Builder patterns for credentials and deletion requests.
Common — Constants, errors & utils
...common/src/main/java/.../CredentialManagementConstants.java, ...common/src/main/java/.../exception/CredentialMgtException.java, ...common/src/main/java/.../exception/CredentialMgtClientException.java, ...common/src/main/java/.../exception/CredentialMgtServerException.java, ...common/src/main/java/.../utils/CredentialManagementUtils.java
Introduce credential type enum, error messages enum/constants, custom exception hierarchy (client/server/base) and utility methods to map errors into typed exceptions.
Common — Handlers (implementation)
...common/src/main/java/.../core/PasskeyCredentialHandler.java, ...common/src/main/java/.../core/PushCredentialHandler.java
Implement CredentialHandler for FIDO2 passkeys (uses WebAuthnService) and push-auth devices (uses DeviceHandlerService); include mapping to CredentialDTO and deletion flows.
V1 API — Service layer & factory
...v1/src/main/java/.../impl/CredentialManagementServiceImpl.java, ...v1/src/main/java/.../factories/CredentialManagementServiceFactory.java
Add service implementation that aggregates handlers, routes delete requests by type, and a factory building the handler map (PASSKEY → PasskeyCredentialHandler, PUSH_AUTH → PushCredentialHandler).
V1 API — REST impl & endpoint utils
...v1/src/main/java/.../impl/UsersCredentialApiServiceImpl.java, ...v1/src/main/java/.../utils/CredentialMgtEndpointUtils.java, ...v1/src/main/java/.../constants/CredentialMgtEndpointConstants.java
Add REST implementation wiring the service to endpoints; add endpoint utilities for error-to-HTTP mapping, validation, and DTO→API model conversion; constants for endpoint error codes.
V1 API — OpenAPI spec
...v1/src/main/resources/credential-management.yaml
Add OpenAPI 3 spec defining GET /users/{user-id}/credentials and DELETE /users/{user-id}/credentials/{type}/{credential-id} with Credential and Error schemas.
V1 API — Tests & test config
...v1/src/test/java/.../impl/CredentialManagementServiceImplTest.java, ...v1/src/test/resources/testng.xml
Add comprehensive unit tests for get/delete flows, type validation, partial failure cases, and TestNG config.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API as UsersCredentialApiServiceImpl
    participant Service as CredentialManagementServiceImpl
    participant Factory as CredentialManagementServiceFactory
    participant PK as PasskeyCredentialHandler
    participant Push as PushCredentialHandler
    participant WebAuthn as WebAuthnService
    participant Device as DeviceHandlerService
    participant Utils as CredentialMgtEndpointUtils

    rect rgb(220,235,255)
    Note over Client,Utils: GET /users/{userId}/credentials
    Client->>API: GET /users/{userId}/credentials
    API->>Service: getCredentials(userId)
    Service->>PK: getCredentials(userId)
    PK->>WebAuthn: fetch registrations
    WebAuthn-->>PK: registrations
    PK-->>Service: CredentialDTOs
    Service->>Push: getCredentials(userId)
    Push->>Device: fetch devices
    Device-->>Push: devices
    Push-->>Service: CredentialDTOs
    Service-->>API: aggregated CredentialDTOs
    API->>Utils: toCredentialResponse(...)
    Utils-->>API: API models
    API-->>Client: 200 OK + payload
    end

    rect rgb(255,235,220)
    Note over Client,Utils: DELETE /users/{userId}/credentials/{type}/{credentialId}
    Client->>API: DELETE /users/{userId}/credentials/{type}/{id}
    API->>Service: deleteCredential(request)
    Service->>Service: normalize type → CredentialTypes
    alt PASSKEY
        Service->>PK: deleteCredential(request)
        PK->>WebAuthn: deregister credential
        WebAuthn-->>PK: success/error
    else PUSH_AUTH
        Service->>Push: deleteCredential(request)
        Push->>Device: unregister device
        Device-->>Push: success/error
    end
    Service-->>API: success / throws CredentialMgtException
    API->>Utils: handleCredentialMgtException(e) (if thrown)
    Utils-->>API: APIError / mapped response
    API-->>Client: 204 No Content or error
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Areas requiring extra attention:

  • PasskeyCredentialHandler.java — WebAuthnService integration, username resolution via RealmService, exception mapping.
  • PushCredentialHandler.java — DeviceHandlerService interactions and "device not found" handling.
  • CredentialManagementServiceImpl.java — handler map routing, credential type normalization, partial-failure aggregation and exception translation.
  • CredentialMgtEndpointUtils.java — HTTP status and error-code normalization, DTO→API type mapping (enum conversions).
  • Unit tests (CredentialManagementServiceImplTest.java) — verify mock injection, edge-case inputs, and partial-failure assertions.

Poem

🐰 I hop with keys and pushy spring skies,

Passkeys and devices in neat little ties,
Handlers assembled, a factory's delight,
Endpoints now ready to fetch and to write,
Tests snugly tucked — a carrot-flavored byte.

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description provides a comprehensive overview of the changes (core interfaces, DTOs, constants, exception handling, service integration, build configuration) but is largely incomplete against the template. Most required sections are empty with placeholder text. Complete the PR description by filling in Purpose (with issue link), Goals, Approach, User stories, Developer Checklist, Release note, Documentation, Training, Certification, Marketing, Automation tests details, Security checks, Samples, Related PRs, Migrations, and Test environment sections.
Docstring Coverage ⚠️ Warning Docstring coverage is 46.51% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main change: introducing an end-user credential management admin API, which aligns perfectly with the comprehensive new module being added.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


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 and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 14

♻️ Duplicate comments (2)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)

99-102: Remove double spaces in error descriptions.

Lines 100 and 102 contain double spaces before "was" in the error descriptions. Clean up these formatting inconsistencies.

Apply this diff:

 ERROR_CODE_DELETE_PASSKEY_CREDENTIAL("60001", "Error deleting credential.",
-        "The request to delete the passkey credential: %s  was invalid."),
+        "The request to delete the passkey credential: %s was invalid."),
 ERROR_CODE_DELETE_PUSH_AUTH_CREDENTIAL("60002", "Error deleting credential.",
-        "The request to delete the push auth credential: %s  was invalid."),
+        "The request to delete the push auth credential: %s was invalid."),
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java (1)

75-77: HTTP spec violation: 204 NO_CONTENT cannot have a response body.

While preventing user ID enumeration is a valid security pattern, returning Response.Status.NO_CONTENT (204) with an error body violates HTTP semantics. RFC 7231 specifies that 204 responses MUST NOT contain a message body, yet line 94 constructs an APIError with an ErrorDTO body that will be serialized.

Consider these alternatives:

  • Return 200 OK with an empty credentials array (semantically correct for "no credentials found")
  • Return 404 NOT_FOUND with a generic message that doesn't reveal whether the user or credential is missing
  • Return 400 BAD_REQUEST with a generic validation error

Apply this diff to return an empty result instead:

-            if (StringUtils.equals(e.getErrorCode(),
-                    CredentialManagementConstants.ErrorMessages.ERROR_CODE_ENTITY_NOT_FOUND.getCode())) {
-                status = Response.Status.NO_CONTENT;
-            } else {
+            if (!StringUtils.equals(e.getErrorCode(),
+                    CredentialManagementConstants.ErrorMessages.ERROR_CODE_ENTITY_NOT_FOUND.getCode())) {
                 status = Response.Status.BAD_REQUEST;
             }

Note: This approach treats entity-not-found as a success case (avoiding enumeration), while other client errors return 400. The caller must handle the distinction between empty results and errors.

🧹 Nitpick comments (9)
components/org.wso2.carbon.identity.api.server.user.credential.management/org.wso2.carbon.identity.api.server.user.credential.management.v1/src/test/resources/testng.xml (1)

21-26: Consider aligning suite name with test class package.

The suite is named org.wso2.carbon.identity.api.server.credential.management.common, but the test class is in package org.wso2.carbon.identity.api.server.user.credential.management.v1.core. While this may be intentional organizational grouping, aligning the suite name with the actual test package would improve clarity and consistency.

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/pom.xml (1)

123-161: Consider automating the API service implementation renaming step.

The commented OpenAPI generator configuration notes that the service implementation class requires manual renaming to *UsersCredentialApiServiceImpl.java after generation. Manual post-generation steps are error-prone and can be easily forgotten during updates.

Consider configuring the OpenAPI generator to produce the correct naming directly (e.g., using custom templates or generator configuration options), or document this manual step prominently in a README or CONTRIBUTING guide.

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/factories/CredentialManagementServiceFactory.java (1)

35-41: Consider singleton pattern for factory.

The factory creates new PasskeyCredentialHandler and PushCredentialHandler instances on every invocation. If this factory is called multiple times per request or across requests, unnecessary object allocation occurs.

If the handlers are stateless (as they appear to be), consider implementing a singleton pattern:

+private static final CredentialManagementServiceImpl INSTANCE;
+
+static {
+    Map<CredentialTypes, CredentialHandler> handlerMap = new EnumMap<>(CredentialTypes.class);
+    handlerMap.put(CredentialTypes.PASSKEY, new PasskeyCredentialHandler());
+    handlerMap.put(CredentialTypes.PUSH_AUTH, new PushCredentialHandler());
+    INSTANCE = new CredentialManagementServiceImpl(handlerMap);
+}
+
 public static CredentialManagementServiceImpl getCredentialManagementService() {
 
-    Map<CredentialTypes, CredentialHandler> handlerMap = new EnumMap<>(CredentialTypes.class);
-    handlerMap.put(CredentialTypes.PASSKEY, new PasskeyCredentialHandler());
-    handlerMap.put(CredentialTypes.PUSH_AUTH, new PushCredentialHandler());
-    return new CredentialManagementServiceImpl(handlerMap);
+    return INSTANCE;
 }
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/resources/credential-management.yaml (1)

44-52: Consider adding maxItems constraint on credential arrays.

The response schema returns an unbounded array of credentials. For production APIs, consider adding a maxItems constraint to prevent potential performance issues when users have many credentials enrolled.

Apply this diff:

         '200':
           description: OK
           content:
             application/json:
               schema:
                 type: array
+                maxItems: 100
                 items:
                   $ref: '#/components/schemas/Credential'
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java (1)

56-63: Exception from one handler stops retrieval from other handlers.

If the first handler throws an exception, credentials from subsequent handlers won't be retrieved. Consider whether partial results should be returned or if this fail-fast behavior is intentional.

If partial results are acceptable, consider collecting errors and continuing with other handlers:

List<CredentialDTO> allCredentials = new ArrayList<>();
List<CredentialMgtException> errors = new ArrayList<>();
for (CredentialHandler handler : handlerMap.values()) {
    try {
        allCredentials.addAll(handler.getCredentials(entityId));
    } catch (CredentialMgtException e) {
        errors.add(e);
        LOG.warn("Failed to retrieve credentials from handler: " + handler.getClass().getName(), e);
    }
}
// Handle errors if needed
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/utils/CredentialManagementUtils.java (1)

43-51: Consider handling IllegalFormatException from String.format.

If the data arguments don't match the format specifiers in error.getDescription(), String.format will throw an IllegalFormatException. Consider wrapping in a try-catch or validating the format.

     public static CredentialMgtServerException handleServerException(ErrorMessages error, Throwable e, Object... data) {

         String description = error.getDescription();
         if (ArrayUtils.isNotEmpty(data)) {
-            description = String.format(description, data);
+            try {
+                description = String.format(description, data);
+            } catch (IllegalFormatException ex) {
+                // Log the formatting error and use the original description
+                description = error.getDescription() + " [Data: " + Arrays.toString(data) + "]";
+            }
         }

         return new CredentialMgtServerException(error.getCode(), error.getMessage(), description, e);
     }
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java (1)

78-96: Consider making errorCode and description fields immutable.

The protected setters allow mutation after construction. If immutability is preferred for exception classes, consider removing the setters or making the fields final.

If the setters aren't used by subclasses, consider:

-    private String errorCode;
-    private String description;
+    private final String errorCode;
+    private final String description;

And remove the setter methods. This ensures exception state cannot change after construction.

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java (2)

120-126: Consider explicit blank check for clarity.

While CredentialTypes.fromString handles blank/null values, explicitly checking for blank strings before the enum lookup would improve readability and avoid unnecessary processing.

Apply this diff:

 public static void validateCredentialType(String value) throws CredentialMgtClientException {

-        if (!CredentialTypes.fromString(value).isPresent()) {
+        if (StringUtils.isBlank(value) || !CredentialTypes.fromString(value).isPresent()) {
             throw new CredentialMgtClientException(CredentialManagementConstants
                     .ErrorMessages.ERROR_CODE_INVALID_CREDENTIAL_TYPE);
         }

171-180: Document unchecked exception behavior.

The method throws APIError (unchecked) when encountering an invalid credential type. While functionally correct, documenting this behavior would improve maintainability, especially since it's called from a stream operation.

Consider adding a JavaDoc comment:

 /**
  * Convert a CredentialDTO to a Credential response object.
  *
  * @param dto CredentialDTO object.
  * @return Credential response object.
+ * @throws APIError if the credential type cannot be mapped (unchecked).
  */
 private static Credential toCredential(CredentialDTO dto) {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 022424d and c077ff8.

⛔ Files ignored due to path filters (5)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/Credential.java is excluded by !**/gen/**
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/Error.java is excluded by !**/gen/**
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/UsersApi.java is excluded by !**/gen/**
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/UsersApiService.java is excluded by !**/gen/**
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/factories/UsersApiServiceFactory.java is excluded by !**/gen/**
📒 Files selected for processing (23)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/pom.xml (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialHandler.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementService.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementServiceDataHolder.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtClientException.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtServerException.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/utils/CredentialManagementUtils.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/pom.xml (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/constants/CredentialMgtEndpointConstants.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/factories/CredentialManagementServiceFactory.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/resources/credential-management.yaml (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImplTest.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/pom.xml (1 hunks)
  • components/org.wso2.carbon.identity.api.server.user.credential.management/org.wso2.carbon.identity.api.server.user.credential.management.v1/src/test/resources/testng.xml (1 hunks)
  • pom.xml (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (9)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/utils/CredentialManagementUtils.java (3)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
  • CredentialManagementConstants (29-149)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtClientException.java (1)
  • CredentialMgtClientException (26-62)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtServerException.java (1)
  • CredentialMgtServerException (24-37)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtClientException.java (1)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
  • CredentialManagementConstants (29-149)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
  • Builder (55-83)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/factories/CredentialManagementServiceFactory.java (4)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
  • CredentialManagementConstants (29-149)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java (1)
  • PasskeyCredentialHandler (49-157)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java (1)
  • PushCredentialHandler (46-122)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java (1)
  • CredentialManagementServiceImpl (39-96)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java (5)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
  • CredentialManagementConstants (29-149)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
  • CredentialDTO (24-84)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
  • CredentialDeletionRequestDTO (24-84)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java (1)
  • CredentialMgtException (24-97)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java (1)
  • CredentialMgtEndpointUtils (43-185)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementService.java (2)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
  • CredentialDTO (24-84)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
  • CredentialDeletionRequestDTO (24-84)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
  • Builder (55-83)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java (6)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
  • CredentialManagementConstants (29-149)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementServiceDataHolder.java (1)
  • CredentialManagementServiceDataHolder (29-81)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
  • CredentialDTO (24-84)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
  • CredentialDeletionRequestDTO (24-84)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java (1)
  • CredentialMgtException (24-97)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/utils/CredentialManagementUtils.java (1)
  • CredentialManagementUtils (29-70)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java (8)
components/org.wso2.carbon.identity.api.server.common/src/main/java/org/wso2/carbon/identity/api/server/common/error/APIError.java (1)
  • APIError (25-63)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
  • CredentialManagementConstants (29-149)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
  • CredentialDTO (24-84)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtClientException.java (1)
  • CredentialMgtClientException (26-62)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java (1)
  • CredentialMgtException (24-97)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtServerException.java (1)
  • CredentialMgtServerException (24-37)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/Credential.java (1)
  • Credential (33-175)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/constants/CredentialMgtEndpointConstants.java (1)
  • CredentialMgtEndpointConstants (24-68)
🪛 Checkov (3.2.334)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/resources/credential-management.yaml

[medium] 50-54: Ensure that arrays have a maximum number of items

(CKV_OPENAPI_21)

🔇 Additional comments (22)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/pom.xml (1)

1-49: LGTM! Clean Maven module configuration.

The POM structure is well-organized with appropriate dependencies for credential management functionality (identity core, FIDO2 authenticator, and push notification handler). Dependencies correctly rely on parent POM for version management.

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/pom.xml (1)

36-111: LGTM! Well-structured dependencies for REST API module.

Dependencies are appropriately scoped with CXF for JAX-RS, comprehensive Jackson exclusions to avoid conflicts, and proper test framework setup with TestNG and Mockito.

components/org.wso2.carbon.identity.api.server.credential.management/pom.xml (1)

1-37: LGTM! Standard parent POM for multi-module structure.

The parent POM correctly declares the common and v1 modules, establishing a clean multi-module project structure for the credential management feature.

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)

55-83: LGTM! Well-implemented builder pattern.

The builder provides a clean, fluent API for constructing immutable CredentialDeletionRequestDTO instances. Implementation follows standard builder pattern conventions.

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/constants/CredentialMgtEndpointConstants.java (1)

24-68: LGTM! Well-structured constants class.

The constants class follows best practices with a private constructor to prevent instantiation, and the ErrorMessages enum provides a clean, type-safe approach to error code management. The getCode() method correctly applies the common prefix to maintain consistency across all error codes.

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)

24-84: LGTM! Properly implemented immutable DTO.

The DTO correctly implements immutability with final fields and provides a clean builder pattern for construction. This serves as a good reference for the similar pattern used in CredentialDeletionRequestDTO.

pom.xml (1)

820-825: LGTM!

The Maven configuration changes properly introduce the new credential management module with appropriate dependencies and scoping. The test dependency (mockito-testng), version properties (identity.local.auth.fido.version, identity.notification.push.version), dependency management entries, and module declaration are all correctly configured.

Also applies to: 865-880, 1014-1015, 1080-1080

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialHandler.java (1)

30-41: LGTM!

The interface contract is clear and well-defined with appropriate exception declarations.

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtServerException.java (1)

24-37: LGTM!

The server exception class properly extends the base CredentialMgtException and provides a clean constructor for error context.

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtClientException.java (1)

26-62: LGTM!

The client exception class provides convenient constructor overloads, including one that accepts ErrorMessages enum for standardized error handling.

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)

60-80: Add documentation clarifying punctuation equivalence or restrict accepted input formats.

The fromString method's use of Collator with PRIMARY strength correctly handles case-insensitive matching and whitespace trimming. Comprehensive test coverage confirms this works for "passkey", "PASSKEY", "PassKey", and similar variants, as well as leading/trailing spaces.

However, the test data provider includes "push_auth" (underscore) matching to PUSH_AUTH, despite the apiValue being "push-auth" (hyphen). This works because Collator.PRIMARY treats punctuation as ignorable in many collation implementations, but this behavior is:

  • Not documented in the code
  • Not guaranteed by the Java specification
  • Potentially fragile across different JDK versions

Either document this punctuation equivalence behavior explicitly (with comments explaining why "push_auth" and "push-auth" are equivalent), or restrict the comparison to enforce exact apiValue matching or enum name matching only, to avoid unexpected side effects.

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java (1)

108-121: LGTM!

The mapPushToCredentialDTO helper method is well-implemented with clear mapping logic from the Device model to CredentialDTO.

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java (1)

125-132: LGTM!

The mapPasskeyToCredentialDTO method correctly maps FIDO2 credential fields to the DTO using the builder pattern.

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/utils/CredentialManagementUtils.java (1)

29-33: LGTM!

Private constructor properly prevents instantiation of the utility class.

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java (1)

24-56: LGTM!

The exception class is well-structured with proper constructor chaining, clear field encapsulation, and support for both root-cause and non-root-cause exception scenarios. The protected setters allow subclass flexibility while maintaining encapsulation.

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java (4)

56-60: LGTM!

The exception handling implementation is clean and delegates correctly to getError.


105-112: LGTM!

Clean error DTO construction with all required fields.


134-140: LGTM!

Proper validation for credential ID with appropriate exception handling.


148-157: LGTM!

Proper null/empty handling and clean stream-based conversion.

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImplTest.java (3)

66-78: LGTM!

Clean test setup using reflection to inject dependencies. The use of EnumMap for handler mapping is type-safe and efficient.


83-249: LGTM!

Comprehensive test coverage including success paths, empty results, exception handling, and partial failure scenarios. The tests properly validate fail-fast behavior and handler interaction patterns.


263-283: LGTM!

Clean helper methods for creating test fixtures. Proper use of Mockito's mocking capabilities.

Comment on lines +76 to +79
if (LOG.isDebugEnabled()) {
LOG.info("Successfully retrieved " + credentialDTOs.size() + " passkey credentials for entity ID: "
+ entityId);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Incorrect log level: LOG.info inside LOG.isDebugEnabled() check.

The condition checks for debug level but logs at info level.

         if (LOG.isDebugEnabled()) {
-            LOG.info("Successfully retrieved " + credentialDTOs.size() + " passkey credentials for entity ID: "
+            LOG.debug("Successfully retrieved " + credentialDTOs.size() + " passkey credentials for entity ID: "
                     + entityId);
         }
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java
around lines 76-79, the code checks LOG.isDebugEnabled() but calls
LOG.info(...); change the call to LOG.debug(...) so the logged level matches the
guard (or alternatively change the guard to LOG.isInfoEnabled() if info is
intended); ensure the log invocation uses the matching level and keep the same
message content.

Comment on lines +100 to +103
if (LOG.isDebugEnabled()) {
LOG.info("Successfully deleted passkey credential for entity ID: "
+ credentialDeletionRequest.getEntityId());
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Incorrect log level: LOG.info inside LOG.isDebugEnabled() check.

Same issue - the log statement should use LOG.debug to match the condition.

         if (LOG.isDebugEnabled()) {
-            LOG.info("Successfully deleted passkey credential for entity ID: "
+            LOG.debug("Successfully deleted passkey credential for entity ID: "
                     + credentialDeletionRequest.getEntityId());
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (LOG.isDebugEnabled()) {
LOG.info("Successfully deleted passkey credential for entity ID: "
+ credentialDeletionRequest.getEntityId());
}
if (LOG.isDebugEnabled()) {
LOG.debug("Successfully deleted passkey credential for entity ID: "
credentialDeletionRequest.getEntityId());
}
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java
around lines 100-103, the code checks LOG.isDebugEnabled() but calls
LOG.info(...) inside that block; change the call to LOG.debug(...) so the log
level matches the debug-enabled guard (or remove the guard if you prefer an
unconditional info log), keeping the message text the same.

Comment on lines +146 to +148
AbstractUserStoreManager userStoreManager = (AbstractUserStoreManager) userRealm
.getTenantUserRealm(IdentityTenantUtil.getTenantId(tenantDomain)).getUserStoreManager();
return userStoreManager.getUserNameFromUserID(userId) + "@" + tenantDomain;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Potential null username could result in "null@tenantDomain".

If getUserNameFromUserID returns null (user not found), the concatenation produces an invalid username string. Consider validating the username before concatenation.

-            return userStoreManager.getUserNameFromUserID(userId) + "@" + tenantDomain;
+            String username = userStoreManager.getUserNameFromUserID(userId);
+            if (username == null) {
+                throw new CredentialMgtException(
+                        CredentialManagementConstants.ErrorMessages.ERROR_CODE_ENTITY_NOT_FOUND.getMessage(),
+                        CredentialManagementConstants.ErrorMessages.ERROR_CODE_ENTITY_NOT_FOUND.getCode(),
+                        String.format(CredentialManagementConstants.ErrorMessages.ERROR_CODE_ENTITY_NOT_FOUND.getDescription(), userId));
+            }
+            return username + "@" + tenantDomain;

Comment on lines +52 to +55
public PushCredentialHandler() {

this.deviceHandler = CredentialManagementServiceDataHolder.getPushDeviceHandler();
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Potential NPE if DeviceHandlerService is not initialized.

The deviceHandler obtained from CredentialManagementServiceDataHolder could be null if the OSGi service is not yet available when the handler is instantiated. Consider adding a null check or documenting the initialization requirements.


🏁 Script executed:

#!/bin/bash
# Check if CredentialManagementServiceDataHolder has null safety for getPushDeviceHandler
ast-grep --pattern $'public static DeviceHandlerService getPushDeviceHandler() {
  $$$
}'

Length of output: 1154



🏁 Script executed:

#!/bin/bash
# Find PushDeviceHandlerHolder and check SERVICE initialization
fd PushDeviceHandlerHolder --type f | head -5

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Check PushCredentialHandler for null checks on deviceHandler
rg -nA5 "this\.deviceHandler" components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java

Length of output: 225


🏁 Script executed:

#!/bin/bash
# Look for null checks in PushCredentialHandler methods
rg -nB2 -A10 "public void\|public.*get" components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java | head -50

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Find the actual PushDeviceHandlerHolder class
find . -name "*PushDeviceHandlerHolder*" -type f

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Check CredentialManagementServiceDataHolder for SERVICE field initialization
rg -nB5 -A15 "class CredentialManagementServiceDataHolder\|class PushDeviceHandlerHolder" components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementServiceDataHolder.java | head -60

Length of output: 0



🏁 Script executed:

#!/bin/bash
# View the complete CredentialManagementServiceDataHolder.java file
cat components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementServiceDataHolder.java

Length of output: 2441


🏁 Script executed:

#!/bin/bash
# View the complete PushCredentialHandler.java file
cat components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java

Length of output: 5782


🏁 Script executed:

#!/bin/bash
# Search for any null checks involving deviceHandler
rg "deviceHandler\s*==" components/org.wso2.carbon.identity.api.server.credential.management/ -A3 -B3

Length of output: 0


Add null check for deviceHandler or guard against uninitialized OSGi service.

The deviceHandler obtained from CredentialManagementServiceDataHolder.getPushDeviceHandler() can be null if the DeviceHandlerService OSGi service is not available (line 45 in DataHolder calls getOSGiService() which returns null when service is not registered). Both getCredentials() (line 67) and deleteCredential() (line 83) invoke methods on deviceHandler without null checks, risking a NullPointerException at runtime. Add a null check in the constructor or guard each method call.

🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java
around lines 52–55, the deviceHandler fetched from
CredentialManagementServiceDataHolder.getPushDeviceHandler() can be null when
the OSGi service is unregistered; add a null check and guard against
uninitialized service: either validate deviceHandler in the constructor and
throw an IllegalStateException with a clear message if null, or set a boolean
'enabled' flag and have getCredentials() and deleteCredential() check that flag
(or deviceHandler != null) before invoking methods, returning appropriate
error/empty responses when the service is unavailable.

Comment on lines +68 to +70
if (LOG.isDebugEnabled()) {
LOG.info("Successfully retrieved push authentication credential for entity ID: " + entityId);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Incorrect log level: LOG.info inside LOG.isDebugEnabled() check.

The condition checks for debug level but logs at info level. This is inconsistent and the info message will only appear when debug is enabled, which is likely unintended.

         if (LOG.isDebugEnabled()) {
-            LOG.info("Successfully retrieved push authentication credential for entity ID: " + entityId);
+            LOG.debug("Successfully retrieved push authentication credential for entity ID: " + entityId);
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (LOG.isDebugEnabled()) {
LOG.info("Successfully retrieved push authentication credential for entity ID: " + entityId);
}
if (LOG.isDebugEnabled()) {
LOG.debug("Successfully retrieved push authentication credential for entity ID: " + entityId);
}
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java
around lines 68 to 70, the code checks LOG.isDebugEnabled() but calls
LOG.info(...) which is inconsistent; change the log call to
LOG.debug("Successfully retrieved push authentication credential for entity ID:
" + entityId) so the message level matches the guard (or alternatively change
the guard to LOG.isInfoEnabled() if the intent is to keep an info-level
message).

Comment on lines +64 to +66
if (LOG.isDebugEnabled()) {
LOG.info("Successfully retrieved " + allCredentials.size() + " credentials.");
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Incorrect log level: LOG.info inside LOG.isDebugEnabled() check.

The condition checks for debug level but logs at info level.

         if (LOG.isDebugEnabled()) {
-            LOG.info("Successfully retrieved " + allCredentials.size() + " credentials.");
+            LOG.debug("Successfully retrieved " + allCredentials.size() + " credentials.");
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (LOG.isDebugEnabled()) {
LOG.info("Successfully retrieved " + allCredentials.size() + " credentials.");
}
if (LOG.isDebugEnabled()) {
LOG.debug("Successfully retrieved " + allCredentials.size() + " credentials.");
}
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java
around lines 64 to 66, the code checks LOG.isDebugEnabled() but calls
LOG.info(...); change the logged method to LOG.debug(...) (or change the guard
to LOG.isInfoEnabled() if the intent is an info-level message) so the log level
and guard match; update only the log invocation or the guard accordingly to
ensure correct logging level.

Comment on lines +82 to +85
CredentialTypes credentialType = CredentialTypes.valueOf(credentialDeletionRequest.getType()
.replace("-", "_").toUpperCase(Locale.ROOT));
CredentialHandler handler = handlerMap.get(credentialType);
handler.deleteCredential(credentialDeletionRequest);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Potential NPE if handler is not found in the map.

After converting the credential type string to CredentialTypes enum, handlerMap.get(credentialType) could return null if the handler isn't registered. The subsequent handler.deleteCredential() call would throw an NPE.

             CredentialTypes credentialType = CredentialTypes.valueOf(credentialDeletionRequest.getType()
                     .replace("-", "_").toUpperCase(Locale.ROOT));
             CredentialHandler handler = handlerMap.get(credentialType);
+            if (handler == null) {
+                throw new CredentialMgtException("Unsupported credential type", 
+                        "CM-60005", "No handler registered for credential type: " + credentialType);
+            }
             handler.deleteCredential(credentialDeletionRequest);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
CredentialTypes credentialType = CredentialTypes.valueOf(credentialDeletionRequest.getType()
.replace("-", "_").toUpperCase(Locale.ROOT));
CredentialHandler handler = handlerMap.get(credentialType);
handler.deleteCredential(credentialDeletionRequest);
CredentialTypes credentialType = CredentialTypes.valueOf(credentialDeletionRequest.getType()
.replace("-", "_").toUpperCase(Locale.ROOT));
CredentialHandler handler = handlerMap.get(credentialType);
if (handler == null) {
throw new CredentialMgtException("Unsupported credential type",
"CM-60005", "No handler registered for credential type: " + credentialType);
}
handler.deleteCredential(credentialDeletionRequest);
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/.../CredentialManagementServiceImpl.java
around lines 82-85, handlerMap.get(credentialType) can return null which leads
to an NPE on handler.deleteCredential(...); add a null check after retrieving
the handler and handle the missing handler case instead of calling
deleteCredential: if handler is null, log a clear message including the
credentialType and return/throw an appropriate API error (or a
CredentialManagement-specific exception) indicating the handler is not
registered; only call handler.deleteCredential(...) when handler != null. Ensure
the error path uses the service's existing error handling pattern (HTTP response
or typed exception) and include the credentialType in the message for easier
debugging.

Comment on lines +89 to +94
if (LOG.isDebugEnabled()) {
LOG.info("Successfully deleted credential type: "
+ credentialDeletionRequest.getType() + " with ID: "
+ credentialDeletionRequest.getCredentialId() + " for entity ID: "
+ credentialDeletionRequest.getEntityId());
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Incorrect log level: LOG.info inside LOG.isDebugEnabled() check.

Same issue - the log statement should use LOG.debug to match the condition.

         if (LOG.isDebugEnabled()) {
-            LOG.info("Successfully deleted credential type: "
+            LOG.debug("Successfully deleted credential type: "
                     + credentialDeletionRequest.getType() + " with ID: "
                     + credentialDeletionRequest.getCredentialId() + " for entity ID: "
                     + credentialDeletionRequest.getEntityId());
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (LOG.isDebugEnabled()) {
LOG.info("Successfully deleted credential type: "
+ credentialDeletionRequest.getType() + " with ID: "
+ credentialDeletionRequest.getCredentialId() + " for entity ID: "
+ credentialDeletionRequest.getEntityId());
}
if (LOG.isDebugEnabled()) {
LOG.debug("Successfully deleted credential type: "
credentialDeletionRequest.getType() + " with ID: "
credentialDeletionRequest.getCredentialId() + " for entity ID: "
credentialDeletionRequest.getEntityId());
}
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java
around lines 89 to 94, the log call inside a LOG.isDebugEnabled() check uses
LOG.info; change that to LOG.debug so the logging level matches the
debug-enabled guard, keeping the same message and string concatenation.

Comment on lines +158 to +161
code:
type: string
description: A unique, machine-readable error code following the WSO2 standard.
example: 'CM-60401'
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

Verify error code format consistency.

Line 161 shows example error code 'CM-60401', but CredentialManagementConstants.ErrorMessages defines codes like 'CM-60001', 'CM-60002', etc. Ensure the example uses a valid error code from the constants.

Run the following script to check all defined error codes:


🏁 Script executed:

#!/bin/bash
# Find all error code definitions in CredentialManagementConstants
ast-grep --pattern 'ERROR_CODE_$_(\"$_\", $_)'

Length of output: 0


I need to search more broadly for the error code definitions. Let me try different approaches to locate the constants file and verify the error codes.


---

🏁 Script executed:

```shell
#!/bin/bash
# Find CredentialManagementConstants file
fd CredentialManagementConstants

Length of output: 247


🏁 Script executed:

#!/bin/bash
# Search for error code definitions with broader pattern
rg -n "CM-[0-9]+" --type=java -C2

Length of output: 2503


🏁 Script executed:

#!/bin/bash
# Search for ERROR_CODE or error code patterns in Java files
rg -n "ERROR_CODE|ErrorMessages" --type=java -C1 | head -100

Length of output: 25526


Let me examine the complete CredentialManagementConstants file to confirm all defined error codes:


---

🏁 Script executed:

```shell
#!/bin/bash
# View the CredentialManagementConstants.java ErrorMessages enum
cat components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java | grep -A 50 "public enum ErrorMessages"

Length of output: 2472


Update example error code to use a valid constant from CredentialManagementConstants.ErrorMessages.

The example 'CM-60401' does not exist. Valid error codes are CM-65001, CM-65002, CM-65003, CM-65004 (server errors) or CM-60001 through CM-60006 (client errors). Use one of these, such as 'CM-60001'.

🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/resources/credential-management.yaml
around lines 158 to 161, the example error code 'CM-60401' is invalid; replace
it with a valid constant from CredentialManagementConstants.ErrorMessages such
as 'CM-60001' (or any of CM-65001..CM-65004 or CM-60001..CM-60006) so the
example matches an actual defined error code.

Comment on lines +251 to +258
@DataProvider(name = "edgeCaseInputs")
public Object[][] edgeCaseInputs() {

return new Object[][]{
{" passkey ", CredentialTypes.PASSKEY},
{"PassKey", CredentialTypes.PASSKEY}
};
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Remove unused data provider.

The edgeCaseInputs data provider is defined but not used by any test method. This is dead code.

Either remove it or add a corresponding test method:

-    @DataProvider(name = "edgeCaseInputs")
-    public Object[][] edgeCaseInputs() {
-
-        return new Object[][]{
-                {"  passkey  ", CredentialTypes.PASSKEY},
-                {"PassKey", CredentialTypes.PASSKEY}
-        };
-    }

Alternatively, if edge-case testing is intended, add a test method that uses this provider:

@Test(dataProvider = "edgeCaseInputs")
public void testDeleteCredentialWithEdgeCaseInputs(String typeInput, CredentialTypes expectedType)
        throws CredentialMgtException {
    // Test implementation
}
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImplTest.java
around lines 251 to 258, the DataProvider method edgeCaseInputs is defined but
never referenced, making it dead code; either remove this unused DataProvider or
add a test method annotated with @Test(dataProvider = "edgeCaseInputs") that
consumes the two inputs (e.g., trimming/case-insensitive credential type
parsing) and asserts the expected CredentialTypes so the provider is utilized.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c077ff8 and 8c8ea7f.

📒 Files selected for processing (2)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/UsersCredentialApiServiceImpl.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/resources/testng.xml (1 hunks)
🔇 Additional comments (3)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/resources/testng.xml (2)

1-20: License and XML structure look good.

The Apache 2.0 license header is properly formatted, and the XML structure is valid and follows TestNG conventions.


21-27: Repository access unavailable; manual verification required.

I was unable to access the repository to verify the concerns raised in the original review comment. The repository clone operation failed, preventing me from:

  1. Confirming the test class file exists at the specified fully qualified name
  2. Verifying the package declaration in the test class
  3. Examining the module structure to assess naming consistency
  4. Comparing with other TestNG suite configurations in the project

The original review's concerns about the suite name including "common" while the test class resides in the "v1.impl" module remain valid but unverified. The suite naming convention requires manual inspection of the codebase to determine if this is:

  • An intentional organizational choice, or
  • A naming inconsistency that should be corrected
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/UsersCredentialApiServiceImpl.java (1)

37-47: I was unable to clone the WSO2 Identity API Server repository to verify the specific implementation details. However, based on WSO2 best practices from the web search:

Key findings from WSO2 patterns:

  • JAX-RS services should use centralized exception mappers (with @Provider annotation) rather than inline error handling
  • Input validation can be applied via Bean Validation framework (@Valid, @NotNull, etc.) at the parameter level
  • Error handling and logging are typically centralized and not inline in service methods
  • Services should delegate to exception mappers for HTTP response generation

Without access to the codebase, I cannot verify:

  1. Whether exception mappers are already implemented for credential deletion errors
  2. Whether validation annotations are applied to method parameters
  3. Whether a centralized logging/auditing mechanism exists for sensitive operations
  4. How similar credential operations are implemented in the same service class

Since the repository is not publicly accessible and verification is inconclusive, here is the rewritten review comment:


Verify input validation and error handling strategy are implemented centrally.

This method lacks visible input validation for userId, type, and credentialId. According to WSO2 best practices, validate these parameters early—either via Bean Validation annotations (@NotNull, @NotEmpty) on method parameters or through a centralized validation layer. Confirm that exceptions from deleteCredential() are handled by a global JAX-RS exception mapper (annotated @Provider) and that credential deletion operations are logged for audit purposes.

Comment on lines +34 to +35
private final CredentialManagementService credentialManagementService =
CredentialManagementServiceFactory.getCredentialManagementService();
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add null safety check for service initialization.

If CredentialManagementServiceFactory.getCredentialManagementService() returns null, all method calls will throw a NullPointerException at runtime.

Add a null check or defensive initialization:

 private final CredentialManagementService credentialManagementService =
         CredentialManagementServiceFactory.getCredentialManagementService();
+
+    public UsersCredentialApiServiceImpl() {
+        if (credentialManagementService == null) {
+            throw new IllegalStateException("CredentialManagementService is not available");
+        }
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private final CredentialManagementService credentialManagementService =
CredentialManagementServiceFactory.getCredentialManagementService();
private final CredentialManagementService credentialManagementService =
CredentialManagementServiceFactory.getCredentialManagementService();
public UsersCredentialApiServiceImpl() {
if (credentialManagementService == null) {
throw new IllegalStateException("CredentialManagementService is not available");
}
}
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/.../UsersCredentialApiServiceImpl.java
around lines 34-35, the direct call to
CredentialManagementServiceFactory.getCredentialManagementService() can return
null and cause NPEs; change the initialization to handle null by adding a
defensive check: if the factory returns null, either assign a clear
no-op/placeholder implementation or throw a descriptive IllegalStateException
(or log and propagate a 500-level API error) so subsequent method calls never
operate on a null service; ensure all usages assume non-null and update
constructors or getters accordingly to enforce this invariant.

Comment on lines +49 to +56
@Override
public Response getUserCredentialsById(String userId) {

return Response.ok()
.entity(CredentialMgtEndpointUtils
.toCredentialResponse(credentialManagementService.getCredentials(userId)))
.build();
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add input validation for userId parameter.

The userId parameter is not validated before use. A null value will cause a NullPointerException when passed to getCredentials().

Add validation:

 @Override
 public Response getUserCredentialsById(String userId) {
-
+    if (userId == null || userId.trim().isEmpty()) {
+        throw new IllegalArgumentException("userId cannot be null or empty");
+    }
+
     return Response.ok()
             .entity(CredentialMgtEndpointUtils
                     .toCredentialResponse(credentialManagementService.getCredentials(userId)))
             .build();
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Override
public Response getUserCredentialsById(String userId) {
return Response.ok()
.entity(CredentialMgtEndpointUtils
.toCredentialResponse(credentialManagementService.getCredentials(userId)))
.build();
}
@Override
public Response getUserCredentialsById(String userId) {
if (userId == null || userId.trim().isEmpty()) {
throw new IllegalArgumentException("userId cannot be null or empty");
}
return Response.ok()
.entity(CredentialMgtEndpointUtils
.toCredentialResponse(credentialManagementService.getCredentials(userId)))
.build();
}
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/UsersCredentialApiServiceImpl.java
around lines 49 to 56, the userId parameter is used without validation which can
cause a NullPointerException; add an input check that returns a 400 Bad Request
(or appropriate API error Response) when userId is null or empty before calling
credentialManagementService.getCredentials(userId), and only call getCredentials
and build the OK response when the validation passes.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (10)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)

99-102: Double spaces in error descriptions.

Lines 100 and 102 contain double spaces before "was" (%s was). Remove the extra space for clean error messages.

         ERROR_CODE_DELETE_PASSKEY_CREDENTIAL("60001", "Error deleting credential.",
-                "The request to delete the passkey credential: %s  was invalid."),
+                "The request to delete the passkey credential: %s was invalid."),
         ERROR_CODE_DELETE_PUSH_AUTH_CREDENTIAL("60002", "Error deleting credential.",
-                "The request to delete the push auth credential: %s  was invalid."),
+                "The request to delete the push auth credential: %s was invalid."),
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)

26-28: Declare fields as final for immutability.

The fields should be final to ensure immutability and thread safety, consistent with the pattern used in CredentialDTO.java.

Apply this diff:

-    private String entityId;
-    private String credentialId;
-    private String type;
+    private final String entityId;
+    private final String credentialId;
+    private final String type;
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/resources/credential-management.yaml (1)

161-161: Invalid error code in example.

The example error code 'CM-60401' does not match any defined constant in CredentialManagementConstants.ErrorMessages. Valid codes are CM-65001 through CM-65004 (server errors) or CM-60001 through CM-60006 (client errors).

Apply this diff to use a valid error code:

-          example: 'CM-60401'
+          example: 'CM-60001'
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java (3)

64-66: Incorrect log level inside debug guard.

The condition checks LOG.isDebugEnabled() but logs at info level, which is inconsistent.

Apply this diff:

         if (LOG.isDebugEnabled()) {
-            LOG.info("Successfully retrieved " + allCredentials.size() + " credentials.");
+            LOG.debug("Successfully retrieved " + allCredentials.size() + " credentials.");
         }

82-85: Potential NullPointerException: missing null check for handler.

handlerMap.get(credentialType) can return null if no handler is registered for the credential type. The subsequent call to handler.deleteCredential() will throw an NPE.

Apply this diff to add a null check:

             CredentialTypes credentialType = CredentialTypes.valueOf(credentialDeletionRequest.getType()
                     .replace("-", "_").toUpperCase(Locale.ROOT));
             CredentialHandler handler = handlerMap.get(credentialType);
+            if (handler == null) {
+                throw new CredentialMgtException("Unsupported credential type", 
+                        CredentialManagementConstants.ErrorMessages.ERROR_CODE_INVALID_CREDENTIAL_TYPE.getCode(),
+                        "No handler registered for credential type: " + credentialType);
+            }
             handler.deleteCredential(credentialDeletionRequest);

89-94: Incorrect log level inside debug guard.

Same issue - LOG.info is used inside a LOG.isDebugEnabled() check.

Apply this diff:

         if (LOG.isDebugEnabled()) {
-            LOG.info("Successfully deleted credential type: "
+            LOG.debug("Successfully deleted credential type: "
                     + credentialDeletionRequest.getType() + " with ID: "
                     + credentialDeletionRequest.getCredentialId() + " for entity ID: "
                     + credentialDeletionRequest.getEntityId());
         }
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java (3)

52-55: Potential NullPointerException: deviceHandler can be null.

The deviceHandler obtained from CredentialManagementServiceDataHolder.getPushDeviceHandler() can return null if the OSGi service is not available. Both getCredentials() and deleteCredential() will fail with an NPE if the service is unregistered.

Add a null check in the constructor:

     public PushCredentialHandler() {

         this.deviceHandler = CredentialManagementServiceDataHolder.getPushDeviceHandler();
+        if (this.deviceHandler == null) {
+            throw new IllegalStateException("DeviceHandlerService is not available. " +
+                    "Ensure the push device handler OSGi service is registered.");
+        }
     }

68-70: Incorrect log level inside debug guard.

The condition checks LOG.isDebugEnabled() but logs at info level.

Apply this diff:

         if (LOG.isDebugEnabled()) {
-            LOG.info("Successfully retrieved push authentication credential for entity ID: " + entityId);
+            LOG.debug("Successfully retrieved push authentication credential for entity ID: " + entityId);
         }

94-97: Incorrect log level inside debug guard.

Same issue - LOG.info is used inside a LOG.isDebugEnabled() check.

Apply this diff:

         if (LOG.isDebugEnabled()) {
-            LOG.info("Successfully deleted push authentication credential for entity ID: "
+            LOG.debug("Successfully deleted push authentication credential for entity ID: "
                     + credentialDeletionRequest.getEntityId());
         }
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImplTest.java (1)

251-258: Remove or use the unused edgeCaseInputs data provider

edgeCaseInputs is still not referenced by any @Test method, so it remains dead code. Either remove this provider or add a test (e.g., another deleteCredential test using @Test(dataProvider = "edgeCaseInputs")) that exercises trimming and mixed‑case inputs.

🧹 Nitpick comments (12)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (2)

60-80: Consider simplifying with equalsIgnoreCase instead of Collator.

The Collator with PRIMARY strength is more robust for Unicode edge cases, but for matching simple ASCII enum names like "passkey" and "push-auth", String.equalsIgnoreCase() would be simpler and more readable.

-        Collator collator = Collator.getInstance(Locale.ROOT);
-        collator.setStrength(Collator.PRIMARY);
-
-        return Arrays.stream(values())
-                .filter(type -> collator.compare(type.name(), candidate) == 0
-                        || collator.compare(type.getApiValue(), candidate) == 0)
-                .findFirst();
+        return Arrays.stream(values())
+                .filter(type -> type.name().equalsIgnoreCase(candidate)
+                        || type.getApiValue().equalsIgnoreCase(candidate))
+                .findFirst();

115-116: Consider relocating external error code constant.

ERROR_CODE_PUSH_AUTH_DEVICE_NOT_FOUND is a raw string constant (from Push Device Handler service) that doesn't follow the ErrorMessages enum pattern. Placing it inside the enum is unconventional and could cause confusion.

Move it to the enclosing class as a class-level constant:

 public class CredentialManagementConstants {
 
+    public static final String ERROR_CODE_PUSH_AUTH_DEVICE_NOT_FOUND = "PDH-15010";
+
     private CredentialManagementConstants() {
 
     }

Then remove it from inside the ErrorMessages enum:

-        public static final String ERROR_CODE_PUSH_AUTH_DEVICE_NOT_FOUND = "PDH-15010";
         private final String code;
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialHandler.java (2)

31-34: Consider enhancing the method javadoc.

The javadoc could be more comprehensive for this public API method. Consider documenting the parameter meaning, return value semantics (e.g., whether an empty list is returned when no credentials exist), and the conditions under which CredentialMgtException is thrown.

Example enhancement:

 /**
- * Retrieves credentials for a given entity.
+ * Retrieves all credentials of this type for a given entity.
+ *
+ * @param entityId the unique identifier of the entity (e.g., user ID)
+ * @return a list of credentials, or an empty list if none exist
+ * @throws CredentialMgtException if retrieval fails due to backend errors
  */

36-40: Consider enhancing the method javadoc.

Similar to getCredentials, the javadoc could provide more detail about the parameter requirements and exception conditions for better API clarity.

Example enhancement:

 /**
- * Deletes a credential for an entity.
+ * Deletes a specific credential for an entity.
+ *
+ * @param credentialDeletionRequest the deletion request containing entity and credential identifiers
+ * @throws CredentialMgtException if deletion fails or the credential does not exist
  */
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/factories/CredentialManagementServiceFactory.java (2)

33-34: Add private constructor to prevent instantiation.

Utility/factory classes with only static methods should have a private constructor to prevent instantiation and clearly communicate intent.

Apply this diff:

 public class CredentialManagementServiceFactory {
+
+    private CredentialManagementServiceFactory() {
+        // Prevent instantiation
+    }

35-41: Consider caching the service instance if called frequently.

The factory creates new handler instances on every invocation. If getCredentialManagementService() is called repeatedly, consider caching either the handlers or the entire service instance to improve efficiency.

Example with lazy singleton pattern:

private static volatile CredentialManagementServiceImpl instance;

public static CredentialManagementServiceImpl getCredentialManagementService() {
    if (instance == null) {
        synchronized (CredentialManagementServiceFactory.class) {
            if (instance == null) {
                Map<CredentialTypes, CredentialHandler> handlerMap = new EnumMap<>(CredentialTypes.class);
                handlerMap.put(CredentialTypes.PASSKEY, new PasskeyCredentialHandler());
                handlerMap.put(CredentialTypes.PUSH_AUTH, new PushCredentialHandler());
                instance = new CredentialManagementServiceImpl(handlerMap);
            }
        }
    }
    return instance;
}
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/resources/testng.xml (1)

21-26: Suite name namespace doesn’t match module path

The suite is named ...credential.management.common while it lives under the .v1 module and only runs ...credential.management.v1.impl.CredentialManagementServiceImplTest. For clarity when multiple suites coexist, consider renaming the suite to reflect the v1 module (e.g., ...credential.management.v1).

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImplTest.java (5)

55-78: Test setup uses reflection on a mocked service – consider simplifying

Using a @Mock for CredentialManagementServiceImpl and injecting handlerMap via reflection works but is brittle against internal field or wiring changes. If possible, prefer a real instance (or @InjectMocks) with handlers injected via constructor / setter / package-private mutator so the tests exercise the object in a more realistic configuration.


145-158: Optionally assert APIError contents when a handler fails

The test currently only checks that an APIError is thrown. For stronger coverage of the exception mapping, consider capturing the thrown APIError (e.g., via Assert.expectThrows) and asserting its status and error code derived from the CredentialMgtException.


196-215: Strengthen deleteCredential test by asserting only the resolved handler is invoked

Right now you verify that the expected handler is invoked once, but the test would still pass if both handlers were called. To guard against accidental double‑deletes, you can also assert that the non‑selected handler is never invoked:

-        CredentialHandler expectedHandler = expectedType == CredentialTypes.PASSKEY ?
-                passkeyHandler : pushAuthHandler;
-        verify(expectedHandler, times(1)).deleteCredential(userCredentialDeletionRequest);
+        CredentialHandler expectedHandler = expectedType == CredentialTypes.PASSKEY ?
+                passkeyHandler : pushAuthHandler;
+        CredentialHandler unexpectedHandler = expectedType == CredentialTypes.PASSKEY ?
+                pushAuthHandler : passkeyHandler;
+
+        verify(expectedHandler, times(1)).deleteCredential(userCredentialDeletionRequest);
+        verify(unexpectedHandler, never()).deleteCredential(userCredentialDeletionRequest);

217-230: Invalid credential‑type path is covered; consider checking error details

The test exercises the invalid credential type path and expects an APIError, which is good. Optionally, you could assert the specific error code/message to ensure the endpoint surfaces the intended client error for unsupported types.


260-283: Consider using real DTO builders instead of mocked DTOs in helpers

The helper methods currently return Mockito‑mocked CredentialDTO / CredentialDeletionRequestDTO instances. Since these DTOs already provide builders, you could construct real instances instead, reducing mocking surface area and giving compile‑time feedback if DTO fields change. This is purely an optional test‑design improvement.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8c8ea7f and c8f9d9e.

⛔ Files ignored due to path filters (5)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/Credential.java is excluded by !**/gen/**
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/Error.java is excluded by !**/gen/**
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/UsersApi.java is excluded by !**/gen/**
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/UsersApiService.java is excluded by !**/gen/**
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/gen/java/org/wso2/carbon/identity/api/server/credential/management/v1/factories/UsersApiServiceFactory.java is excluded by !**/gen/**
📒 Files selected for processing (24)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/pom.xml (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialHandler.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementService.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementServiceDataHolder.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtClientException.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtServerException.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/utils/CredentialManagementUtils.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/pom.xml (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/constants/CredentialMgtEndpointConstants.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/factories/CredentialManagementServiceFactory.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/UsersCredentialApiServiceImpl.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/resources/credential-management.yaml (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImplTest.java (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/resources/testng.xml (1 hunks)
  • components/org.wso2.carbon.identity.api.server.credential.management/pom.xml (1 hunks)
  • pom.xml (5 hunks)
✅ Files skipped from review due to trivial changes (1)
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtServerException.java
🚧 Files skipped from review as they are similar to previous changes (11)
  • components/org.wso2.carbon.identity.api.server.credential.management/pom.xml
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementServiceDataHolder.java
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/constants/CredentialMgtEndpointConstants.java
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/pom.xml
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementService.java
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/utils/CredentialManagementUtils.java
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/UsersCredentialApiServiceImpl.java
  • components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java
🧰 Additional context used
🧬 Code graph analysis (6)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/factories/CredentialManagementServiceFactory.java (4)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
  • CredentialManagementConstants (29-149)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PasskeyCredentialHandler.java (1)
  • PasskeyCredentialHandler (49-157)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java (1)
  • PushCredentialHandler (46-122)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java (1)
  • CredentialManagementServiceImpl (39-96)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/core/PushCredentialHandler.java (6)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
  • CredentialManagementConstants (29-149)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementServiceDataHolder.java (1)
  • CredentialManagementServiceDataHolder (29-81)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
  • CredentialDTO (24-84)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
  • CredentialDeletionRequestDTO (24-84)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java (1)
  • CredentialMgtException (24-97)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/utils/CredentialManagementUtils.java (1)
  • CredentialManagementUtils (29-70)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
  • Builder (55-83)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImplTest.java (4)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
  • CredentialManagementConstants (29-149)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
  • CredentialDTO (24-84)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
  • CredentialDeletionRequestDTO (24-84)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java (1)
  • CredentialMgtException (24-97)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtClientException.java (1)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
  • CredentialManagementConstants (29-149)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImpl.java (5)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialManagementConstants.java (1)
  • CredentialManagementConstants (29-149)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDTO.java (1)
  • CredentialDTO (24-84)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/dto/CredentialDeletionRequestDTO.java (1)
  • CredentialDeletionRequestDTO (24-84)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtException.java (1)
  • CredentialMgtException (24-97)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/utils/CredentialMgtEndpointUtils.java (1)
  • CredentialMgtEndpointUtils (43-185)
🪛 Checkov (3.2.334)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/resources/credential-management.yaml

[medium] 50-54: Ensure that arrays have a maximum number of items

(CKV_OPENAPI_21)

🔇 Additional comments (12)
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/main/java/org/wso2/carbon/identity/api/server/credential/management/v1/factories/CredentialManagementServiceFactory.java (1)

38-39: I'll help you verify the backend service initialization concerns. Let me search for the relevant code to understand the service initialization pattern and null safety.
<function_calls>

#!/bin/bash

Find the CredentialManagementServiceDataHolder and handler implementations

fd -t f -name "*.java" | head -30


</function_calls>

Let me get a better overview of the project structure:
<function_calls>

#!/bin/bash

Search for the DataHolder class

rg -n "class CredentialManagementServiceDataHolder" --type=java


</function_calls>

Now let me search for the handler implementations:
<function_calls>

#!/bin/bash

Search for handler classes

rg -n "class PasskeyCredentialHandler|class PushCredentialHandler" --type=java


</function_calls>

Let me also check the factory file itself to understand the context better:
<function_calls>

#!/bin/bash

Find and examine the factory file

fd -t f -name "CredentialManagementServiceFactory.java" -exec cat -n {} ;


</function_calls>

Let me search more broadly for these components:
<function_calls>

#!/bin/bash

Search for all references to DataHolder methods

rg -n "getWebAuthnService|getPushDeviceHandler" --type=java


</function_calls>

Let me also check for OSGi component and service reference annotations:
<function_calls>

#!/bin/bash

Search for @component and @reference annotations

rg -n "@component|@reference|@service" --type=java | head -50


</function_calls>

#!/bin/bash # List files to understand repository structure find . -type f -name "*.java" | grep -i "credential\|factory\|handler\|dataholder" | head -20
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/pom.xml (1)

35-48: LGTM!

Module structure is well-organized and dependency declarations follow Maven best practices. Version inheritance from parent dependencyManagement is correct.

pom.xml (3)

1014-1017: Clarify documentation inconsistency in version property comment.

Line 1017 comment was changed to "Organization management impl Version" but the property name on line 1018 is .core.version. The comment now mismatches the property it describes. Verify if this comment change was intentional or should be reverted/aligned with the actual property's purpose.


1080-1080: LGTM!

Credential management module is properly registered in the modules list, maintaining alphabetical organization patterns in the module registry.


820-825: mockito-testng 0.5.2 is available in Maven Central but version mismatch with TestNG 6.9.10 warrants attention.

mockito-testng version 0.5.2 is published to Maven Central and does not enforce a specific TestNG version, so it will technically run with TestNG 6.9.10. However, 0.5.2 was released in 2023 and is intended for modern TestNG releases. Using a significantly older TestNG version (6.9.10) may lead to API or behavior compatibility issues. Consider testing the combination or updating to a more recent TestNG version if runtime issues occur.

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/exception/CredentialMgtClientException.java (1)

19-27: Overall exception structure and ErrorMessages integration look good

The class cleanly extends the base CredentialMgtException and the ErrorMessages-based constructor keeps client errors aligned with the shared constants. No functional issues spotted here.

Also applies to: 53-61

components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.v1/src/test/java/org/wso2/carbon/identity/api/server/credential/management/v1/impl/CredentialManagementServiceImplTest.java (6)

80-103: Happy‑path aggregation in getCredentials is well covered

This test cleanly verifies aggregation across both handlers and asserts the combined result plus interaction counts. No issues spotted here.


105-121: Empty‑result behavior is correctly asserted

You explicitly assert a non‑null but empty list and verify both handlers are invoked once, which is a good contract for the “no credentials” case.


123-143: Single‑handler success scenario looks correct

The case where only one handler returns credentials is exercised, and you still verify both handlers are called once; this nicely guards against silently skipping one of the handlers.


160-181: Short‑circuiting semantics on handler failure are well tested

Verifying that the push‑auth handler is never called when the passkey handler fails gives good protection against partial‑success behavior sneaking in later. This test looks solid.


183-194: Credential type data provider covers key normalizations

The validCredentialTypes data set nicely exercises case differences and both hyphen/underscore representations, which will catch regressions in CredentialTypes normalization.


232-249: Exception propagation for deleteCredential is tested appropriately

This test verifies that a handler‑level CredentialMgtException during deletion is mapped to an APIError, which is the critical behavior here. No changes needed.

Comment on lines +27 to +29
/**
* Credential Management Service interface.
*/
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Correct the interface javadoc.

The javadoc describes this as "Credential Management Service interface" but the interface is actually named CredentialHandler. The documentation should accurately reflect the interface name.

Apply this diff to fix the javadoc:

 /**
- * Credential Management Service interface.
+ * Interface for handling credential operations for a specific credential type.
  */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* Credential Management Service interface.
*/
/**
* Interface for handling credential operations for a specific credential type.
*/
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/org.wso2.carbon.identity.api.server.credential.management.common/src/main/java/org/wso2/carbon/identity/api/server/credential/management/common/CredentialHandler.java
around lines 27 to 29, update the class-level Javadoc so it accurately names the
interface (replace "Credential Management Service interface." with a description
that references the interface name, e.g., "CredentialHandler interface." or
"Interface for handling credential management operations."). Ensure the first
sentence references CredentialHandler and keep the Javadoc concise and
grammatically correct.

Comment on lines +28 to +51
/**
* Constructor with {@code message}, {@code errorCode} and {@code description} parameters.
*
* @param message Message to be included in the exception.
* @param errorCode Error code of the exception.
* @param description Description of the exception.
*/
public CredentialMgtClientException(String errorCode, String message, String description) {

super(message, errorCode, description);
}

/**
* Constructor with {@code message}, {@code errorCode}, {@code description} and {@code cause} parameters.
*
* @param message Message to be included in the exception.
* @param errorCode Error code of the exception.
* @param description Description of the exception.
* @param cause Exception to be wrapped.
*/
public CredentialMgtClientException(String errorCode, String message, String description, Throwable cause) {

super(message, errorCode, description, cause);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Constructor parameter order vs Javadoc is inconsistent and can confuse callers

Both String-based constructors take (String errorCode, String message, String description[, Throwable cause]), but the Javadoc text and @param tags describe the parameters in the order (message, errorCode, description, cause), while super(...) is called as (message, errorCode, description[, cause]). This mismatch is easy to misread and could lead to callers swapping arguments unintentionally.

Consider either:

  • Updating the Javadoc (summary sentence and @param order) to match the current signature, or
  • Reordering the parameters in the signature to (String message, String errorCode, String description[, Throwable cause]) for clarity and alignment with the super(...) call and docs.

Minimal fix (docs-only) example:

-    /**
-     * Constructor with {@code message}, {@code errorCode} and {@code description} parameters.
-     *
-     * @param message     Message to be included in the exception.
-     * @param errorCode   Error code of the exception.
-     * @param description Description of the exception.
-     */
-    public CredentialMgtClientException(String errorCode, String message, String description) {
+    /**
+     * Constructor with {@code errorCode}, {@code message} and {@code description} parameters.
+     *
+     * @param errorCode   Error code of the exception.
+     * @param message     Message to be included in the exception.
+     * @param description Description of the exception.
+     */
+    public CredentialMgtClientException(String errorCode, String message, String description) {
@@
-    /**
-     * Constructor with {@code message}, {@code errorCode}, {@code description} and {@code cause} parameters.
-     *
-     * @param message     Message to be included in the exception.
-     * @param errorCode   Error code of the exception.
-     * @param description Description of the exception.
-     * @param cause       Exception to be wrapped.
-     */
-    public CredentialMgtClientException(String errorCode, String message, String description, Throwable cause) {
+    /**
+     * Constructor with {@code errorCode}, {@code message}, {@code description} and {@code cause} parameters.
+     *
+     * @param errorCode   Error code of the exception.
+     * @param message     Message to be included in the exception.
+     * @param description Description of the exception.
+     * @param cause       Exception to be wrapped.
+     */
+    public CredentialMgtClientException(String errorCode, String message, String description, Throwable cause) {
🤖 Prompt for AI Agents
In
components/org.wso2.carbon.identity.api.server.credential.management/.../CredentialMgtClientException.java
around lines 28-51, the Javadoc describes parameters in the order (message,
errorCode, description, cause) while the constructors' signature is (String
errorCode, String message, String description[, Throwable cause]) and super(...)
is invoked as (message, errorCode, description[, cause]); update the Javadoc to
reflect the actual parameter order by changing the summary sentence and the
@param tags to list @param errorCode, @param message, @param description and
@param cause (in that order) with the correct descriptions so docs match the
signature and avoid confusion.

Comment on lines +865 to +880
<dependency>
<groupId>org.wso2.carbon.identity.server.api</groupId>
<artifactId>org.wso2.carbon.identity.api.server.credential.management.common</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity.notification.push</groupId>
<artifactId>org.wso2.carbon.identity.notification.push.device.handler</artifactId>
<version>${identity.notification.push.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity.local.auth.fido</groupId>
<artifactId>org.wso2.carbon.identity.application.authenticator.fido2</artifactId>
<version>${identity.local.auth.fido.version}</version>
</dependency>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Script executed:

#!/bin/bash
# Verify artifact versions in repositories

echo "=== Checking artifact availability ===" 

# Check fido2 authenticator (5.4.26) in Maven Central
echo -e "\n1. Checking fido2 authenticator v5.4.26:"
curl -s -w "\nHTTP Status: %{http_code}\n" \
  "https://repo.maven.apache.org/maven2/org/wso2/carbon/identity/local/auth/fido/org.wso2.carbon.identity.application.authenticator.fido2/5.4.26/" | head -5

# Check push device handler (1.0.6) in Maven Central
echo -e "\n2. Checking push device handler v1.0.6:"
curl -s -w "\nHTTP Status: %{http_code}\n" \
  "https://repo.maven.apache.org/maven2/org/wso2/carbon/identity/notification/push/org.wso2.carbon.identity.notification.push.device.handler/1.0.6/" | head -5

# Check credential management common artifact (uses ${project.version})
echo -e "\n3. Checking credential management common (uses project.version):"
curl -s -w "\nHTTP Status: %{http_code}\n" \
  "https://repo.maven.apache.org/maven2/org/wso2/carbon/identity/server/api/org.wso2.carbon.identity.api.server.credential.management.common/" | head -5

Repository: wso2/identity-api-server


<shell_result>
Repository: wso2/identity-api-server
Script execution failed with unrecoverable error: [CAPABILITY:RUN_SHELL_SCRIPT] Failed to clone repository wso2/identity-api-server: Clone operation failed
</shell_result>


org.wso2.carbon.identity.application.authenticator.fido2 5.4.26 Maven Central


<web_search_result>
I couldn't find an artifact with groupId org.wso2.carbon.identity.application.authenticator.fido2 version 5.4.26 on Maven Central. The FIDO2 authenticator artifacts are published under groupId org.wso2.carbon.identity.local.auth.fido (artifactId org.wso2.carbon.identity.application.authenticator.fido2) and available from the WSO2 repositories; known published versions include 5.3.x and 5.4.x (e.g. 5.3.32, 5.4.10 / 5.4.17), but not 5.4.26. [1][2]

Sources:

  • org.wso2.carbon.identity.application.authenticator.fido2 (examples of published versions; WSO2 repo / mvnrepository). [1]
  • org.wso2.carbon.identity.application.authenticator.fido2.server.feature (shows 5.4.x series; WSO2/Maven listings). [2]
    </web_search_result>

org.wso2.carbon.identity.notification.push.device.handler 1.0.6 Maven Central


<web_search_result>
Yes — org.wso2.carbon.identity.notification.push.device.handler version 1.0.6 is published (available from WSO2 Releases). See the artifact listing and versions on MVNRepository. [1][2]

Maven dependency (use WSO2 Releases repository):

org.wso2.carbon.identity.notification.push
org.wso2.carbon.identity.notification.push.device.handler
1.0.6

Sources:

  • Artifact page (versions list) — MVNRepository. [1]
  • Related push-notification feature / provider v1.0.6 entries — MVNRepository. [2]

References:
[1] https://mvnrepository.com/artifact/org.wso2.carbon.identity.notification.push/org.wso2.carbon.identity.notification.push.device.handler
[2] https://mvnrepository.com/artifact/org.wso2.carbon.identity.notification.push/org.wso2.carbon.identity.notification.push.feature
</web_search_result>


WSO2 identity-notification-push device handler version 1.0.6


<web_search_result>
Yes — version 1.0.6 of the WSO2 push notification modules is available on Maven (released Feb 20, 2025). Maven coordinates you can use:

  • GroupId: org.wso2.carbon.identity.notification.push
  • ArtifactId: org.wso2.carbon.identity.notification.push.device.handler
  • Version: 1.0.6. (mvnrepository.com)

The push feature/pom (identity-notification-push) also has a 1.0.6 release on WSO2 Maven listings. (mvnrepository.com)

If you want direct download or pom/bundle files, fetch them from the WSO2 Releases repository on the Maven pages above. (mvnrepository.com)

Citations:


Verify FIDO2 authenticator version 5.4.26—this version may not exist in repositories.

The fido2 authenticator version 5.4.26 does not appear in known repositories. Available versions in the 5.4.x series are 5.4.10, 5.4.17, etc., but not 5.4.26. Confirm the correct version for org.wso2.carbon.identity.application.authenticator.fido2 or update the ${identity.local.auth.fido.version} property accordingly. The push device handler v1.0.6 is valid and published.

🤖 Prompt for AI Agents
In pom.xml around lines 865 to 880 the configured FIDO2 authenticator version
(${identity.local.auth.fido.version}) resolves to 5.4.26 which is not present in
known repositories; verify the correct published version for
org.wso2.carbon.identity.application.authenticator.fido2 and update the property
(or hardcode the dependency version) to a valid released version (e.g., 5.4.17
or whichever is found in your artifact repository), or if 5.4.26 is required
ensure it is published to your repo and update repository settings accordingly.

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