From cdf9eb19ac05ceedf303f5381be4a45ee390191e Mon Sep 17 00:00:00 2001 From: Rashmini Date: Tue, 29 Aug 2023 15:08:00 +0530 Subject: [PATCH 01/17] Add recovery V2 API --- .../pom.xml | 189 +++ .../api/user/recovery/v2/RecoveryApi.java | 190 +++ .../user/recovery/v2/RecoveryApiService.java | 59 + .../factories/RecoveryApiServiceFactory.java | 32 + .../api/user/recovery/v2/model/APICall.java | 146 ++ .../v2/model/AccountRecoveryType.java | 176 +++ .../recovery/v2/model/ConfirmRequest.java | 159 +++ .../user/recovery/v2/model/ErrorResponse.java | 165 +++ .../user/recovery/v2/model/InitRequest.java | 145 ++ ...asswordRecoveryExternalNotifyResponse.java | 241 ++++ ...asswordRecoveryInternalNotifyResponse.java | 219 +++ .../v2/model/PasswordResetResponse.java | 124 ++ .../api/user/recovery/v2/model/Property.java | 124 ++ .../recovery/v2/model/RecoveryChannel.java | 168 +++ .../v2/model/RecoveryChannelInformation.java | 136 ++ .../recovery/v2/model/RecoveryRequest.java | 162 +++ ...esendConfirmationCodeExternalResponse.java | 244 ++++ ...esendConfirmationCodeInternalResponse.java | 222 +++ .../v2/model/ResendConfirmationRequest.java | 136 ++ .../recovery/v2/model/ResetCodeResponse.java | 133 ++ .../user/recovery/v2/model/ResetRequest.java | 180 +++ .../recovery/v2/model/RetryErrorResponse.java | 221 +++ .../api/user/recovery/v2/model/UserClaim.java | 124 ++ .../model/UsernameRecoveryNotifyResponse.java | 176 +++ .../v2/impl/RecoveryApiServiceImpl.java | 86 ++ .../user/recovery/v2/impl/core/Constants.java | 121 ++ .../v2/impl/core/PasswordRecoveryService.java | 463 ++++++ .../v2/impl/core/UsernameRecoveryService.java | 182 +++ .../core/exceptions/BadRequestException.java | 64 + .../core/exceptions/ConflictException.java | 67 + .../core/exceptions/ForbiddenException.java | 65 + .../InternalServerErrorException.java | 66 + .../exceptions/NotAcceptableException.java | 65 + .../core/exceptions/NotFoundException.java | 65 + .../PreconditionFailedException.java | 81 ++ .../v2/impl/core/utils/RecoveryUtil.java | 576 ++++++++ .../META-INF/cxf/user-recovery-v2-cxf.xml | 33 + .../main/resources/user.account.recovery.yaml | 1256 +++++++++++++++++ .../pom.xml | 1 + 39 files changed, 7062 insertions(+) create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/pom.xml create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/RecoveryApi.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/RecoveryApiService.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/factories/RecoveryApiServiceFactory.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/APICall.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/AccountRecoveryType.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ConfirmRequest.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ErrorResponse.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/InitRequest.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordRecoveryExternalNotifyResponse.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordRecoveryInternalNotifyResponse.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordResetResponse.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/Property.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/RecoveryChannel.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/RecoveryChannelInformation.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/RecoveryRequest.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationCodeExternalResponse.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationCodeInternalResponse.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationRequest.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResetCodeResponse.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResetRequest.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/RetryErrorResponse.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/UserClaim.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/UsernameRecoveryNotifyResponse.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/RecoveryApiServiceImpl.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/Constants.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/BadRequestException.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ConflictException.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ForbiddenException.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/InternalServerErrorException.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotAcceptableException.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotFoundException.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/PreconditionFailedException.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/resources/META-INF/cxf/user-recovery-v2-cxf.xml create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/resources/user.account.recovery.yaml diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/pom.xml b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/pom.xml new file mode 100644 index 00000000..bfdfba89 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/pom.xml @@ -0,0 +1,189 @@ + + + + + + org.wso2.carbon.identity.api.user.recovery + org.wso2.carbon.identity.user.api + 1.3.19-SNAPSHOT + ../pom.xml + + 4.0.0 + + org.wso2.carbon.identity.rest.api.user.recovery.v2 + jar + WSO2 Identity Server - User Account Recovery Rest API + WSO2 Identity Server - User Account Recovery Rest API + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.8 + + + add-source + generate-sources + + add-source + + + + src/gen/java + + + + + + + + + + + org.apache.cxf + cxf-rt-frontend-jaxrs + provided + + + org.apache.cxf + cxf-rt-rs-service-description + provided + + + org.springframework + spring-web + provided + + + javax.ws.rs + javax.ws.rs-api + provided + + + io.swagger + swagger-jaxrs + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-annotations + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + + + javax.ws.rs + jsr311-api + + + com.google.guava + guava + + + + + com.fasterxml.jackson.jaxrs + jackson-jaxrs-json-provider + provided + + + org.wso2.carbon.identity.governance + org.wso2.carbon.identity.recovery + provided + + + javax.ws.rs + jsr311-api + + + + + org.wso2.carbon.identity.governance + org.wso2.carbon.identity.governance + provided + + + javax.ws.rs + jsr311-api + + + + + org.wso2.carbon.identity.user.api + org.wso2.carbon.identity.api.user.common + provided + + + org.wso2.carbon.identity.user.api + org.wso2.carbon.identity.api.user.recovery.commons + provided + + + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/RecoveryApi.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/RecoveryApi.java new file mode 100644 index 00000000..4f95030a --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/RecoveryApi.java @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2; + +import org.springframework.beans.factory.annotation.Autowired; +import org.apache.cxf.jaxrs.ext.multipart.Attachment; +import org.apache.cxf.jaxrs.ext.multipart.Multipart; +import java.io.InputStream; + +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.AccountRecoveryType; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ConfirmRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.InitRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.PasswordRecoveryExternalNotifyResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.PasswordRecoveryInternalNotifyResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.PasswordResetResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RecoveryRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ResendConfirmationCodeExternalResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ResendConfirmationCodeInternalResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ResendConfirmationRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ResetCodeResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ResetRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RetryErrorResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.UsernameRecoveryNotifyResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.RecoveryApiService; + +import javax.validation.Valid; +import javax.ws.rs.*; +import javax.ws.rs.core.Response; +import io.swagger.annotations.*; + +import javax.validation.constraints.*; + +@Path("/recovery") +@Api(description = "The recovery API") + +public class RecoveryApi { + + @Autowired + private RecoveryApiService delegate; + + @Valid + @POST + @Path("/password/confirm") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @ApiOperation(value = "Confirm password recovery ", notes = "- This API is used to validate the __confirmationCode__ given at password recovery. - Use the returned __reset code__ with the __password reset API__ to reset the password. - The API will return the next API call. ", response = ResetCodeResponse.class, tags={ "Password Recovery", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "- Password reset confirmed. - `resetCode` is returned. ", response = ResetCodeResponse.class), + @ApiResponse(code = 400, message = "Bad Request. Request cannot be processed by the server.", response = ErrorResponse.class), + @ApiResponse(code = 404, message = "Confirmation code is not found.", response = ErrorResponse.class), + @ApiResponse(code = 406, message = "Confirmation code given in the request is not valid or expired. ", response = ErrorResponse.class), + @ApiResponse(code = 500, message = "Server Error.", response = ErrorResponse.class) + }) + public Response confirmRecovery(@ApiParam(value = "- Request to confirm the password recovery. - `confirmationCode` is `REQUIRED`. " ,required=true) @Valid ConfirmRequest confirmRequest) { + + return delegate.confirmRecovery(confirmRequest ); + } + + @Valid + @POST + @Path("/password/init") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @ApiOperation(value = "Initiate password recovery ", notes = "- This API is used to initiate password recovery by user. The API will return recovery information for password recovery with challenge questions and password recovery with notifications. - `mode` __recoverWithNotifications__ contains available communication channels and a recovery code for password recovery with notifications. The next API call will be returned in the response. - If `password recovery with notifications` is not enabled, the response will not contain __recoverWithNotifications__ mode. - __recoverWithChallengeQuestions__ contains the next API call to begin the recovery process via challenge questions. - If `password recovery with challenge questions` is not enabled, the response will not contain __recoverWithChallengeQuestions__ mode. ", response = AccountRecoveryType.class, responseContainer = "List", tags={ "Password Recovery", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "User is successfully identified for the given claims and returning available notification channels for the user.", response = AccountRecoveryType.class, responseContainer = "List"), + @ApiResponse(code = 400, message = "Bad Request. The request cannot be processed by the server.", response = ErrorResponse.class), + @ApiResponse(code = 404, message = "No user found for the given set of claims or no recovery channels are availabe for the user.", response = ErrorResponse.class), + @ApiResponse(code = 409, message = "Mutiple users found for the given claims.", response = ErrorResponse.class), + @ApiResponse(code = 500, message = "Server Error.", response = ErrorResponse.class) + }) + public Response initiatePasswordRecovery(@ApiParam(value = "Request to initate password recovery process. The request should contain the claims to identify the user. User claims are `REQUIRED`." ,required=true) @Valid InitRequest initRequest) { + + return delegate.initiatePasswordRecovery(initRequest ); + } + + @Valid + @POST + @Path("/username/init") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @ApiOperation(value = "Initiate Username Recovery", notes = "- This API is used to initiate username recovery by user. The API will return available recovery information for username recovery with notifications. - Use the returned __recoveryCode__ and the __channelId__ with __username recover api__ to confirm the the username recovery and to recieve recovery notifications via the channel specified by the user. ", response = AccountRecoveryType.class, responseContainer = "List", tags={ "Username Recovery", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "User is successfully identified for the given claims and returning available notification channels for the user.", response = AccountRecoveryType.class, responseContainer = "List"), + @ApiResponse(code = 400, message = "Bad Request. The request cannot be processed by the server.", response = ErrorResponse.class), + @ApiResponse(code = 403, message = "Username recovery is not enabled.", response = ErrorResponse.class), + @ApiResponse(code = 404, message = "No user found for the given set of claims or no recovery channels are availabe for the user.", response = ErrorResponse.class), + @ApiResponse(code = 409, message = "Mutiple users found for the given claims.", response = ErrorResponse.class), + @ApiResponse(code = 500, message = "Server Error.", response = ErrorResponse.class) + }) + public Response initiateUsernameRecovery(@ApiParam(value = "Request to initate username recovery process. The request should contain the claims to identify the user. User claims are `REQUIRED`." ,required=true) @Valid InitRequest initRequest) { + + return delegate.initiateUsernameRecovery(initRequest ); + } + + @Valid + @POST + @Path("/password/recover") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @ApiOperation(value = "Get Recovery Information ", notes = "- This API is used to send recovery information to the user who matches the recovery code via the channel specified by the channel Id. - NOTE: If the notification channel is EXTERNAL, the API will return a confirmationCode. - Use the returned confimation code with __password recpvery confirm API__ to verify the password recovery process. - The API will return the next API call. ", response = PasswordRecoveryExternalNotifyResponse.class, tags={ "Password Recovery", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "- Password recovery initiated via `EXTERNAL` channel. API will return a `confirmationCode` to confirm password recovery. - Use the confirmation code with __password recpvery confirm API__ to confirm the password recovery. ", response = PasswordRecoveryExternalNotifyResponse.class), + @ApiResponse(code = 202, message = "- Password recovery initiated via internal channels. API will send a `confirmationCode` to the channel specified by the user. - Use the confirmation code with __password recovery confirm API__ to confirm the password recovery. ", response = PasswordRecoveryInternalNotifyResponse.class), + @ApiResponse(code = 400, message = "Bad Request. Request cannot be processed by the server.", response = ErrorResponse.class), + @ApiResponse(code = 403, message = "Password recovery is not enabled.", response = ErrorResponse.class), + @ApiResponse(code = 404, message = "Recovery code is not found.", response = ErrorResponse.class), + @ApiResponse(code = 406, message = "- Recovery code given in the request is not valid or expired. - Channel id is not valid ", response = ErrorResponse.class), + @ApiResponse(code = 500, message = "Server Error.", response = ErrorResponse.class) + }) + public Response recoverPassword(@ApiParam(value = "- Request to receive recovery notifications. - `recoveryCode` and `channelId` are `REQUIRED`. - __NOTE__ `channelId` should always be __larger than 0__. " ,required=true) @Valid RecoveryRequest recoveryRequest) { + + return delegate.recoverPassword(recoveryRequest ); + } + + @Valid + @POST + @Path("/username/recover") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @ApiOperation(value = "Get Recovery Information", notes = "- This API is used to confirm username recovery and send username recovery information to the user who matches the recovery code via the channel specified by the channel Id. - __NOTE__: If the notification channel is __EXTERNAL__, the API will return the username of the user. ", response = UsernameRecoveryNotifyResponse.class, tags={ "Username Recovery", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "Username is successfully recovered and the __notification channel__ is `EXTERNAL`.", response = UsernameRecoveryNotifyResponse.class), + @ApiResponse(code = 202, message = "Username is successfully recovered.", response = UsernameRecoveryNotifyResponse.class), + @ApiResponse(code = 400, message = "Bad Request. Request cannot be processed by the server.", response = ErrorResponse.class), + @ApiResponse(code = 404, message = "Recovery code is not found.", response = ErrorResponse.class), + @ApiResponse(code = 406, message = "- Recovery code given in the request is not valid or expired. - Channel id is not valid ", response = ErrorResponse.class), + @ApiResponse(code = 500, message = "Server Error.", response = ErrorResponse.class) + }) + public Response recoverUsername(@ApiParam(value = "- Request to confirm username recovery and receive recovery notifications. - `recoveryCode` and `channelId` are `REQUIRED`. - __NOTE__ `channelId` should always be __larger than 0__. " ,required=true) @Valid RecoveryRequest recoveryRequest) { + + return delegate.recoverUsername(recoveryRequest ); + } + + @Valid + @POST + @Path("/password/resend") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @ApiOperation(value = "Resend password recovery confirmation details ", notes = "- This API is used to resend a confirmation code to the user via a user preferred channel defined at password recovery. - NOTE: The API cannot be used when the notification channel is external. - The API will return the next API calls. ", response = ResendConfirmationCodeExternalResponse.class, tags={ "Password Recovery", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "- API will return a new `confirmationCode`. - Use the confirmation code with __password recovery confirm API__ to confirm the password recovery. ", response = ResendConfirmationCodeExternalResponse.class), + @ApiResponse(code = 202, message = "- API will send a `confirmationCode` to the channel specified by the user. - Use the confirmation code with __password recovery confirm API__ to confirm the password recovery. ", response = ResendConfirmationCodeInternalResponse.class), + @ApiResponse(code = 400, message = "Bad Request. Request cannot be processed by the server.", response = ErrorResponse.class), + @ApiResponse(code = 404, message = "Resend code is not found.", response = ErrorResponse.class), + @ApiResponse(code = 406, message = "Resend code given in the request is not valid or expired.", response = ErrorResponse.class), + @ApiResponse(code = 500, message = "Server Error.", response = ErrorResponse.class) + }) + public Response resendConfirmation(@ApiParam(value = "- Request to resend the `confirmationCode` to the user via a user preferred channel. - Can send additional properties. " ,required=true) @Valid ResendConfirmationRequest resendConfirmationRequest) { + + return delegate.resendConfirmation(resendConfirmationRequest ); + } + + @Valid + @POST + @Path("/password/reset") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @ApiOperation(value = "Reset password ", notes = "This API is used to reset the password of the user who matches the resetCode given by the confirmation API. ", response = PasswordResetResponse.class, tags={ "Password Recovery" }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "Successful password reset.", response = PasswordResetResponse.class), + @ApiResponse(code = 400, message = "Bad Request. Request cannot be processed by the server.", response = ErrorResponse.class), + @ApiResponse(code = 404, message = "Reset code is not found.", response = ErrorResponse.class), + @ApiResponse(code = 406, message = "Reset code given in the request is not valid or expired.", response = ErrorResponse.class), + @ApiResponse(code = 412, message = "Password policy violation.", response = RetryErrorResponse.class), + @ApiResponse(code = 500, message = "Server Error.", response = ErrorResponse.class) + }) + public Response resetPassword(@ApiParam(value = "- Request to reset the password. - `resetCode` and `password` are required. " ,required=true) @Valid ResetRequest resetRequest) { + + return delegate.resetPassword(resetRequest ); + } + +} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/RecoveryApiService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/RecoveryApiService.java new file mode 100644 index 00000000..54a2dc51 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/RecoveryApiService.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2; + +import org.wso2.carbon.identity.rest.api.user.recovery.v2.*; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.*; +import org.apache.cxf.jaxrs.ext.multipart.Attachment; +import org.apache.cxf.jaxrs.ext.multipart.Multipart; +import java.io.InputStream; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.AccountRecoveryType; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ConfirmRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.InitRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.PasswordRecoveryExternalNotifyResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.PasswordRecoveryInternalNotifyResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.PasswordResetResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RecoveryRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ResendConfirmationCodeExternalResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ResendConfirmationCodeInternalResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ResendConfirmationRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ResetCodeResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ResetRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RetryErrorResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.UsernameRecoveryNotifyResponse; +import javax.ws.rs.core.Response; + + +public interface RecoveryApiService { + + public Response confirmRecovery(ConfirmRequest confirmRequest); + + public Response initiatePasswordRecovery(InitRequest initRequest); + + public Response initiateUsernameRecovery(InitRequest initRequest); + + public Response recoverPassword(RecoveryRequest recoveryRequest); + + public Response recoverUsername(RecoveryRequest recoveryRequest); + + public Response resendConfirmation(ResendConfirmationRequest resendConfirmationRequest); + + public Response resetPassword(ResetRequest resetRequest); +} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/factories/RecoveryApiServiceFactory.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/factories/RecoveryApiServiceFactory.java new file mode 100644 index 00000000..8ce00fcf --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/factories/RecoveryApiServiceFactory.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.factories; + +import org.wso2.carbon.identity.rest.api.user.recovery.v2.RecoveryApiService; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.RecoveryApiServiceImpl; + +public class RecoveryApiServiceFactory { + + private final static RecoveryApiService service = new RecoveryApiServiceImpl(); + + public static RecoveryApiService getRecoveryApi() + { + return service; + } +} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/APICall.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/APICall.java new file mode 100644 index 00000000..f08079ba --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/APICall.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.*; + +/** + * Object that holds next API call details + **/ + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; +@ApiModel(description = "Object that holds next API call details") +public class APICall { + + private String rel; + private String href; + private String type; + + /** + * Next API call + **/ + public APICall rel(String rel) { + + this.rel = rel; + return this; + } + + @ApiModelProperty(example = "next", value = "Next API call") + @JsonProperty("rel") + @Valid + public String getRel() { + return rel; + } + public void setRel(String rel) { + this.rel = rel; + } + + /** + * Next API url + **/ + public APICall href(String href) { + + this.href = href; + return this; + } + + @ApiModelProperty(example = "/api/users/recovery/v2/", value = "Next API url") + @JsonProperty("href") + @Valid + public String getHref() { + return href; + } + public void setHref(String href) { + this.href = href; + } + + /** + * HTTP method type + **/ + public APICall type(String type) { + + this.type = type; + return this; + } + + @ApiModelProperty(example = "POST", value = "HTTP method type") + @JsonProperty("type") + @Valid + public String getType() { + return type; + } + public void setType(String type) { + this.type = type; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + APICall apICall = (APICall) o; + return Objects.equals(this.rel, apICall.rel) && + Objects.equals(this.href, apICall.href) && + Objects.equals(this.type, apICall.type); + } + + @Override + public int hashCode() { + return Objects.hash(rel, href, type); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class APICall {\n"); + + sb.append(" rel: ").append(toIndentedString(rel)).append("\n"); + sb.append(" href: ").append(toIndentedString(href)).append("\n"); + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/AccountRecoveryType.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/AccountRecoveryType.java new file mode 100644 index 00000000..1aedc7ee --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/AccountRecoveryType.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.APICall; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RecoveryChannelInformation; +import javax.validation.constraints.*; + +/** + * Object that encapsulates details of the account recovery channel + **/ + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; +@ApiModel(description = "Object that encapsulates details of the account recovery channel") +public class AccountRecoveryType { + + private String mode; + private String flowConfirmationCode; + private RecoveryChannelInformation channelInfo; + private List links = null; + + + /** + **/ + public AccountRecoveryType mode(String mode) { + + this.mode = mode; + return this; + } + + @ApiModelProperty(example = "recoverWithNotifications", value = "") + @JsonProperty("mode") + @Valid + public String getMode() { + return mode; + } + public void setMode(String mode) { + this.mode = mode; + } + + /** + **/ + public AccountRecoveryType flowConfirmationCode(String flowConfirmationCode) { + + this.flowConfirmationCode = flowConfirmationCode; + return this; + } + + @ApiModelProperty(value = "") + @JsonProperty("flowConfirmationCode") + @Valid + public String getFlowConfirmationCode() { + return flowConfirmationCode; + } + public void setFlowConfirmationCode(String flowConfirmationCode) { + this.flowConfirmationCode = flowConfirmationCode; + } + + /** + **/ + public AccountRecoveryType channelInfo(RecoveryChannelInformation channelInfo) { + + this.channelInfo = channelInfo; + return this; + } + + @ApiModelProperty(value = "") + @JsonProperty("channelInfo") + @Valid + public RecoveryChannelInformation getChannelInfo() { + return channelInfo; + } + public void setChannelInfo(RecoveryChannelInformation channelInfo) { + this.channelInfo = channelInfo; + } + + /** + * Contains available api calls + **/ + public AccountRecoveryType links(List links) { + + this.links = links; + return this; + } + + @ApiModelProperty(value = "Contains available api calls") + @JsonProperty("links") + @Valid + public List getLinks() { + return links; + } + public void setLinks(List links) { + this.links = links; + } + + public AccountRecoveryType addLinksItem(APICall linksItem) { + if (this.links == null) { + this.links = new ArrayList<>(); + } + this.links.add(linksItem); + return this; + } + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AccountRecoveryType accountRecoveryType = (AccountRecoveryType) o; + return Objects.equals(this.mode, accountRecoveryType.mode) && + Objects.equals(this.flowConfirmationCode, accountRecoveryType.flowConfirmationCode) && + Objects.equals(this.channelInfo, accountRecoveryType.channelInfo) && + Objects.equals(this.links, accountRecoveryType.links); + } + + @Override + public int hashCode() { + return Objects.hash(mode, flowConfirmationCode, channelInfo, links); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class AccountRecoveryType {\n"); + + sb.append(" mode: ").append(toIndentedString(mode)).append("\n"); + sb.append(" flowConfirmationCode: ").append(toIndentedString(flowConfirmationCode)).append("\n"); + sb.append(" channelInfo: ").append(toIndentedString(channelInfo)).append("\n"); + sb.append(" links: ").append(toIndentedString(links)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ConfirmRequest.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ConfirmRequest.java new file mode 100644 index 00000000..31dfa0c3 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ConfirmRequest.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.Property; +import javax.validation.constraints.*; + +/** + * Request to confirm password recovery + **/ + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; +@ApiModel(description = "Request to confirm password recovery") +public class ConfirmRequest { + + private String confirmationCode; + private String otp; + private List properties = null; + + + /** + * Confirmation code of the recovery flow + **/ + public ConfirmRequest confirmationCode(String confirmationCode) { + + this.confirmationCode = confirmationCode; + return this; + } + + @ApiModelProperty(example = "1234-2ws34-12345", value = "Confirmation code of the recovery flow") + @JsonProperty("confirmationCode") + @Valid + @NotNull(message = "Property confirmationCode cannot be null.") + public String getConfirmationCode() { + return confirmationCode; + } + public void setConfirmationCode(String confirmationCode) { + this.confirmationCode = confirmationCode; + } + + /** + * OTP sent to the user + **/ + public ConfirmRequest otp(String otp) { + + this.otp = otp; + return this; + } + + @ApiModelProperty(example = "abc123", value = "OTP sent to the user") + @JsonProperty("otp") + @Valid + public String getOtp() { + return otp; + } + public void seOtp(String otp) { + this.otp = otp; + } + + /** + * (OPTIONAL) Additional META properties + **/ + public ConfirmRequest properties(List properties) { + + this.properties = properties; + return this; + } + + @ApiModelProperty(value = "(OPTIONAL) Additional META properties") + @JsonProperty("properties") + @Valid + public List getProperties() { + return properties; + } + public void setProperties(List properties) { + this.properties = properties; + } + + public ConfirmRequest addPropertiesItem(Property propertiesItem) { + if (this.properties == null) { + this.properties = new ArrayList<>(); + } + this.properties.add(propertiesItem); + return this; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ConfirmRequest confirmRequest = (ConfirmRequest) o; + return Objects.equals(this.confirmationCode, confirmRequest.confirmationCode) && + Objects.equals(this.otp, confirmRequest.otp) && + Objects.equals(this.properties, confirmRequest.properties); + } + + @Override + public int hashCode() { + return Objects.hash(confirmationCode, otp, properties); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class ConfirmRequest {\n"); + + sb.append(" confirmationCode: ").append(toIndentedString(confirmationCode)).append("\n"); + sb.append(" otp: ").append(toIndentedString(otp)).append("\n"); + sb.append(" properties: ").append(toIndentedString(properties)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ErrorResponse.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ErrorResponse.java new file mode 100644 index 00000000..7267e580 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ErrorResponse.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.*; + + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; + +public class ErrorResponse { + + private String code; + private String message; + private String description; + private String traceId; + + /** + * Error code corresponding to the error + **/ + public ErrorResponse code(String code) { + + this.code = code; + return this; + } + + @ApiModelProperty(example = "UAR-10001", value = "Error code corresponding to the error") + @JsonProperty("code") + @Valid + public String getCode() { + return code; + } + public void setCode(String code) { + this.code = code; + } + + /** + * Error message + **/ + public ErrorResponse message(String message) { + + this.message = message; + return this; + } + + @ApiModelProperty(example = "invalid_request", value = "Error message") + @JsonProperty("message") + @Valid + public String getMessage() { + return message; + } + public void setMessage(String message) { + this.message = message; + } + + /** + * Description about the error + **/ + public ErrorResponse description(String description) { + + this.description = description; + return this; + } + + @ApiModelProperty(example = "Invalid claim uri", value = "Description about the error") + @JsonProperty("description") + @Valid + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + + /** + * Some Correlation for Error Instance + **/ + public ErrorResponse traceId(String traceId) { + + this.traceId = traceId; + return this; + } + + @ApiModelProperty(example = "2345dfgh678h789bhjk", value = "Some Correlation for Error Instance") + @JsonProperty("traceId") + @Valid + public String getTraceId() { + return traceId; + } + public void setTraceId(String traceId) { + this.traceId = traceId; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ErrorResponse errorResponse = (ErrorResponse) o; + return Objects.equals(this.code, errorResponse.code) && + Objects.equals(this.message, errorResponse.message) && + Objects.equals(this.description, errorResponse.description) && + Objects.equals(this.traceId, errorResponse.traceId); + } + + @Override + public int hashCode() { + return Objects.hash(code, message, description, traceId); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class ErrorResponse {\n"); + + sb.append(" code: ").append(toIndentedString(code)).append("\n"); + sb.append(" message: ").append(toIndentedString(message)).append("\n"); + sb.append(" description: ").append(toIndentedString(description)).append("\n"); + sb.append(" traceId: ").append(toIndentedString(traceId)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/InitRequest.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/InitRequest.java new file mode 100644 index 00000000..dd13ee26 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/InitRequest.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.Property; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.UserClaim; +import javax.validation.constraints.*; + +/** + * Request to initate an account recovery + **/ + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; +@ApiModel(description = "Request to initate an account recovery") +public class InitRequest { + + private List claims = new ArrayList<>(); + + private List properties = null; + + + /** + * User claims to identify the user as UserClaim objects + **/ + public InitRequest claims(List claims) { + + this.claims = claims; + return this; + } + + @ApiModelProperty(required = true, value = "User claims to identify the user as UserClaim objects") + @JsonProperty("claims") + @Valid + @NotNull(message = "Property claims cannot be null.") + + public List getClaims() { + return claims; + } + public void setClaims(List claims) { + this.claims = claims; + } + + public InitRequest addClaimsItem(UserClaim claimsItem) { + this.claims.add(claimsItem); + return this; + } + + /** + * (OPTIONAL) Additional META properties + **/ + public InitRequest properties(List properties) { + + this.properties = properties; + return this; + } + + @ApiModelProperty(value = "(OPTIONAL) Additional META properties") + @JsonProperty("properties") + @Valid + public List getProperties() { + return properties; + } + public void setProperties(List properties) { + this.properties = properties; + } + + public InitRequest addPropertiesItem(Property propertiesItem) { + if (this.properties == null) { + this.properties = new ArrayList<>(); + } + this.properties.add(propertiesItem); + return this; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InitRequest initRequest = (InitRequest) o; + return Objects.equals(this.claims, initRequest.claims) && + Objects.equals(this.properties, initRequest.properties); + } + + @Override + public int hashCode() { + return Objects.hash(claims, properties); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class InitRequest {\n"); + + sb.append(" claims: ").append(toIndentedString(claims)).append("\n"); + sb.append(" properties: ").append(toIndentedString(properties)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordRecoveryExternalNotifyResponse.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordRecoveryExternalNotifyResponse.java new file mode 100644 index 00000000..2bc683b6 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordRecoveryExternalNotifyResponse.java @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.APICall; +import javax.validation.constraints.*; + + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; + +public class PasswordRecoveryExternalNotifyResponse { + + private String code; + private String message; + private String flowConfirmationCode; + private String notificationChannel; + private String confirmationCode; + private String resendCode; + private List links = null; + + + /** + * Success status code + **/ + public PasswordRecoveryExternalNotifyResponse code(String code) { + + this.code = code; + return this; + } + + @ApiModelProperty(example = "PWR-02002", value = "Success status code") + @JsonProperty("code") + @Valid + public String getCode() { + return code; + } + public void setCode(String code) { + this.code = code; + } + + /** + * Success status message + **/ + public PasswordRecoveryExternalNotifyResponse message(String message) { + + this.message = message; + return this; + } + + @ApiModelProperty(example = "successful_request", value = "Success status message") + @JsonProperty("message") + @Valid + public String getMessage() { + return message; + } + public void setMessage(String message) { + this.message = message; + } + + /** + * Recovery flow confirmation code + **/ + public PasswordRecoveryExternalNotifyResponse flowConfirmationCode(String flowConfirmationCode) { + + this.flowConfirmationCode = flowConfirmationCode; + return this; + } + + @ApiModelProperty(example = "1234-1234-1234-1234", value = "Flow confirmation code of the recovery flow") + @JsonProperty("flowConfirmationCode") + @Valid + public String getFlowConfirmationCode() { + return flowConfirmationCode; + } + public void setFlowConfirmationCode(String flowConfirmationCode) { + this.flowConfirmationCode = flowConfirmationCode; + } + + /** + * Channel that is used to send recovery information + **/ + public PasswordRecoveryExternalNotifyResponse notificationChannel(String notificationChannel) { + + this.notificationChannel = notificationChannel; + return this; + } + + @ApiModelProperty(example = "EXTERNAL", value = "Channel that is used to send recovery information") + @JsonProperty("notificationChannel") + @Valid + public String getNotificationChannel() { + return notificationChannel; + } + public void setNotificationChannel(String notificationChannel) { + this.notificationChannel = notificationChannel; + } + + /** + * - Confirmation code for password recovery when the notifications are externally managed. - The confirmation code will be returned only if the notification channel is _EXTERNAL_. Use this code with password confirm API to get a password reset code. + **/ + public PasswordRecoveryExternalNotifyResponse confirmationCode(String confirmationCode) { + + this.confirmationCode = confirmationCode; + return this; + } + + @ApiModelProperty(example = "12345-45678-6789098-8765", value = "- Confirmation code for password recovery when the notifications are externally managed. - The confirmation code will be returned only if the notification channel is _EXTERNAL_. Use this code with password confirm API to get a password reset code. ") + @JsonProperty("confirmationCode") + @Valid + public String getConfirmationCode() { + return confirmationCode; + } + public void setConfirmationCode(String confirmationCode) { + this.confirmationCode = confirmationCode; + } + + /** + * Code to get a new confirmation code. + **/ + public PasswordRecoveryExternalNotifyResponse resendCode(String resendCode) { + + this.resendCode = resendCode; + return this; + } + + @ApiModelProperty(example = "1234-123456-12345-12345", value = "Code to get a new confirmation code.") + @JsonProperty("resendCode") + @Valid + public String getResendCode() { + return resendCode; + } + public void setResendCode(String resendCode) { + this.resendCode = resendCode; + } + + /** + * Contains available api calls + **/ + public PasswordRecoveryExternalNotifyResponse links(List links) { + + this.links = links; + return this; + } + + @ApiModelProperty(value = "Contains available api calls") + @JsonProperty("links") + @Valid + public List getLinks() { + return links; + } + public void setLinks(List links) { + this.links = links; + } + + public PasswordRecoveryExternalNotifyResponse addLinksItem(APICall linksItem) { + if (this.links == null) { + this.links = new ArrayList<>(); + } + this.links.add(linksItem); + return this; + } + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PasswordRecoveryExternalNotifyResponse passwordRecoveryExternalNotifyResponse = (PasswordRecoveryExternalNotifyResponse) o; + return Objects.equals(this.code, passwordRecoveryExternalNotifyResponse.code) && + Objects.equals(this.message, passwordRecoveryExternalNotifyResponse.message) && + Objects.equals(this.flowConfirmationCode, passwordRecoveryExternalNotifyResponse.flowConfirmationCode) && + Objects.equals(this.notificationChannel, passwordRecoveryExternalNotifyResponse.notificationChannel) && + Objects.equals(this.confirmationCode, passwordRecoveryExternalNotifyResponse.confirmationCode) && + Objects.equals(this.resendCode, passwordRecoveryExternalNotifyResponse.resendCode) && + Objects.equals(this.links, passwordRecoveryExternalNotifyResponse.links); + } + + @Override + public int hashCode() { + return Objects.hash(code, message, flowConfirmationCode, notificationChannel, confirmationCode, resendCode, links); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class PasswordRecoveryExternalNotifyResponse {\n"); + + sb.append(" code: ").append(toIndentedString(code)).append("\n"); + sb.append(" message: ").append(toIndentedString(message)).append("\n"); + sb.append(" flowConfirmationCode: ").append(toIndentedString(flowConfirmationCode)).append("\n"); + sb.append(" notificationChannel: ").append(toIndentedString(notificationChannel)).append("\n"); + sb.append(" confirmationCode: ").append(toIndentedString(confirmationCode)).append("\n"); + sb.append(" resendCode: ").append(toIndentedString(resendCode)).append("\n"); + sb.append(" links: ").append(toIndentedString(links)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordRecoveryInternalNotifyResponse.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordRecoveryInternalNotifyResponse.java new file mode 100644 index 00000000..f8e86ff6 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordRecoveryInternalNotifyResponse.java @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.APICall; +import javax.validation.constraints.*; + + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; + +public class PasswordRecoveryInternalNotifyResponse { + + private String code; + private String message; + private String flowConfirmationCode; + private String notificationChannel; + private String resendCode; + private List links = null; + + + /** + * Success status code + **/ + public PasswordRecoveryInternalNotifyResponse code(String code) { + + this.code = code; + return this; + } + + @ApiModelProperty(example = "PWR-02002", value = "Success status code") + @JsonProperty("code") + @Valid + public String getCode() { + return code; + } + public void setCode(String code) { + this.code = code; + } + + /** + * Success status message + **/ + public PasswordRecoveryInternalNotifyResponse message(String message) { + + this.message = message; + return this; + } + + @ApiModelProperty(example = "successful_request", value = "Success status message") + @JsonProperty("message") + @Valid + public String getMessage() { + return message; + } + public void setMessage(String message) { + this.message = message; + } + + /** + * Recovery flow confirmation code + **/ + public PasswordRecoveryInternalNotifyResponse flowConfirmationCode(String flowConfirmationCode) { + + this.flowConfirmationCode = flowConfirmationCode; + return this; + } + + @ApiModelProperty(example = "1234-1234-1234-1234", value = "Flow confirmation code of the recovery flow") + @JsonProperty("flowConfirmationCode") + @Valid + public String getFlowConfirmationCode() { + return flowConfirmationCode; + } + public void setFlowConfirmationCode(String flowConfirmationCode) { + this.flowConfirmationCode = flowConfirmationCode; + } + + /** + * Channel that is used to send recovery information + **/ + public PasswordRecoveryInternalNotifyResponse notificationChannel(String notificationChannel) { + + this.notificationChannel = notificationChannel; + return this; + } + + @ApiModelProperty(example = "EMAIL", value = "Channel that is used to send recovery information") + @JsonProperty("notificationChannel") + @Valid + public String getNotificationChannel() { + return notificationChannel; + } + public void setNotificationChannel(String notificationChannel) { + this.notificationChannel = notificationChannel; + } + + /** + * Code to resend the confirmation code to the user via user user selected channel + **/ + public PasswordRecoveryInternalNotifyResponse resendCode(String resendCode) { + + this.resendCode = resendCode; + return this; + } + + @ApiModelProperty(example = "1234-123456-12345-12345", value = "Code to resend the confirmation code to the user via user user selected channel") + @JsonProperty("resendCode") + @Valid + public String getResendCode() { + return resendCode; + } + public void setResendCode(String resendCode) { + this.resendCode = resendCode; + } + + /** + * Contains available api calls + **/ + public PasswordRecoveryInternalNotifyResponse links(List links) { + + this.links = links; + return this; + } + + @ApiModelProperty(value = "Contains available api calls") + @JsonProperty("links") + @Valid + public List getLinks() { + return links; + } + public void setLinks(List links) { + this.links = links; + } + + public PasswordRecoveryInternalNotifyResponse addLinksItem(APICall linksItem) { + if (this.links == null) { + this.links = new ArrayList<>(); + } + this.links.add(linksItem); + return this; + } + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PasswordRecoveryInternalNotifyResponse passwordRecoveryInternalNotifyResponse = (PasswordRecoveryInternalNotifyResponse) o; + return Objects.equals(this.code, passwordRecoveryInternalNotifyResponse.code) && + Objects.equals(this.message, passwordRecoveryInternalNotifyResponse.message) && + Objects.equals(this.flowConfirmationCode, passwordRecoveryInternalNotifyResponse.flowConfirmationCode) && + Objects.equals(this.notificationChannel, passwordRecoveryInternalNotifyResponse.notificationChannel) && + Objects.equals(this.resendCode, passwordRecoveryInternalNotifyResponse.resendCode) && + Objects.equals(this.links, passwordRecoveryInternalNotifyResponse.links); + } + + @Override + public int hashCode() { + return Objects.hash(code, message, flowConfirmationCode, notificationChannel, resendCode, links); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class PasswordRecoveryInternalNotifyResponse {\n"); + + sb.append(" code: ").append(toIndentedString(code)).append("\n"); + sb.append(" message: ").append(toIndentedString(message)).append("\n"); + sb.append(" flowConfirmationCode: ").append(toIndentedString(flowConfirmationCode)).append("\n"); + sb.append(" notificationChannel: ").append(toIndentedString(notificationChannel)).append("\n"); + sb.append(" resendCode: ").append(toIndentedString(resendCode)).append("\n"); + sb.append(" links: ").append(toIndentedString(links)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordResetResponse.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordResetResponse.java new file mode 100644 index 00000000..9670b10f --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordResetResponse.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.*; + +/** + * API response for a successful password reset + **/ + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; +@ApiModel(description = "API response for a successful password reset") +public class PasswordResetResponse { + + private String code; + private String message; + + /** + * Operation code + **/ + public PasswordResetResponse code(String code) { + + this.code = code; + return this; + } + + @ApiModelProperty(example = "PWR-02001", value = "Operation code") + @JsonProperty("code") + @Valid + public String getCode() { + return code; + } + public void setCode(String code) { + this.code = code; + } + + /** + * Message regarding the operation. + **/ + public PasswordResetResponse message(String message) { + + this.message = message; + return this; + } + + @ApiModelProperty(example = "successful_request", value = "Message regarding the operation.") + @JsonProperty("message") + @Valid + public String getMessage() { + return message; + } + public void setMessage(String message) { + this.message = message; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PasswordResetResponse passwordResetResponse = (PasswordResetResponse) o; + return Objects.equals(this.code, passwordResetResponse.code) && + Objects.equals(this.message, passwordResetResponse.message); + } + + @Override + public int hashCode() { + return Objects.hash(code, message); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class PasswordResetResponse {\n"); + + sb.append(" code: ").append(toIndentedString(code)).append("\n"); + sb.append(" message: ").append(toIndentedString(message)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/Property.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/Property.java new file mode 100644 index 00000000..30a904fb --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/Property.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.*; + +/** + * object that holds a property as a key, value pair + **/ + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; +@ApiModel(description = "object that holds a property as a key, value pair") +public class Property { + + private String key; + private String value; + + /** + * Unique identifier as the key of the peroperty + **/ + public Property key(String key) { + + this.key = key; + return this; + } + + @ApiModelProperty(example = "key", value = "Unique identifier as the key of the peroperty") + @JsonProperty("key") + @Valid + public String getKey() { + return key; + } + public void setKey(String key) { + this.key = key; + } + + /** + * Value of the property + **/ + public Property value(String value) { + + this.value = value; + return this; + } + + @ApiModelProperty(example = "value", value = "Value of the property") + @JsonProperty("value") + @Valid + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Property property = (Property) o; + return Objects.equals(this.key, property.key) && + Objects.equals(this.value, property.value); + } + + @Override + public int hashCode() { + return Objects.hash(key, value); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class Property {\n"); + + sb.append(" key: ").append(toIndentedString(key)).append("\n"); + sb.append(" value: ").append(toIndentedString(value)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/RecoveryChannel.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/RecoveryChannel.java new file mode 100644 index 00000000..1bb26f28 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/RecoveryChannel.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.*; + +/** + * Object with notification channel attributes + **/ + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; +@ApiModel(description = "Object with notification channel attributes") +public class RecoveryChannel { + + private String id; + private String type; + private String value; + private Boolean preferred; + + /** + * Id given to the channel + **/ + public RecoveryChannel id(String id) { + + this.id = id; + return this; + } + + @ApiModelProperty(example = "1", value = "Id given to the channel") + @JsonProperty("id") + @Valid + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + + /** + * Type of the chanel + **/ + public RecoveryChannel type(String type) { + + this.type = type; + return this; + } + + @ApiModelProperty(example = "EMAIL", value = "Type of the chanel") + @JsonProperty("type") + @Valid + public String getType() { + return type; + } + public void setType(String type) { + this.type = type; + } + + /** + * Masked channel value + **/ + public RecoveryChannel value(String value) { + + this.value = value; + return this; + } + + @ApiModelProperty(example = "wso2***********.com", value = "Masked channel value") + @JsonProperty("value") + @Valid + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + + /** + * Whether the channel is a user preferred channel + **/ + public RecoveryChannel preferred(Boolean preferred) { + + this.preferred = preferred; + return this; + } + + @ApiModelProperty(example = "true", value = "Whether the channel is a user preferred channel") + @JsonProperty("preferred") + @Valid + public Boolean getPreferred() { + return preferred; + } + public void setPreferred(Boolean preferred) { + this.preferred = preferred; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RecoveryChannel recoveryChannel = (RecoveryChannel) o; + return Objects.equals(this.id, recoveryChannel.id) && + Objects.equals(this.type, recoveryChannel.type) && + Objects.equals(this.value, recoveryChannel.value) && + Objects.equals(this.preferred, recoveryChannel.preferred); + } + + @Override + public int hashCode() { + return Objects.hash(id, type, value, preferred); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class RecoveryChannel {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append(" value: ").append(toIndentedString(value)).append("\n"); + sb.append(" preferred: ").append(toIndentedString(preferred)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/RecoveryChannelInformation.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/RecoveryChannelInformation.java new file mode 100644 index 00000000..a5c73c21 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/RecoveryChannelInformation.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RecoveryChannel; +import javax.validation.constraints.*; + +/** + * Response with the recovery ID and the available recovery channels + **/ + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; +@ApiModel(description = "Response with the recovery ID and the available recovery channels") +public class RecoveryChannelInformation { + + private String recoveryCode; + private List channels = null; + + + /** + * Code to recovery the user account + **/ + public RecoveryChannelInformation recoveryCode(String recoveryCode) { + + this.recoveryCode = recoveryCode; + return this; + } + + @ApiModelProperty(example = "1234-55678-5668-2345", value = "Code to recovery the user account") + @JsonProperty("recoveryCode") + @Valid + public String getRecoveryCode() { + return recoveryCode; + } + public void setRecoveryCode(String recoveryCode) { + this.recoveryCode = recoveryCode; + } + + /** + * Availabel recovery channels for the user + **/ + public RecoveryChannelInformation channels(List channels) { + + this.channels = channels; + return this; + } + + @ApiModelProperty(value = "Availabel recovery channels for the user") + @JsonProperty("channels") + @Valid + public List getChannels() { + return channels; + } + public void setChannels(List channels) { + this.channels = channels; + } + + public RecoveryChannelInformation addChannelsItem(RecoveryChannel channelsItem) { + if (this.channels == null) { + this.channels = new ArrayList<>(); + } + this.channels.add(channelsItem); + return this; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RecoveryChannelInformation recoveryChannelInformation = (RecoveryChannelInformation) o; + return Objects.equals(this.recoveryCode, recoveryChannelInformation.recoveryCode) && + Objects.equals(this.channels, recoveryChannelInformation.channels); + } + + @Override + public int hashCode() { + return Objects.hash(recoveryCode, channels); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class RecoveryChannelInformation {\n"); + + sb.append(" recoveryCode: ").append(toIndentedString(recoveryCode)).append("\n"); + sb.append(" channels: ").append(toIndentedString(channels)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/RecoveryRequest.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/RecoveryRequest.java new file mode 100644 index 00000000..79c4b94d --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/RecoveryRequest.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.Property; +import javax.validation.constraints.*; + +/** + * Request to start the recovery for the user who matches the recovery code via the given channelID + **/ + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; +@ApiModel(description = "Request to start the recovery for the user who matches the recovery code via the given channelID") +public class RecoveryRequest { + + private String recoveryCode; + private String channelId; + private List properties = null; + + + /** + * Recovery code for the user + **/ + public RecoveryRequest recoveryCode(String recoveryCode) { + + this.recoveryCode = recoveryCode; + return this; + } + + @ApiModelProperty(example = "1234-5678-2455-3433", required = true, value = "Recovery code for the user") + @JsonProperty("recoveryCode") + @Valid + @NotNull(message = "Property recoveryCode cannot be null.") + + public String getRecoveryCode() { + return recoveryCode; + } + public void setRecoveryCode(String recoveryCode) { + this.recoveryCode = recoveryCode; + } + + /** + * Id of the notification channel that user preferrs to get recovery notifications. + **/ + public RecoveryRequest channelId(String channelId) { + + this.channelId = channelId; + return this; + } + + @ApiModelProperty(example = "1", required = true, value = "Id of the notification channel that user preferrs to get recovery notifications.") + @JsonProperty("channelId") + @Valid + @NotNull(message = "Property channelId cannot be null.") + + public String getChannelId() { + return channelId; + } + public void setChannelId(String channelId) { + this.channelId = channelId; + } + + /** + * (OPTIONAL) Additional META properties + **/ + public RecoveryRequest properties(List properties) { + + this.properties = properties; + return this; + } + + @ApiModelProperty(value = "(OPTIONAL) Additional META properties") + @JsonProperty("properties") + @Valid + public List getProperties() { + return properties; + } + public void setProperties(List properties) { + this.properties = properties; + } + + public RecoveryRequest addPropertiesItem(Property propertiesItem) { + if (this.properties == null) { + this.properties = new ArrayList<>(); + } + this.properties.add(propertiesItem); + return this; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RecoveryRequest recoveryRequest = (RecoveryRequest) o; + return Objects.equals(this.recoveryCode, recoveryRequest.recoveryCode) && + Objects.equals(this.channelId, recoveryRequest.channelId) && + Objects.equals(this.properties, recoveryRequest.properties); + } + + @Override + public int hashCode() { + return Objects.hash(recoveryCode, channelId, properties); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class RecoveryRequest {\n"); + + sb.append(" recoveryCode: ").append(toIndentedString(recoveryCode)).append("\n"); + sb.append(" channelId: ").append(toIndentedString(channelId)).append("\n"); + sb.append(" properties: ").append(toIndentedString(properties)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationCodeExternalResponse.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationCodeExternalResponse.java new file mode 100644 index 00000000..49c6ca66 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationCodeExternalResponse.java @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.APICall; +import javax.validation.constraints.*; + +/** + * Object encapsulate the details regarding resend confirmation code + **/ + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; +@ApiModel(description = "Object encapsulate the details regarding resend confirmation code") +public class ResendConfirmationCodeExternalResponse { + + private String code; + private String message; + private String flowConfirmationCode; + private String notificationChannel; + private String confirmationCode; + private String resendCode; + private List links = null; + + + /** + * Success status code + **/ + public ResendConfirmationCodeExternalResponse code(String code) { + + this.code = code; + return this; + } + + @ApiModelProperty(example = "PWR-02002", value = "Success status code") + @JsonProperty("code") + @Valid + public String getCode() { + return code; + } + public void setCode(String code) { + this.code = code; + } + + /** + * Success status message + **/ + public ResendConfirmationCodeExternalResponse message(String message) { + + this.message = message; + return this; + } + + @ApiModelProperty(example = "successful_request", value = "Success status message") + @JsonProperty("message") + @Valid + public String getMessage() { + return message; + } + public void setMessage(String message) { + this.message = message; + } + + /** + * Recovery flow confirmation code + **/ + public ResendConfirmationCodeExternalResponse flowConfirmationCode(String flowConfirmationCode) { + + this.flowConfirmationCode = flowConfirmationCode; + return this; + } + + @ApiModelProperty(example = "1234-1234-1234-1234", value = "Flow confirmation code of the recovery flow") + @JsonProperty("flowConfirmationCode") + @Valid + public String getFlowConfirmationCode() { + return flowConfirmationCode; + } + public void setFlowConfirmationCode(String flowConfirmationCode) { + this.flowConfirmationCode = flowConfirmationCode; + } + + /** + * Channel that is used to send recovery information + **/ + public ResendConfirmationCodeExternalResponse notificationChannel(String notificationChannel) { + + this.notificationChannel = notificationChannel; + return this; + } + + @ApiModelProperty(example = "EMAIL", value = "Channel that is used to send recovery information") + @JsonProperty("notificationChannel") + @Valid + public String getNotificationChannel() { + return notificationChannel; + } + public void setNotificationChannel(String notificationChannel) { + this.notificationChannel = notificationChannel; + } + + /** + * Confirmation code to confirm the password recovery + **/ + public ResendConfirmationCodeExternalResponse confirmationCode(String confirmationCode) { + + this.confirmationCode = confirmationCode; + return this; + } + + @ApiModelProperty(example = "1234-12345-234-123456", value = "Confirmation code to confirm the password recovery") + @JsonProperty("confirmationCode") + @Valid + public String getConfirmationCode() { + return confirmationCode; + } + public void setConfirmationCode(String confirmationCode) { + this.confirmationCode = confirmationCode; + } + + /** + * Resend code to resend the confirmation code + **/ + public ResendConfirmationCodeExternalResponse resendCode(String resendCode) { + + this.resendCode = resendCode; + return this; + } + + @ApiModelProperty(example = "1234-12345-234-123456", value = "Resend code to resend the confirmation code") + @JsonProperty("resendCode") + @Valid + public String getResendCode() { + return resendCode; + } + public void setResendCode(String resendCode) { + this.resendCode = resendCode; + } + + /** + * Contains available api calls + **/ + public ResendConfirmationCodeExternalResponse links(List links) { + + this.links = links; + return this; + } + + @ApiModelProperty(value = "Contains available api calls") + @JsonProperty("links") + @Valid + public List getLinks() { + return links; + } + public void setLinks(List links) { + this.links = links; + } + + public ResendConfirmationCodeExternalResponse addLinksItem(APICall linksItem) { + if (this.links == null) { + this.links = new ArrayList<>(); + } + this.links.add(linksItem); + return this; + } + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ResendConfirmationCodeExternalResponse resendConfirmationCodeExternalResponse = (ResendConfirmationCodeExternalResponse) o; + return Objects.equals(this.code, resendConfirmationCodeExternalResponse.code) && + Objects.equals(this.message, resendConfirmationCodeExternalResponse.message) && + Objects.equals(this.flowConfirmationCode, resendConfirmationCodeExternalResponse.flowConfirmationCode) && + Objects.equals(this.notificationChannel, resendConfirmationCodeExternalResponse.notificationChannel) && + Objects.equals(this.confirmationCode, resendConfirmationCodeExternalResponse.confirmationCode) && + Objects.equals(this.resendCode, resendConfirmationCodeExternalResponse.resendCode) && + Objects.equals(this.links, resendConfirmationCodeExternalResponse.links); + } + + @Override + public int hashCode() { + return Objects.hash(code, message, flowConfirmationCode, notificationChannel, confirmationCode, resendCode, links); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class ResendConfirmationCodeExternalResponse {\n"); + + sb.append(" code: ").append(toIndentedString(code)).append("\n"); + sb.append(" message: ").append(toIndentedString(message)).append("\n"); + sb.append(" flowConfirmationCode: ").append(toIndentedString(flowConfirmationCode)).append("\n"); + sb.append(" notificationChannel: ").append(toIndentedString(notificationChannel)).append("\n"); + sb.append(" confirmationCode: ").append(toIndentedString(confirmationCode)).append("\n"); + sb.append(" resendCode: ").append(toIndentedString(resendCode)).append("\n"); + sb.append(" links: ").append(toIndentedString(links)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationCodeInternalResponse.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationCodeInternalResponse.java new file mode 100644 index 00000000..437706d2 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationCodeInternalResponse.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.APICall; +import javax.validation.constraints.*; + +/** + * Object encapsulate the details regarding resend confirmation code + **/ + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; +@ApiModel(description = "Object encapsulate the details regarding resend confirmation code") +public class ResendConfirmationCodeInternalResponse { + + private String code; + private String message; + private String flowConfirmationCode; + private String notificationChannel; + private String resendCode; + private List links = null; + + + /** + * Success status code + **/ + public ResendConfirmationCodeInternalResponse code(String code) { + + this.code = code; + return this; + } + + @ApiModelProperty(example = "PWR-02002", value = "Success status code") + @JsonProperty("code") + @Valid + public String getCode() { + return code; + } + public void setCode(String code) { + this.code = code; + } + + /** + * Success status message + **/ + public ResendConfirmationCodeInternalResponse message(String message) { + + this.message = message; + return this; + } + + @ApiModelProperty(example = "successful_request", value = "Success status message") + @JsonProperty("message") + @Valid + public String getMessage() { + return message; + } + public void setMessage(String message) { + this.message = message; + } + + /** + * Recovery flow confirmation code + **/ + public ResendConfirmationCodeInternalResponse flowConfirmationCode(String flowConfirmationCode) { + + this.flowConfirmationCode = flowConfirmationCode; + return this; + } + + @ApiModelProperty(example = "1234-1234-1234-1234", value = "Flow confirmation code of the recovery flow") + @JsonProperty("flowConfirmationCode") + @Valid + public String getFlowConfirmationCode() { + return flowConfirmationCode; + } + public void setFlowConfirmationCode(String flowConfirmationCode) { + this.flowConfirmationCode = flowConfirmationCode; + } + + /** + * Channel that is used to send recovery information + **/ + public ResendConfirmationCodeInternalResponse notificationChannel(String notificationChannel) { + + this.notificationChannel = notificationChannel; + return this; + } + + @ApiModelProperty(example = "EMAIL", value = "Channel that is used to send recovery information") + @JsonProperty("notificationChannel") + @Valid + public String getNotificationChannel() { + return notificationChannel; + } + public void setNotificationChannel(String notificationChannel) { + this.notificationChannel = notificationChannel; + } + + /** + * Resend code to resend the confirmation code + **/ + public ResendConfirmationCodeInternalResponse resendCode(String resendCode) { + + this.resendCode = resendCode; + return this; + } + + @ApiModelProperty(example = "1234-12345-234-123456", value = "Resend code to resend the confirmation code") + @JsonProperty("resendCode") + @Valid + public String getResendCode() { + return resendCode; + } + public void setResendCode(String resendCode) { + this.resendCode = resendCode; + } + + /** + * Contains available api calls + **/ + public ResendConfirmationCodeInternalResponse links(List links) { + + this.links = links; + return this; + } + + @ApiModelProperty(value = "Contains available api calls") + @JsonProperty("links") + @Valid + public List getLinks() { + return links; + } + public void setLinks(List links) { + this.links = links; + } + + public ResendConfirmationCodeInternalResponse addLinksItem(APICall linksItem) { + if (this.links == null) { + this.links = new ArrayList<>(); + } + this.links.add(linksItem); + return this; + } + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ResendConfirmationCodeInternalResponse resendConfirmationCodeInternalResponse = (ResendConfirmationCodeInternalResponse) o; + return Objects.equals(this.code, resendConfirmationCodeInternalResponse.code) && + Objects.equals(this.message, resendConfirmationCodeInternalResponse.message) && + Objects.equals(this.flowConfirmationCode, resendConfirmationCodeInternalResponse.flowConfirmationCode) && + Objects.equals(this.notificationChannel, resendConfirmationCodeInternalResponse.notificationChannel) && + Objects.equals(this.resendCode, resendConfirmationCodeInternalResponse.resendCode) && + Objects.equals(this.links, resendConfirmationCodeInternalResponse.links); + } + + @Override + public int hashCode() { + return Objects.hash(code, message, flowConfirmationCode, notificationChannel, resendCode, links); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class ResendConfirmationCodeInternalResponse {\n"); + + sb.append(" code: ").append(toIndentedString(code)).append("\n"); + sb.append(" message: ").append(toIndentedString(message)).append("\n"); + sb.append(" flowConfirmationCode: ").append(toIndentedString(flowConfirmationCode)).append("\n"); + sb.append(" notificationChannel: ").append(toIndentedString(notificationChannel)).append("\n"); + sb.append(" resendCode: ").append(toIndentedString(resendCode)).append("\n"); + sb.append(" links: ").append(toIndentedString(links)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationRequest.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationRequest.java new file mode 100644 index 00000000..7c0f43de --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationRequest.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.Property; +import javax.validation.constraints.*; + +/** + * Request to resend the confirmation code in password recovery + **/ + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; +@ApiModel(description = "Request to resend the confirmation code in password recovery") +public class ResendConfirmationRequest { + + private String resendCode; + private List properties = null; + + + /** + * Resend code returned by the password recovery API + **/ + public ResendConfirmationRequest resendCode(String resendCode) { + + this.resendCode = resendCode; + return this; + } + + @ApiModelProperty(example = "1234-2ws34-1234", value = "Resend code returned by the password recovery API") + @JsonProperty("resendCode") + @Valid + public String getResendCode() { + return resendCode; + } + public void setResendCode(String resendCode) { + this.resendCode = resendCode; + } + + /** + * (OPTIONAL) Additional META properties + **/ + public ResendConfirmationRequest properties(List properties) { + + this.properties = properties; + return this; + } + + @ApiModelProperty(value = "(OPTIONAL) Additional META properties") + @JsonProperty("properties") + @Valid + public List getProperties() { + return properties; + } + public void setProperties(List properties) { + this.properties = properties; + } + + public ResendConfirmationRequest addPropertiesItem(Property propertiesItem) { + if (this.properties == null) { + this.properties = new ArrayList<>(); + } + this.properties.add(propertiesItem); + return this; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ResendConfirmationRequest resendConfirmationRequest = (ResendConfirmationRequest) o; + return Objects.equals(this.resendCode, resendConfirmationRequest.resendCode) && + Objects.equals(this.properties, resendConfirmationRequest.properties); + } + + @Override + public int hashCode() { + return Objects.hash(resendCode, properties); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class ResendConfirmationRequest {\n"); + + sb.append(" resendCode: ").append(toIndentedString(resendCode)).append("\n"); + sb.append(" properties: ").append(toIndentedString(properties)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResetCodeResponse.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResetCodeResponse.java new file mode 100644 index 00000000..075f6eaa --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResetCodeResponse.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.APICall; +import javax.validation.constraints.*; + + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; + +public class ResetCodeResponse { + + private String resetCode; + private List links = null; + + + /** + * Password reset code to reset the password + **/ + public ResetCodeResponse resetCode(String resetCode) { + + this.resetCode = resetCode; + return this; + } + + @ApiModelProperty(example = "1234-55678-5668-2345", value = "Password reset code to reset the password") + @JsonProperty("resetCode") + @Valid + public String getResetCode() { + return resetCode; + } + public void setResetCode(String resetCode) { + this.resetCode = resetCode; + } + + /** + * Contains available api calls + **/ + public ResetCodeResponse links(List links) { + + this.links = links; + return this; + } + + @ApiModelProperty(value = "Contains available api calls") + @JsonProperty("links") + @Valid + public List getLinks() { + return links; + } + public void setLinks(List links) { + this.links = links; + } + + public ResetCodeResponse addLinksItem(APICall linksItem) { + if (this.links == null) { + this.links = new ArrayList<>(); + } + this.links.add(linksItem); + return this; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ResetCodeResponse resetCodeResponse = (ResetCodeResponse) o; + return Objects.equals(this.resetCode, resetCodeResponse.resetCode) && + Objects.equals(this.links, resetCodeResponse.links); + } + + @Override + public int hashCode() { + return Objects.hash(resetCode, links); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class ResetCodeResponse {\n"); + + sb.append(" resetCode: ").append(toIndentedString(resetCode)).append("\n"); + sb.append(" links: ").append(toIndentedString(links)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResetRequest.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResetRequest.java new file mode 100644 index 00000000..f7448454 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResetRequest.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.Property; +import javax.validation.constraints.*; + +/** + * Object to reset the password of a user + **/ + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; +@ApiModel(description = "Object to reset the password of a user") +public class ResetRequest { + + private String resetCode; + private String flowConfirmationCode; + private String password; + private List properties = null; + + + /** + * resetCode given by the confim API + **/ + public ResetRequest resetCode(String resetCode) { + + this.resetCode = resetCode; + return this; + } + + @ApiModelProperty(value = "resetCode given by the confim API") + @JsonProperty("resetCode") + @Valid + @NotNull(message = "Property resetCode cannot be null.") + public String getResetCode() { + return resetCode; + } + public void setResetCode(String resetCode) { + this.resetCode = resetCode; + } + + /** + * Confirmation code of the recovery flow + **/ + public ResetRequest flowConfirmationCode(String flowConfirmationCode) { + + this.flowConfirmationCode = flowConfirmationCode; + return this; + } + + @ApiModelProperty(example = "1234-2ws34-12345", value = "Confirmation code of the recovery flow") + @JsonProperty("flowConfirmationCode") + @Valid + @NotNull(message = "Property flowConfirmationCode cannot be null.") + public String getFlowConfirmationCode() { + return flowConfirmationCode; + } + public void setFlowConfirmationCode(String flowConfirmationCode) { + this.flowConfirmationCode = flowConfirmationCode; + } + + /** + * New password given by the user + **/ + public ResetRequest password(String password) { + + this.password = password; + return this; + } + + @ApiModelProperty(value = "New password given by the user") + @JsonProperty("password") + @Valid + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } + + /** + * (OPTIONAL) Additional META properties + **/ + public ResetRequest properties(List properties) { + + this.properties = properties; + return this; + } + + @ApiModelProperty(value = "(OPTIONAL) Additional META properties") + @JsonProperty("properties") + @Valid + public List getProperties() { + return properties; + } + public void setProperties(List properties) { + this.properties = properties; + } + + public ResetRequest addPropertiesItem(Property propertiesItem) { + if (this.properties == null) { + this.properties = new ArrayList<>(); + } + this.properties.add(propertiesItem); + return this; + } + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ResetRequest resetRequest = (ResetRequest) o; + return Objects.equals(this.resetCode, resetRequest.resetCode) && + Objects.equals(this.flowConfirmationCode, resetRequest.flowConfirmationCode) && + Objects.equals(this.password, resetRequest.password) && + Objects.equals(this.properties, resetRequest.properties); + } + + @Override + public int hashCode() { + return Objects.hash(resetCode, flowConfirmationCode, password, properties); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class ResetRequest {\n"); + + sb.append(" resetCode: ").append(toIndentedString(resetCode)).append("\n"); + sb.append(" flowConfirmationCode: ").append(toIndentedString(flowConfirmationCode)).append("\n"); + sb.append(" password: ").append(toIndentedString(password)).append("\n"); + sb.append(" properties: ").append(toIndentedString(properties)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/RetryErrorResponse.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/RetryErrorResponse.java new file mode 100644 index 00000000..32a1ebd2 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/RetryErrorResponse.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.APICall; +import javax.validation.constraints.*; + + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; + +public class RetryErrorResponse { + + private String code; + private String message; + private String description; + private String traceId; + private String resetCode; + private List links = null; + + + /** + * Error code corresponding to the error + **/ + public RetryErrorResponse code(String code) { + + this.code = code; + return this; + } + + @ApiModelProperty(example = "PWR-10004", value = "Error code corresponding to the error") + @JsonProperty("code") + @Valid + public String getCode() { + return code; + } + public void setCode(String code) { + this.code = code; + } + + /** + * Error message + **/ + public RetryErrorResponse message(String message) { + + this.message = message; + return this; + } + + @ApiModelProperty(example = "Retry", value = "Error message") + @JsonProperty("message") + @Valid + public String getMessage() { + return message; + } + public void setMessage(String message) { + this.message = message; + } + + /** + * Error description + **/ + public RetryErrorResponse description(String description) { + + this.description = description; + return this; + } + + @ApiModelProperty(example = "Password policy violation", value = "Error description") + @JsonProperty("description") + @Valid + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + + /** + * Some Correlation for Error Instance + **/ + public RetryErrorResponse traceId(String traceId) { + + this.traceId = traceId; + return this; + } + + @ApiModelProperty(example = "2345dfgh678h789bhjk", value = "Some Correlation for Error Instance") + @JsonProperty("traceId") + @Valid + public String getTraceId() { + return traceId; + } + public void setTraceId(String traceId) { + this.traceId = traceId; + } + + /** + * Password reset code used in the request + **/ + public RetryErrorResponse resetCode(String resetCode) { + + this.resetCode = resetCode; + return this; + } + + @ApiModelProperty(example = "1234-34567-3456-2345678", value = "Password reset code used in the request") + @JsonProperty("resetCode") + @Valid + public String getResetCode() { + return resetCode; + } + public void setResetCode(String resetCode) { + this.resetCode = resetCode; + } + + /** + * Contains available api calls + **/ + public RetryErrorResponse links(List links) { + + this.links = links; + return this; + } + + @ApiModelProperty(value = "Contains available api calls") + @JsonProperty("links") + @Valid + public List getLinks() { + return links; + } + public void setLinks(List links) { + this.links = links; + } + + public RetryErrorResponse addLinksItem(APICall linksItem) { + if (this.links == null) { + this.links = new ArrayList<>(); + } + this.links.add(linksItem); + return this; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RetryErrorResponse retryErrorResponse = (RetryErrorResponse) o; + return Objects.equals(this.code, retryErrorResponse.code) && + Objects.equals(this.message, retryErrorResponse.message) && + Objects.equals(this.description, retryErrorResponse.description) && + Objects.equals(this.traceId, retryErrorResponse.traceId) && + Objects.equals(this.resetCode, retryErrorResponse.resetCode) && + Objects.equals(this.links, retryErrorResponse.links); + } + + @Override + public int hashCode() { + return Objects.hash(code, message, description, traceId, resetCode, links); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class RetryErrorResponse {\n"); + + sb.append(" code: ").append(toIndentedString(code)).append("\n"); + sb.append(" message: ").append(toIndentedString(message)).append("\n"); + sb.append(" description: ").append(toIndentedString(description)).append("\n"); + sb.append(" traceId: ").append(toIndentedString(traceId)).append("\n"); + sb.append(" resetCode: ").append(toIndentedString(resetCode)).append("\n"); + sb.append(" links: ").append(toIndentedString(links)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/UserClaim.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/UserClaim.java new file mode 100644 index 00000000..7d39da7d --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/UserClaim.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.*; + +/** + * Object that holds a user claim and the corresponding value + **/ + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; +@ApiModel(description = "Object that holds a user claim and the corresponding value") +public class UserClaim { + + private String uri; + private String value; + + /** + * Claim uri + **/ + public UserClaim uri(String uri) { + + this.uri = uri; + return this; + } + + @ApiModelProperty(example = "http://wso2.org/claims/givenname", value = "Claim uri") + @JsonProperty("uri") + @Valid + public String getUri() { + return uri; + } + public void setUri(String uri) { + this.uri = uri; + } + + /** + * Value for the claim + **/ + public UserClaim value(String value) { + + this.value = value; + return this; + } + + @ApiModelProperty(example = "user1", value = "Value for the claim") + @JsonProperty("value") + @Valid + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + UserClaim userClaim = (UserClaim) o; + return Objects.equals(this.uri, userClaim.uri) && + Objects.equals(this.value, userClaim.value); + } + + @Override + public int hashCode() { + return Objects.hash(uri, value); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class UserClaim {\n"); + + sb.append(" uri: ").append(toIndentedString(uri)).append("\n"); + sb.append(" value: ").append(toIndentedString(value)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/UsernameRecoveryNotifyResponse.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/UsernameRecoveryNotifyResponse.java new file mode 100644 index 00000000..1332d950 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/UsernameRecoveryNotifyResponse.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.*; + +/** + * API response for successful username recovery + **/ + +import io.swagger.annotations.*; +import java.util.Objects; +import javax.validation.Valid; +import javax.xml.bind.annotation.*; +@ApiModel(description = "API response for successful username recovery") +public class UsernameRecoveryNotifyResponse { + + private String code; + private String message; + private String notificationChannel; + private String username; + + /** + * Success status code + **/ + public UsernameRecoveryNotifyResponse code(String code) { + + this.code = code; + return this; + } + + @ApiModelProperty(example = "UNR-02001", required = true, value = "Success status code") + @JsonProperty("code") + @Valid + @NotNull(message = "Property code cannot be null.") + + public String getCode() { + return code; + } + public void setCode(String code) { + this.code = code; + } + + /** + * Success status message + **/ + public UsernameRecoveryNotifyResponse message(String message) { + + this.message = message; + return this; + } + + @ApiModelProperty(example = "successful_request", required = true, value = "Success status message") + @JsonProperty("message") + @Valid + @NotNull(message = "Property message cannot be null.") + + public String getMessage() { + return message; + } + public void setMessage(String message) { + this.message = message; + } + + /** + * Channel which the recovery information is sent to the user + **/ + public UsernameRecoveryNotifyResponse notificationChannel(String notificationChannel) { + + this.notificationChannel = notificationChannel; + return this; + } + + @ApiModelProperty(example = "EXTERNAL", required = true, value = "Channel which the recovery information is sent to the user") + @JsonProperty("notificationChannel") + @Valid + @NotNull(message = "Property notificationChannel cannot be null.") + + public String getNotificationChannel() { + return notificationChannel; + } + public void setNotificationChannel(String notificationChannel) { + this.notificationChannel = notificationChannel; + } + + /** + * - Username of the user - Username will be returned _ONLY IF_ the notification channel is `EXTERNAL` + **/ + public UsernameRecoveryNotifyResponse username(String username) { + + this.username = username; + return this; + } + + @ApiModelProperty(example = "user1", required = true, value = "- Username of the user - Username will be returned _ONLY IF_ the notification channel is `EXTERNAL` ") + @JsonProperty("username") + @Valid + @NotNull(message = "Property username cannot be null.") + + public String getUsername() { + return username; + } + public void setUsername(String username) { + this.username = username; + } + + + + @Override + public boolean equals(java.lang.Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + UsernameRecoveryNotifyResponse usernameRecoveryNotifyResponse = (UsernameRecoveryNotifyResponse) o; + return Objects.equals(this.code, usernameRecoveryNotifyResponse.code) && + Objects.equals(this.message, usernameRecoveryNotifyResponse.message) && + Objects.equals(this.notificationChannel, usernameRecoveryNotifyResponse.notificationChannel) && + Objects.equals(this.username, usernameRecoveryNotifyResponse.username); + } + + @Override + public int hashCode() { + return Objects.hash(code, message, notificationChannel, username); + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("class UsernameRecoveryNotifyResponse {\n"); + + sb.append(" code: ").append(toIndentedString(code)).append("\n"); + sb.append(" message: ").append(toIndentedString(message)).append("\n"); + sb.append(" notificationChannel: ").append(toIndentedString(notificationChannel)).append("\n"); + sb.append(" username: ").append(toIndentedString(username)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n"); + } +} + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/RecoveryApiServiceImpl.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/RecoveryApiServiceImpl.java new file mode 100644 index 00000000..b49ed427 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/RecoveryApiServiceImpl.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl; + +import org.springframework.beans.factory.annotation.Autowired; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.RecoveryApiService; + +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.PasswordRecoveryService; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.UsernameRecoveryService; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ConfirmRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.InitRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RecoveryRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ResendConfirmationRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ResetRequest; + +import javax.ws.rs.core.Response; + +/** + * Implementation of RecoveryApi Service. + */ +public class RecoveryApiServiceImpl implements RecoveryApiService { + + @Autowired + private UsernameRecoveryService usernameRecoveryService; + + @Autowired + private PasswordRecoveryService passwordRecoveryService; + + @Override + public Response confirmRecovery(ConfirmRequest confirmRequest) { + + return passwordRecoveryService.confirmRecovery(confirmRequest); + } + + @Override + public Response initiatePasswordRecovery(InitRequest initRequest) { + + return passwordRecoveryService.initiatePasswordRecovery(initRequest); + } + + @Override + public Response initiateUsernameRecovery(InitRequest initRequest) { + + return usernameRecoveryService.initiateUsernameRecovery(initRequest); + } + + @Override + public Response recoverPassword(RecoveryRequest recoveryRequest) { + + return passwordRecoveryService.recoverPassword(recoveryRequest); + } + + @Override + public Response recoverUsername(RecoveryRequest recoveryRequest) { + + return usernameRecoveryService.recoverUsername(recoveryRequest); + } + + @Override + public Response resendConfirmation(ResendConfirmationRequest resendConfirmationRequest) { + + return passwordRecoveryService.resendConfirmation(resendConfirmationRequest); + } + + @Override + public Response resetPassword(ResetRequest resetRequest) { + + return passwordRecoveryService.resetPassword(resetRequest); + } +} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/Constants.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/Constants.java new file mode 100644 index 00000000..061aae10 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/Constants.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core; + +import static org.wso2.carbon.identity.api.user.common.Constants.USER_API_PATH_COMPONENT; + +/** + * Constants for the recovery endpoint. + */ +public class Constants { + + public static final String SERVER_ERROR = "Error occurred in the server while performing the task."; + public static final String DEFAULT_RESPONSE_CONTENT_TYPE = "application/json"; + public static final String HEADER_CONTENT_TYPE = "Content-Type"; + + // Default error messages. + public static final String STATUS_FORBIDDEN_MESSAGE_DEFAULT = "Forbidden"; + public static final String STATUS_NOT_FOUND_MESSAGE_DEFAULT = "Not Found"; + public static final String STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT = "Internal server error"; + public static final String STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT = "Not Accepted"; + public static final String STATUS_CONFLICT_MESSAGE_DEFAULT = "Conflict"; + public static final String STATUS_PRECONDITION_FAILED_MESSAGE_DEFAULT = "Precondition Failed"; + public static final String STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT = + "The server encountered an internal error. Please contact administrator."; + + // Recovery type. + public static final String RECOVERY_WITH_NOTIFICATIONS = "recoverWithNotifications"; + public static final String RECOVER_WITH_CHALLENGE_QUESTIONS = "recoverWithChallengeQuestions"; + + public static final String ACCOUNT_RECOVERY_ENDPOINT_BASEPATH = USER_API_PATH_COMPONENT + "/v2"; + public static final String CHALLENGE_QUESTIONS_ENDPOINT_BASEPATH = "identity/recovery/v0.9"; + + /** + * Relation states for the APIs. + */ + public static class RelationStates { + + public static final String NEXT_REL = "next"; + public static final String RESEND_REL = "resend"; + } + + /** + * Enum contains the recovery api names and the corresponding urls. + */ + public enum APICall { + + INITIATE_USERNAME_RECOVERY_API("POST", "initiate_username_recovery", + "/recovery/username/init"), + INITIATE_PASSWORD_RECOVERY_API("POST", "initiate_password_recovery", + "/recovery/password/init"), + RECOVER_USERNAME_API("POST", "recover_username", + "/recovery/username/recover"), + RECOVER_PASSWORD_API("POST", "recover_password", + "/recovery/password/recover"), + CONFIRM_PASSWORD_RECOVERY_API("POST", "confirm_password_recovery", + "/recovery/password/confirm"), + RESET_PASSWORD_API("POST", "reset_password", + "/recovery/password/reset"), + RESEND_CONFIRMATION_API("POST", "resend_confirmation", + "/recovery/password/resend"), + RECOVER_WITH_SECURITY_QUESTIONS_API("GET", "security_questions_api", + "/security-question?username=%s"); + + /** + * Name of the API. + */ + private final String apiName; + + /** + * Url of the API. + */ + private final String apiUrl; + + /** + * Http method call. + */ + private String type; + + APICall(String type, String apiName, String apiUrl) { + + this.type = type; + this.apiName = apiName; + this.apiUrl = apiUrl; + } + + /** + * Get http method type. + * + * @return Get http method type + */ + public String getType() { + return type; + } + + /** + * Get the url of the API. + * + * @return API url + */ + public String getApiUrl() { + + return apiUrl; + } + } +} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java new file mode 100644 index 00000000..86090364 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java @@ -0,0 +1,463 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.identity.api.user.common.Util; +import org.wso2.carbon.identity.api.user.recovery.commons.UserAccountRecoveryServiceDataHolder; +import org.wso2.carbon.identity.governance.service.notification.NotificationChannels; +import org.wso2.carbon.identity.recovery.IdentityRecoveryClientException; +import org.wso2.carbon.identity.recovery.IdentityRecoveryConstants; +import org.wso2.carbon.identity.recovery.IdentityRecoveryException; +import org.wso2.carbon.identity.recovery.dto.PasswordRecoverDTO; +import org.wso2.carbon.identity.recovery.dto.PasswordResetCodeDTO; +import org.wso2.carbon.identity.recovery.dto.RecoveryChannelInfoDTO; +import org.wso2.carbon.identity.recovery.dto.RecoveryInformationDTO; +import org.wso2.carbon.identity.recovery.dto.ResendConfirmationDTO; +import org.wso2.carbon.identity.recovery.dto.SuccessfulPasswordResetDTO; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.utils.RecoveryUtil; + +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.APICall; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.AccountRecoveryType; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ConfirmRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.InitRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.PasswordRecoveryExternalNotifyResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.PasswordRecoveryInternalNotifyResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.PasswordResetResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RecoveryChannel; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RecoveryChannelInformation; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RecoveryRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ResendConfirmationCodeExternalResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ResendConfirmationCodeInternalResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ResendConfirmationRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ResetCodeResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ResetRequest; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import javax.ws.rs.core.Response; + +/** + * Call internal OSGI services to perform password recovery. + */ +public class PasswordRecoveryService { + + private static final Log log = LogFactory.getLog(PasswordRecoveryService.class.getName()); + + /** + * Initiate Password Recovery from POST. + * + * @param initRequest {@link InitRequest} object which holds the information in the account recovery + * request + * @return Response + */ + public Response initiatePasswordRecovery(InitRequest initRequest) { + + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + Map userClaims = RecoveryUtil.buildUserClaimsMap(initRequest.getClaims()); + try { + // Get password recovery notification information. + RecoveryInformationDTO recoveryInformationDTO = + UserAccountRecoveryServiceDataHolder.getPasswordRecoveryManager().initiate(userClaims, tenantDomain, + RecoveryUtil.buildPropertiesMap(initRequest.getProperties())); + // If RecoveryChannelInfoDTO is null throw not found error. + if (recoveryInformationDTO == null) { + if (log.isDebugEnabled()) { + String message = "No recovery information for password recovery request"; + log.debug(message); + } + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } + return Response.ok().entity(buildPasswordRecoveryInitResponse(tenantDomain, recoveryInformationDTO)) + .build(); + } catch (IdentityRecoveryClientException e) { + throw RecoveryUtil.handleClientExceptions(PasswordRecoveryService.class.getName(), tenantDomain, + IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation(), e); + } catch (IdentityRecoveryException e) { + throw RecoveryUtil.buildInternalServerErrorResponse(PasswordRecoveryService.class.getName(), + Constants.SERVER_ERROR, e.getErrorCode(), Util.getCorrelation(), e); + } + } + + /** + * Send the recovery notifications to the user via user preferred channel given by the channelId param. + * + * @param recoveryRequest {@link RecoveryRequest} Object which holds the recovery information in the + * password recovery request + * @return Response + */ + public Response recoverPassword(RecoveryRequest recoveryRequest) { + + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + String recoveryId = recoveryRequest.getRecoveryCode(); + String channelId = recoveryRequest.getChannelId(); + try { + PasswordRecoverDTO passwordRecoverDTO = UserAccountRecoveryServiceDataHolder.getPasswordRecoveryManager() + .notify(recoveryId, channelId, tenantDomain, + RecoveryUtil.buildPropertiesMap(recoveryRequest.getProperties())); + if (passwordRecoverDTO == null) { + if (log.isDebugEnabled()) { + String message = String + .format("No password recovery data object for recovery code : %s", recoveryId); + log.debug(message); + } + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } + return buildPasswordRecoveryResponse(tenantDomain, passwordRecoverDTO.getNotificationChannel(), + passwordRecoverDTO); + } catch (IdentityRecoveryClientException e) { + throw RecoveryUtil.handleClientExceptions(PasswordRecoveryService.class.getName(), tenantDomain, + IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation(), e); + } catch (IdentityRecoveryException e) { + throw RecoveryUtil.buildInternalServerErrorResponse(PasswordRecoveryService.class.getName(), + Constants.SERVER_ERROR, e.getErrorCode(), Util.getCorrelation(), e); + } + } + + /** + * Validate the recovery code given for verify password reset. + * + * @param confirmRequest {@link ConfirmRequest}Confirmation code object received for password recovery + * @return Response + */ + public Response confirmRecovery(ConfirmRequest confirmRequest) { + + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + try { + PasswordResetCodeDTO passwordResetCodeDTO = + UserAccountRecoveryServiceDataHolder.getPasswordRecoveryManager() + .confirm(confirmRequest.getOtp(), confirmRequest.getConfirmationCode(), tenantDomain, + RecoveryUtil.buildPropertiesMap(confirmRequest.getProperties())); + return Response.ok().entity(buildResetCodeResponse(tenantDomain, passwordResetCodeDTO)).build(); + } catch (IdentityRecoveryClientException e) { + throw RecoveryUtil.handleClientExceptions(PasswordRecoveryService.class.getName(), tenantDomain, + IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation(), e); + } catch (IdentityRecoveryException e) { + throw RecoveryUtil.buildInternalServerErrorResponse(PasswordRecoveryService.class.getName(), + Constants.SERVER_ERROR, e.getErrorCode(), Util.getCorrelation(), e); + } + } + + /** + * Update the password of the user with the new given password. + * + * @param resetRequest {@link ResetRequest} Object which holds the password reset code and password reset + * information + * @return Response + */ + public Response resetPassword(ResetRequest resetRequest) { + + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + char[] password = resetRequest.getPassword().toCharArray(); + try { + SuccessfulPasswordResetDTO successfulPasswordResetDTO = + UserAccountRecoveryServiceDataHolder.getPasswordRecoveryManager() + .reset(resetRequest.getResetCode(), resetRequest.getFlowConfirmationCode(), password, + RecoveryUtil.buildPropertiesMap(resetRequest.getProperties())); + return Response.ok().entity(buildPasswordResetResponse(successfulPasswordResetDTO)).build(); + } catch (IdentityRecoveryClientException e) { + // Send the reset code again for a retry attempt. + throw RecoveryUtil.handleClientExceptions(PasswordRecoveryService.class.getName(), tenantDomain, + IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, resetRequest.getResetCode(), + Util.getCorrelation(), e); + } catch (IdentityRecoveryException e) { + throw RecoveryUtil.buildInternalServerErrorResponse(PasswordRecoveryService.class.getName(), + Constants.SERVER_ERROR, e.getErrorCode(), Util.getCorrelation(), e); + } + } + + /** + * Resend the recovery confirmation code to the user. + * + * @param resendConfirmationRequest ResendConfirmationRequest {@link ResendConfirmationRequest} object + * which wraps the resend request + * @return Response + */ + public Response resendConfirmation(ResendConfirmationRequest resendConfirmationRequest) { + + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + String resendCode = resendConfirmationRequest.getResendCode(); + Map properties = RecoveryUtil.buildPropertiesMap(resendConfirmationRequest.getProperties()); + try { + ResendConfirmationDTO resendConfirmationDTO = + UserAccountRecoveryServiceDataHolder.getPasswordRecoveryManager() + .resend(tenantDomain, resendCode, properties); + if (resendConfirmationDTO == null) { + if (log.isDebugEnabled()) { + log.debug("No ResendConfirmationDTO data for resend code :" + resendCode); + } + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } + return buildResendConfirmationResponse(tenantDomain, resendConfirmationDTO); + } catch (IdentityRecoveryClientException e) { + throw RecoveryUtil.handleClientExceptions(PasswordRecoveryService.class.getName(), tenantDomain, + IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation(), e); + } catch (IdentityRecoveryException e) { + throw RecoveryUtil.buildInternalServerErrorResponse(PasswordRecoveryService.class.getName(), + Constants.SERVER_ERROR, e.getErrorCode(), Util.getCorrelation(), e); + } + } + + /** + * Build Resend confirmation code response according to the notification channel. + * + * @param tenantDomain Tenant domain in the request. + * @param resendConfirmationDTO ResendConfirmationDTO + * @return Response + */ + private Response buildResendConfirmationResponse(String tenantDomain, + ResendConfirmationDTO resendConfirmationDTO) { + + ArrayList apiCallsArrayList = new ArrayList<>(); + // Add confirm API call information. + apiCallsArrayList.add(RecoveryUtil.buildApiCall(Constants.APICall.CONFIRM_PASSWORD_RECOVERY_API.getType(), + Constants.RelationStates.NEXT_REL, RecoveryUtil + .buildURIForBody(tenantDomain, Constants.APICall.CONFIRM_PASSWORD_RECOVERY_API.getApiUrl(), + Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); + // Add resend confirmation code API call information. + apiCallsArrayList.add(RecoveryUtil.buildApiCall(Constants.APICall.RESEND_CONFIRMATION_API.getType(), + Constants.RelationStates.RESEND_REL, RecoveryUtil + .buildURIForBody(tenantDomain, Constants.APICall.RESEND_CONFIRMATION_API.getApiUrl(), + Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); + if (NotificationChannels.EXTERNAL_CHANNEL.getChannelType() + .equals(resendConfirmationDTO.getNotificationChannel())) { + ResendConfirmationCodeExternalResponse resendConfirmationCodeExternalResponse = + new ResendConfirmationCodeExternalResponse(); + resendConfirmationCodeExternalResponse.setCode(resendConfirmationDTO.getSuccessCode()); + resendConfirmationCodeExternalResponse.setMessage(resendConfirmationDTO.getSuccessMessage()); + resendConfirmationCodeExternalResponse.setFlowConfirmationCode(resendConfirmationDTO.getRecoveryFlowId()); + resendConfirmationCodeExternalResponse + .setNotificationChannel(resendConfirmationDTO.getNotificationChannel()); + resendConfirmationCodeExternalResponse.setResendCode(resendConfirmationDTO.getResendCode()); + resendConfirmationCodeExternalResponse + .setConfirmationCode(resendConfirmationDTO.getExternalConfirmationCode()); + resendConfirmationCodeExternalResponse.setLinks(apiCallsArrayList); + return Response.ok().entity(resendConfirmationCodeExternalResponse).build(); + } else { + ResendConfirmationCodeInternalResponse resendConfirmationCodeInternalResponse = + new ResendConfirmationCodeInternalResponse(); + resendConfirmationCodeInternalResponse.setCode(resendConfirmationDTO.getSuccessCode()); + resendConfirmationCodeInternalResponse.setMessage(resendConfirmationDTO.getSuccessMessage()); + resendConfirmationCodeInternalResponse.setFlowConfirmationCode(resendConfirmationDTO.getRecoveryFlowId()); + resendConfirmationCodeInternalResponse + .setNotificationChannel(resendConfirmationDTO.getNotificationChannel()); + resendConfirmationCodeInternalResponse.setResendCode(resendConfirmationDTO.getResendCode()); + resendConfirmationCodeInternalResponse.setLinks(apiCallsArrayList); + return Response.accepted().entity(resendConfirmationCodeInternalResponse).build(); + } + } + + /** + * Build successful response for successful password update. + * + * @param successfulPasswordResetDTO SuccessfulPasswordResetDTO object + * @return PasswordResetResponse + */ + private PasswordResetResponse buildPasswordResetResponse( + SuccessfulPasswordResetDTO successfulPasswordResetDTO) { + + PasswordResetResponse passwordResetResponseDTO = new PasswordResetResponse(); + passwordResetResponseDTO.setCode(successfulPasswordResetDTO.getSuccessCode()); + passwordResetResponseDTO.setMessage(successfulPasswordResetDTO.getMessage()); + return passwordResetResponseDTO; + } + + /** + * Build the ResetCodeResponse for successful confirmation code validation. + * + * @param tenantDomain Tenant Domain + * @param passwordResetCodeDTO {@link PasswordResetCodeDTO}PasswordResetCodeDTO + * @return ResetCodeResponseDTO {@link ResetCodeResponse}object with a password reset code + */ + private ResetCodeResponse buildResetCodeResponse(String tenantDomain, + PasswordResetCodeDTO passwordResetCodeDTO) { + + // Build next API calls list. + ArrayList apiCallsArrayList = new ArrayList<>(); + apiCallsArrayList.add(RecoveryUtil + .buildApiCall(Constants.APICall.RESET_PASSWORD_API.getType(), Constants.RelationStates.NEXT_REL, + RecoveryUtil.buildURIForBody(tenantDomain, Constants.APICall.RESET_PASSWORD_API.getApiUrl(), + Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); + ResetCodeResponse resetCodeResponseDTO = new ResetCodeResponse(); + resetCodeResponseDTO.setResetCode(passwordResetCodeDTO.getPasswordResetCode()); + resetCodeResponseDTO.setLinks(apiCallsArrayList); + return resetCodeResponseDTO; + } + + /** + * Build the successful response according to the notification channel. + * + * @param tenantDomain Tenant domain + * @param notificationChannel Notification channel + * @param passwordRecoverDTO {@link PasswordRecoverDTO} PasswordRecoverDTO + * @return Response + */ + private Response buildPasswordRecoveryResponse(String tenantDomain, String notificationChannel, + PasswordRecoverDTO passwordRecoverDTO) { + + // Build next API calls. + ArrayList apiCallsArrayList = new ArrayList<>(); + apiCallsArrayList.add(RecoveryUtil.buildApiCall(Constants.APICall.CONFIRM_PASSWORD_RECOVERY_API.getType(), + Constants.RelationStates.NEXT_REL, RecoveryUtil + .buildURIForBody(tenantDomain, Constants.APICall.CONFIRM_PASSWORD_RECOVERY_API.getApiUrl(), + Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); + // Add resend confirmation code API call information. + apiCallsArrayList.add(RecoveryUtil.buildApiCall(Constants.APICall.RESEND_CONFIRMATION_API.getType(), + Constants.RelationStates.RESEND_REL, RecoveryUtil + .buildURIForBody(tenantDomain, Constants.APICall.RESEND_CONFIRMATION_API.getApiUrl(), + Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); + if (NotificationChannels.EXTERNAL_CHANNEL.getChannelType().equals(notificationChannel)) { + return Response.ok() + .entity(buildPasswordRecoveryExternalResponse(passwordRecoverDTO, apiCallsArrayList)).build(); + } else { + return Response.accepted() + .entity(buildPasswordRecoveryInternalResponse(passwordRecoverDTO, apiCallsArrayList)).build(); + } + } + + /** + * Build PasswordRecoveryExternalNotifyResponse for successful password recovery. + * + * @param passwordRecoverDTO {@link PasswordRecoverDTO}PasswordRecoverDTO object + * @param apiCallsArrayList List of available API calls + * @return {@link PasswordRecoveryExternalNotifyResponse} Password recovery external notify response + */ + private PasswordRecoveryExternalNotifyResponse buildPasswordRecoveryExternalResponse( + PasswordRecoverDTO passwordRecoverDTO, ArrayList apiCallsArrayList) { + + PasswordRecoveryExternalNotifyResponse passwordRecoveryResponse = + new PasswordRecoveryExternalNotifyResponse(); + passwordRecoveryResponse.setCode(passwordRecoverDTO.getCode()); + passwordRecoveryResponse.setMessage(passwordRecoverDTO.getMessage()); + passwordRecoveryResponse.setFlowConfirmationCode(passwordRecoverDTO.getRecoveryFlowId()); + passwordRecoveryResponse.setNotificationChannel(passwordRecoverDTO.getNotificationChannel()); + passwordRecoveryResponse.setConfirmationCode(passwordRecoverDTO.getConfirmationCode()); + passwordRecoveryResponse.setResendCode(passwordRecoverDTO.getResendCode()); + passwordRecoveryResponse.setLinks(apiCallsArrayList); + return passwordRecoveryResponse; + } + + /** + * Build PasswordRecoveryInternalNotifyResponse for successful password recovery. + * + * @param passwordRecoverDTO {@link PasswordRecoverDTO}PasswordRecoverDTO object + * @param apiCallsArrayList List of available API calls + * @return {@link PasswordRecoveryInternalNotifyResponse} + */ + private PasswordRecoveryInternalNotifyResponse buildPasswordRecoveryInternalResponse( + PasswordRecoverDTO passwordRecoverDTO, ArrayList apiCallsArrayList) { + + PasswordRecoveryInternalNotifyResponse passwordRecoveryResponse = + new PasswordRecoveryInternalNotifyResponse(); + passwordRecoveryResponse.setCode(passwordRecoverDTO.getCode()); + passwordRecoveryResponse.setMessage(passwordRecoverDTO.getMessage()); + passwordRecoveryResponse.setFlowConfirmationCode(passwordRecoverDTO.getRecoveryFlowId()); + passwordRecoveryResponse.setNotificationChannel(passwordRecoverDTO.getNotificationChannel()); + passwordRecoveryResponse.setLinks(apiCallsArrayList); + passwordRecoveryResponse.setResendCode(passwordRecoverDTO.getResendCode()); + return passwordRecoveryResponse; + } + + /** + * Build recovery information for recover with notifications. + * + * @param recoveryType Recovery type + * @param recoveryFlowId Recovery flow id + * @param recoveryChannelInformation RecoveryChannelInformation which wraps recovery channel information + * @param apiCallsArrayList Available API calls + * @return AccountRecoveryType which wraps recovery options available for the user + */ + private AccountRecoveryType buildAccountRecoveryType(String recoveryType, String recoveryFlowId, + RecoveryChannelInformation recoveryChannelInformation, + ArrayList apiCallsArrayList) { + + AccountRecoveryType accountRecoveryType = new AccountRecoveryType(); + accountRecoveryType.setMode(recoveryType); + accountRecoveryType.setFlowConfirmationCode(recoveryFlowId); + accountRecoveryType.setChannelInfo(recoveryChannelInformation); + accountRecoveryType.setLinks(apiCallsArrayList); + return accountRecoveryType; + } + + /** + * Method to build recovery channel information. + * + * @param recoveryInformationDTO RecoveryInformation with recovery information + * @return RecoveryChannelInformation + */ + private RecoveryChannelInformation buildRecoveryChannelInformation( + RecoveryInformationDTO recoveryInformationDTO) { + + RecoveryChannelInfoDTO recoveryChannelInfoDTO = recoveryInformationDTO.getRecoveryChannelInfoDTO(); + List channels = RecoveryUtil + .buildRecoveryChannelInformation(recoveryChannelInfoDTO.getNotificationChannelDTOs()); + RecoveryChannelInformation recoveryChannelInformation = new RecoveryChannelInformation(); + recoveryChannelInformation.setRecoveryCode(recoveryChannelInfoDTO.getRecoveryCode()); + recoveryChannelInformation.setChannels(channels); + return recoveryChannelInformation; + } + + /** + * Build a list of account recovery options available for a successful password recovery. + * + * @param tenantDomain Tenant domain + * @param recoveryInformationDTO RecoveryInformationDTO which wraps the password recovery information + * @return List of {@link AccountRecoveryType} + */ + private List buildPasswordRecoveryInitResponse(String tenantDomain, + RecoveryInformationDTO recoveryInformationDTO) { + + ArrayList accountRecoveryTypes = new ArrayList<>(); + boolean isNotificationBasedRecoveryEnabled = recoveryInformationDTO.isNotificationBasedRecoveryEnabled(); + boolean isQuestionBasedRecoveryAllowedForUser = recoveryInformationDTO.isQuestionBasedRecoveryAllowedForUser(); + if (isNotificationBasedRecoveryEnabled) { + String recoveryFlowId = recoveryInformationDTO.getRecoveryFlowId(); + // Build next API calls list. + ArrayList apiCallsArrayList = new ArrayList<>(); + apiCallsArrayList.add(RecoveryUtil.buildApiCall(Constants.APICall.RECOVER_PASSWORD_API.getType(), + Constants.RelationStates.NEXT_REL, RecoveryUtil + .buildURIForBody(tenantDomain, Constants.APICall.RECOVER_PASSWORD_API.getApiUrl(), + Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); + RecoveryChannelInformation recoveryChannelInformation = buildRecoveryChannelInformation( + recoveryInformationDTO); + // Build recovery information for recover with notifications. + AccountRecoveryType accountRecoveryType = buildAccountRecoveryType(Constants.RECOVERY_WITH_NOTIFICATIONS, + recoveryFlowId, recoveryChannelInformation, apiCallsArrayList); + accountRecoveryTypes.add(accountRecoveryType); + } + if (isQuestionBasedRecoveryAllowedForUser) { + // Build next API calls list. + ArrayList apiCallsArrayList = new ArrayList<>(); + apiCallsArrayList.add(RecoveryUtil + .buildApiCall(Constants.APICall.RECOVER_WITH_SECURITY_QUESTIONS_API.getType(), + Constants.RelationStates.NEXT_REL, RecoveryUtil.buildURIForBody(tenantDomain, + Constants.APICall.RECOVER_WITH_SECURITY_QUESTIONS_API.getApiUrl(), + Constants.CHALLENGE_QUESTIONS_ENDPOINT_BASEPATH), + recoveryInformationDTO.getUsername())); + // Build recovery information for recover with security questions. + AccountRecoveryType accountRecoveryType = buildAccountRecoveryType( + Constants.RECOVER_WITH_CHALLENGE_QUESTIONS, null, null, apiCallsArrayList); + accountRecoveryTypes.add(accountRecoveryType); + } + return accountRecoveryTypes; + } +} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java new file mode 100644 index 00000000..2e306601 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.identity.api.user.common.Util; +import org.wso2.carbon.identity.api.user.recovery.commons.UserAccountRecoveryServiceDataHolder; +import org.wso2.carbon.identity.governance.service.notification.NotificationChannels; +import org.wso2.carbon.identity.recovery.IdentityRecoveryClientException; +import org.wso2.carbon.identity.recovery.IdentityRecoveryConstants; +import org.wso2.carbon.identity.recovery.IdentityRecoveryException; +import org.wso2.carbon.identity.recovery.dto.RecoveryChannelInfoDTO; +import org.wso2.carbon.identity.recovery.dto.RecoveryInformationDTO; +import org.wso2.carbon.identity.recovery.dto.UsernameRecoverDTO; + +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.utils.RecoveryUtil; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.APICall; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.AccountRecoveryType; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.InitRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RecoveryChannel; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RecoveryChannelInformation; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RecoveryRequest; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.UsernameRecoveryNotifyResponse; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import javax.ws.rs.core.Response; + +/** + * Call internal OSGI services to perform username recovery. + */ +public class UsernameRecoveryService { + + private static final Log log = LogFactory.getLog(UsernameRecoveryService.class); + + /** + * Initiate userName recovery from POST. + * + * @param initRequest {@link InitRequest} object which holds the information in the account recovery + * request + * @return Response + */ + public Response initiateUsernameRecovery(InitRequest initRequest) { + + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + Map userClaims = RecoveryUtil.buildUserClaimsMap(initRequest.getClaims()); + try { + // Get username recovery notification information. + RecoveryInformationDTO recoveryInformationDTO = + UserAccountRecoveryServiceDataHolder.getUsernameRecoveryManager().initiate(userClaims, tenantDomain, + RecoveryUtil.buildPropertiesMap(initRequest.getProperties())); + if (recoveryInformationDTO == null) { + // If RecoveryChannelInfoDTO is null throw not found error. + if (log.isDebugEnabled()) { + String message = "No recovery information username recovery request"; + log.debug(message); + } + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } + return Response.ok().entity(buildUsernameRecoveryInitResponse(recoveryInformationDTO, tenantDomain)) + .build(); + } catch (IdentityRecoveryClientException e) { + throw RecoveryUtil + .handleClientExceptions(UsernameRecoveryService.class.getName(), tenantDomain, + IdentityRecoveryConstants.USER_NAME_RECOVERY, Util.getCorrelation(), e); + } catch (IdentityRecoveryException e) { + throw RecoveryUtil.buildInternalServerErrorResponse(UsernameRecoveryService.class.getName(), + Constants.SERVER_ERROR, e.getErrorCode(), Util.getCorrelation(), e); + } + } + + /** + * Send the recovery notifications to the user via user preferred channel given by the channelId param. + * + * @param recoveryRequest {@link RecoveryRequest} Object which holds the recovery information in the + * username recovery request + * @return Response + */ + public Response recoverUsername(RecoveryRequest recoveryRequest) { + + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + String recoveryId = recoveryRequest.getRecoveryCode(); + String channelId = recoveryRequest.getChannelId(); + try { + UsernameRecoverDTO usernameRecoverDTO = UserAccountRecoveryServiceDataHolder.getUsernameRecoveryManager(). + notify(recoveryId, channelId, tenantDomain, + RecoveryUtil.buildPropertiesMap(recoveryRequest.getProperties())); + if (usernameRecoverDTO == null) { + if (log.isDebugEnabled()) { + String message = String.format("No recovery data object for recovery code : %s", recoveryId); + log.debug(message); + } + return Response.status(Response.Status.OK).build(); + } + return buildUsernameRecoveryResponse(usernameRecoverDTO.getNotificationChannel(), usernameRecoverDTO); + } catch (IdentityRecoveryClientException e) { + throw RecoveryUtil + .handleClientExceptions(UsernameRecoveryService.class.getName(), tenantDomain, + IdentityRecoveryConstants.USER_NAME_RECOVERY, StringUtils.EMPTY, Util.getCorrelation(), e); + } catch (IdentityRecoveryException e) { + throw RecoveryUtil.buildInternalServerErrorResponse(UsernameRecoveryService.class.getName(), + Constants.SERVER_ERROR, e.getErrorCode(), Util.getCorrelation(), e); + } + } + + /** + * Build the successful response according to the notification channel. + * + * @param notificationChannel Notification channel + * @param usernameRecoverDTO Object which holds the successful recovery information + * @return Response + */ + private Response buildUsernameRecoveryResponse(String notificationChannel, UsernameRecoverDTO usernameRecoverDTO) { + + UsernameRecoveryNotifyResponse usernameRecoveryNotifyResponse = + new UsernameRecoveryNotifyResponse(); + usernameRecoveryNotifyResponse.setCode(usernameRecoverDTO.getCode()); + usernameRecoveryNotifyResponse.setMessage(usernameRecoverDTO.getMessage()); + usernameRecoveryNotifyResponse.setNotificationChannel(usernameRecoverDTO.getNotificationChannel()); + if (NotificationChannels.EXTERNAL_CHANNEL.getChannelType().equals(notificationChannel)) { + usernameRecoveryNotifyResponse.setUsername(usernameRecoverDTO.getUsername()); + return Response.ok().entity(usernameRecoveryNotifyResponse).build(); + } else { + return Response.accepted().entity(usernameRecoveryNotifyResponse).build(); + } + } + + /** + * Build a list of account recovery options available for successful user identification and channel retrieval. + * + * @param recoveryInformationDTO User recovery information object {@link RecoveryInformationDTO} + * @param tenantDomain Tenant domain + * @return List of {@link AccountRecoveryType} + */ + private List buildUsernameRecoveryInitResponse( + RecoveryInformationDTO recoveryInformationDTO, String tenantDomain) { + + RecoveryChannelInfoDTO recoveryChannelInfoDTO = recoveryInformationDTO.getRecoveryChannelInfoDTO(); + List channels = RecoveryUtil + .buildRecoveryChannelInformation(recoveryChannelInfoDTO.getNotificationChannelDTOs()); + // Build Recovery Channel Information. + RecoveryChannelInformation recoveryChannelInformation = new RecoveryChannelInformation(); + recoveryChannelInformation.setRecoveryCode(recoveryChannelInfoDTO.getRecoveryCode()); + recoveryChannelInformation.setChannels(channels); + // Build next API calls. + ArrayList apiCallsArrayList = new ArrayList<>(); + apiCallsArrayList.add(RecoveryUtil + .buildApiCall(Constants.APICall.RECOVER_USERNAME_API.getType(), Constants.RelationStates.NEXT_REL, + RecoveryUtil.buildURIForBody(tenantDomain, Constants.APICall.RECOVER_USERNAME_API.getApiUrl(), + Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); + // Build recovery type information. + AccountRecoveryType accountRecoveryType = new AccountRecoveryType(); + accountRecoveryType.setMode(Constants.RECOVERY_WITH_NOTIFICATIONS); + accountRecoveryType.setChannelInfo(recoveryChannelInformation); + accountRecoveryType.setLinks(apiCallsArrayList); + + ArrayList recoveryTypeDTOS = new ArrayList<>(); + recoveryTypeDTOS.add(accountRecoveryType); + return recoveryTypeDTOS; + } +} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/BadRequestException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/BadRequestException.java new file mode 100644 index 00000000..2dfa4002 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/BadRequestException.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions; + +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; + +/** + * BadRequestException class. + */ +public class BadRequestException extends WebApplicationException { + + /** + * Exception message. + */ + private String message; + + /** + * Constructs a new exception from the ErrorDTO{@link ErrorResponse} object. + * + * @param errorResponse ErrorResponse{@link ErrorResponse} object holding the error code and the message + */ + public BadRequestException(ErrorResponse errorResponse) { + super(Response.status(Response.Status.BAD_REQUEST).entity(errorResponse) + .header(Constants.HEADER_CONTENT_TYPE, Constants.DEFAULT_RESPONSE_CONTENT_TYPE).build()); + message = errorResponse.getDescription(); + } + + /** + * Constructs a new exception instance. + */ + public BadRequestException() { + super(Response.Status.BAD_REQUEST); + } + + /** + * Get exception message. + * + * @return Exception message + */ + @Override + public String getMessage() { + return message; + } +} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ConflictException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ConflictException.java new file mode 100644 index 00000000..beb0bf34 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ConflictException.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions; + +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; + +/** + * ConflictException class. + */ +public class ConflictException extends WebApplicationException { + + /** + * Exception message. + */ + private String message; + + /** + * Constructs a new exception from the ErrorDTO{@link ErrorResponse} object. + * + * @param errorResponse ErrorResponse{@link ErrorResponse} object holding the error code and the message + */ + public ConflictException(ErrorResponse errorResponse) { + + super(Response.status(Response.Status.CONFLICT).entity(errorResponse) + .header(Constants.HEADER_CONTENT_TYPE, Constants.DEFAULT_RESPONSE_CONTENT_TYPE).build()); + message = errorResponse.getDescription(); + } + + /** + * Constructs a new exception instance. + */ + public ConflictException() { + + super(Response.Status.CONFLICT); + } + + /** + * Get exception message. + * + * @return Exception message + */ + @Override + public String getMessage() { + + return message; + } +} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ForbiddenException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ForbiddenException.java new file mode 100644 index 00000000..86661e8e --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ForbiddenException.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions; + +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; + +/** + * ForbiddenException class. + */ +public class ForbiddenException extends WebApplicationException { + + /** + * Exception message. + */ + private String message; + + /** + * Constructs a new exception from the ErrorDTO{@link ErrorResponse} object. + * + * @param errorResponse ErrorResponse{@link ErrorResponse} object holding the error code and the message + */ + public ForbiddenException(ErrorResponse errorResponse) { + + super(Response.status(Response.Status.FORBIDDEN).entity(errorResponse) + .header(Constants.HEADER_CONTENT_TYPE, Constants.DEFAULT_RESPONSE_CONTENT_TYPE).build()); + message = errorResponse.getDescription(); + } + + /** + * Constructs a new exception instance. + */ + public ForbiddenException() { + super(Response.Status.FORBIDDEN); + } + + /** + * Get exception message. + * + * @return Exception message + */ + @Override + public String getMessage() { + return message; + } +} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/InternalServerErrorException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/InternalServerErrorException.java new file mode 100644 index 00000000..123a80f6 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/InternalServerErrorException.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions; + +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; + +/** + * InternalServerErrorException class. + */ +public class InternalServerErrorException extends WebApplicationException { + + /** + * Exception message. + */ + private String message; + + public InternalServerErrorException(Throwable e) { + super(e, Response.Status.INTERNAL_SERVER_ERROR); + } + + /** + * Constructs a new exception instance. + */ + public InternalServerErrorException() { + super(Response.Status.INTERNAL_SERVER_ERROR); + } + + public InternalServerErrorException(String message, Throwable e) { + super(message, e, Response.Status.INTERNAL_SERVER_ERROR); + } + + public InternalServerErrorException(String message) { + super(message, Response.Status.INTERNAL_SERVER_ERROR); + } + + /** + * Constructs a new exception from the ErrorDTO{@link ErrorResponse} object. + * + * @param errorResponse ErrorResponse{@link ErrorResponse} object holding the error code and the message + */ + public InternalServerErrorException(ErrorResponse errorResponse) { + + super(Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errorResponse) + .header(Constants.HEADER_CONTENT_TYPE, Constants.DEFAULT_RESPONSE_CONTENT_TYPE).build()); + } +} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotAcceptableException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotAcceptableException.java new file mode 100644 index 00000000..ea2a0eec --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotAcceptableException.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions; + +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; + +/** + * NotAcceptableException class. + */ +public class NotAcceptableException extends WebApplicationException { + + /** + * Exception message. + */ + private String message; + + /** + * Constructs a new exception from the ErrorDTO{@link ErrorResponse} object. + * + * @param errorResponse ErrorResponse{@link ErrorResponse} object holding the error code and the message + */ + public NotAcceptableException(ErrorResponse errorResponse) { + + super(Response.status(Response.Status.NOT_ACCEPTABLE).entity(errorResponse) + .header(Constants.HEADER_CONTENT_TYPE, Constants.DEFAULT_RESPONSE_CONTENT_TYPE).build()); + message = errorResponse.getDescription(); + } + + /** + * Constructs a new exception instance. + */ + public NotAcceptableException() { + super(Response.Status.NOT_ACCEPTABLE); + } + + /** + * Get exception message. + * + * @return Exception message + */ + @Override + public String getMessage() { + return message; + } +} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotFoundException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotFoundException.java new file mode 100644 index 00000000..1202b0a6 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotFoundException.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions; + +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; + +/** + * NotFoundException class. + */ +public class NotFoundException extends WebApplicationException { + + /** + * Exception message. + */ + private String message; + + /** + * Constructs a new exception from the ErrorDTO{@link ErrorResponse} object. + * + * @param errorResponse ErrorResponse{@link ErrorResponse} object holding the error code and the message + */ + public NotFoundException(ErrorResponse errorResponse) { + + super(Response.status(Response.Status.NOT_FOUND).entity(errorResponse) + .header(Constants.HEADER_CONTENT_TYPE, Constants.DEFAULT_RESPONSE_CONTENT_TYPE).build()); + message = errorResponse.getDescription(); + } + + /** + * Constructs a new exception instance. + */ + public NotFoundException() { + super(Response.Status.NOT_ACCEPTABLE); + } + + /** + * Get exception message. + * + * @return Exception message + */ + @Override + public String getMessage() { + return message; + } +} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/PreconditionFailedException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/PreconditionFailedException.java new file mode 100644 index 00000000..883dddb1 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/PreconditionFailedException.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions; + +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RetryErrorResponse; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; + +/** + * PreconditionFailedException class. + */ +public class PreconditionFailedException extends WebApplicationException { + + /** + * Exception message. + */ + private String message; + + /** + * Constructs a new exception from the ErrorDTO{@link ErrorResponse} object. + * + * @param errorResponse ErrorResponse{@link ErrorResponse} object holding the error code and the message + */ + public PreconditionFailedException(ErrorResponse errorResponse) { + + super(Response.status(Response.Status.PRECONDITION_FAILED).entity(errorResponse) + .header(Constants.HEADER_CONTENT_TYPE, Constants.DEFAULT_RESPONSE_CONTENT_TYPE).build()); + message = errorResponse.getDescription(); + } + + /** + * Constructs a new exception from the RetryErrorDTO{@link RetryErrorResponse} object. + * + * @param retryErrorResponse RetryErrorResponse{@link RetryErrorResponse} object holding the error code and the + * message + */ + public PreconditionFailedException(RetryErrorResponse retryErrorResponse) { + + super(Response.status(Response.Status.PRECONDITION_FAILED).entity(retryErrorResponse) + .header(Constants.HEADER_CONTENT_TYPE, Constants.DEFAULT_RESPONSE_CONTENT_TYPE).build()); + message = retryErrorResponse.getDescription(); + } + + /** + * Constructs a new exception instance. + */ + public PreconditionFailedException() { + + super(Response.Status.PRECONDITION_FAILED); + } + + /** + * Get exception message. + * + * @return Exception message + */ + @Override + public String getMessage() { + + return message; + } +} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java new file mode 100644 index 00000000..8d25e223 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java @@ -0,0 +1,576 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.utils; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.wso2.carbon.identity.api.user.common.error.APIError; +import org.wso2.carbon.identity.core.ServiceURLBuilder; +import org.wso2.carbon.identity.core.URLBuilderException; +import org.wso2.carbon.identity.core.util.IdentityTenantUtil; +import org.wso2.carbon.identity.core.util.IdentityUtil; +import org.wso2.carbon.identity.recovery.IdentityRecoveryClientException; +import org.wso2.carbon.identity.recovery.IdentityRecoveryConstants; +import org.wso2.carbon.identity.recovery.dto.NotificationChannelDTO; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions.ConflictException; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions.ForbiddenException; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions.InternalServerErrorException; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions.NotAcceptableException; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions.NotFoundException; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions.PreconditionFailedException; + +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.APICall; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.Property; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RecoveryChannel; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RetryErrorResponse; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.UserClaim; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; + +import static org.wso2.carbon.identity.api.user.common.Constants.TENANT_CONTEXT_PATH_COMPONENT; +import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.Error.UNEXPECTED_SERVER_ERROR; + +/** + * Contains the recovery endpoint utils. + */ +public class RecoveryUtil { + + private static final Log log = LogFactory.getLog(RecoveryUtil.class); + private static final String LOG_MESSAGE_PREFIX = "INITIATOR"; + private static final String FORBIDDEN_ERROR_CATEGORY = "FORBIDDEN_ERROR_CATEGORY"; + private static final String CONFLICT_REQUEST_ERROR_CATEGORY = "CONFLICT_REQUEST_ERROR_CATEGORY"; + private static final String REQUEST_NOT_FOUND_ERROR_CATEGORY = "REQUEST_NOT_FOUND_ERROR_CATEGORY"; + private static final String REQUEST_NOT_ACCEPTABLE_ERROR_CATEGORY = "REQUEST_NOT_ACCEPTABLE_ERROR_CATEGORY"; + private static final String RETRY_ERROR_CATEGORY = "RETRY_ERROR_CATEGORY"; + + // Map with the error codes categorized in to different error groups. + private static final HashMap clientErrorMap = generateClientErrorMap(); + + /** + * Converts a list of UserClaim in to a UserClaim array. + * + * @param userClaimsList UserClaims List + * @return Map of user claims + */ + public static HashMap buildUserClaimsMap(List userClaimsList) { + + HashMap userClaims = new HashMap<>(); + for (UserClaim userClaimModel : userClaimsList) { + userClaims.put(userClaimModel.getUri(), userClaimModel.getValue()); + } + return userClaims; + } + + /** + * Convert the list of Properties in to an array. + * + * @param propertyList List of {@link Property} objects + * @return Map of properties + */ + public static HashMap buildPropertiesMap(List propertyList) { + + HashMap properties = new HashMap<>(); + if (propertyList == null) { + return properties; + } + for (Property propertyDTO : propertyList) { + properties.put(propertyDTO.getKey(), propertyDTO.getValue()); + } + return properties; + } + + /** + * Build the channel response object list. + * + * @param channels Available notification channels list as objects of {@link NotificationChannelDTO} + * @return List of RecoveryChannels {@link RecoveryChannel} + */ + public static List buildRecoveryChannelInformation(NotificationChannelDTO[] channels) { + + List recoveryChannelDTOS = new ArrayList<>(); + if (channels != null) { + // Create a response object and add the details to each object. + for (NotificationChannelDTO channel : channels) { + RecoveryChannel recoveryChannel = new RecoveryChannel(); + recoveryChannel.setId(Integer.toString(channel.getId())); + recoveryChannel.setType(channel.getType()); + recoveryChannel.setValue(channel.getValue()); + if (StringUtils.isNotEmpty(channel.getValue())) { + recoveryChannel.setPreferred(channel.isPreferred()); + } + recoveryChannelDTOS.add(recoveryChannel); + } + } + return recoveryChannelDTOS; + } + + /** + * Handle client errors with specific http codes. + * + * @param className Class name + * @param scenario Recovery scenario + * @param exception IdentityRecoveryClientException + * @return WebApplicationException (NOTE: Returns null when the client error is for no user available or for + * multiple users available + */ + public static WebApplicationException handleClientExceptions(String className, String tenantDomain, + String scenario, String correlationId, + IdentityRecoveryClientException exception) { + + return handleClientExceptions(className, tenantDomain, scenario, StringUtils.EMPTY, correlationId, exception); + } + + /** + * Handle client errors with specific http codes. + * + * @param className Class name + * @param scenario Recovery scenario + * @param code Recovery code + * @param exception IdentityRecoveryClientException + * @return WebApplicationException (NOTE: Returns null when the client error is for no user available or for + * multiple users available + */ + public static WebApplicationException handleClientExceptions(String className, String tenantDomain, String scenario, + String code, String correlationId, + IdentityRecoveryClientException exception) { + + if (StringUtils.isEmpty(exception.getErrorCode())) { + return buildConflictRequestResponseObject(className, exception.getMessage(), exception.getErrorCode(), + correlationId); + } + String errorCode = prependOperationScenarioToErrorCode(exception.getErrorCode(), scenario); + + if (clientErrorMap.containsKey(errorCode)) { + String errorCategory = clientErrorMap.get(errorCode); + + // Throw errors according to exception category. + switch (errorCategory) { + case FORBIDDEN_ERROR_CATEGORY: + return buildForbiddenRequestResponseObject(className, exception.getMessage(), errorCode, + correlationId); + case CONFLICT_REQUEST_ERROR_CATEGORY: + if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_MULTIPLE_MATCHING_USERS.getCode() + .equals(errorCode)) { + // If user notify is not enabled, throw a accepted response. + if (!Boolean.parseBoolean(IdentityUtil + .getProperty(IdentityRecoveryConstants.ConnectorConfig.NOTIFY_USER_EXISTENCE))) { + return new WebApplicationException(Response.accepted().build()); + } + } + return buildConflictRequestResponseObject(className, exception.getMessage(), + exception.getErrorCode(), correlationId); + case REQUEST_NOT_FOUND_ERROR_CATEGORY: + if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_USER_FOUND.getCode().equals(errorCode)) { + // If user notify is not enabled, throw a accepted response. + if (!Boolean.parseBoolean(IdentityUtil + .getProperty(IdentityRecoveryConstants.ConnectorConfig.NOTIFY_USER_EXISTENCE))) { + return new WebApplicationException(Response.accepted().build()); + } + } + return buildRequestNotFoundResponseObject(className, exception.getMessage(), errorCode, + correlationId); + case REQUEST_NOT_ACCEPTABLE_ERROR_CATEGORY: + return buildRequestNotAcceptableResponseObject(className, exception.getMessage(), errorCode, + correlationId); + case RETRY_ERROR_CATEGORY: + return buildRetryPasswordResetObject(className, tenantDomain, exception.getMessage(), errorCode, + code, correlationId); + default: + return buildConflictRequestResponseObject(className, exception.getMessage(), errorCode, + correlationId); + } + } else { + return buildConflictRequestResponseObject(className, exception.getMessage(), errorCode, correlationId); + } + } + + /** + * Logs the error, builds a internalServerErrorException with specified details and throws it. + * + * @param className Class name + * @param message Error message + * @param code Error code + * @param correlationId Correlation Id + * @param throwable Error + * @return WebApplicationException + */ + public static WebApplicationException buildInternalServerErrorResponse(String className, String message, + String code, String correlationId, + Throwable throwable) { + + if (StringUtils.isNotBlank(className)) { + message = String.format("%s : %s - %s", LOG_MESSAGE_PREFIX, className, message); + } + if (throwable == null) { + log.error(message); + } else { + log.error(message, throwable); + } + return buildInternalServerError(code, correlationId); + } + + /** + * Build API call information. + * + * @param type Type of the API call + * @param rel API relation + * @param apiUrl Url of the API + * @param data Additional data + * @return APICall {@link APICall} which encapsulates the API name and the url + */ + public static APICall buildApiCall(String type, String rel, String apiUrl, String data) { + + if (StringUtils.isNotEmpty(data)) { + apiUrl = String.format(apiUrl, data); + } + APICall apiCall = new APICall(); + apiCall.setType(type); + apiCall.setRel(rel); + apiCall.setHref(apiUrl); + return apiCall; + } + + /** + * @deprecated This was deprecated because the requirement is to get the absolute and relative URIs by using the + * {@link ServiceURLBuilder} methods. + * @since 1.1.6 + * + * Please use {@link #buildURIForBody(String, String, String)} method to build URIs for body. + * + * Build the relative url. + * @param tenantDomain Tenant Domain + * @param endpoint API endpoint + * @return Url + */ + public static String buildUri(String tenantDomain, String endpoint, String baseUrl) { + + String tenantQualifiedRelativePath = + String.format(TENANT_CONTEXT_PATH_COMPONENT, tenantDomain) + baseUrl; + return tenantQualifiedRelativePath + endpoint; + } + + /** + * Builds URI prepending the user API context with the proxy context path to the endpoint. + * Ex: /t//api/users/ + * + * @param endpoint Relative endpoint path. + * @return Relative URI. + */ + public static String buildURIForBody(String tenantDomain, String endpoint, String baseUrl) { + + String url; + String context = getContext(tenantDomain, endpoint, baseUrl); + + try { + url = ServiceURLBuilder.create().addPath(context).build().getRelativePublicURL(); + } catch (URLBuilderException e) { + String errorDescription = "Server encountered an error while building URL for response body."; + org.wso2.carbon.identity.api.user.common.error.ErrorResponse errorResponse = + new org.wso2.carbon.identity.api.user.common.error.ErrorResponse.Builder() + .withCode(UNEXPECTED_SERVER_ERROR.getCode()) + .withMessage("Error while building response.") + .withDescription(errorDescription) + .build(log, e, errorDescription); + + Response.Status status = Response.Status.INTERNAL_SERVER_ERROR; + throw new APIError(status, errorResponse); + } + return url; + } + + /** + * Builds the API context on whether the tenant qualified url is enabled or not. In tenant qualified mode the + * ServiceURLBuilder appends the tenant domain to the URI as a path param automatically. But + * in non tenant qualified mode we need to append the tenant domain to the path manually. + * + * @param endpoint Relative endpoint path. + * @return Context of the API. + */ + private static String getContext(String tenantDomain, String endpoint, String baseUrl) { + + String context; + if (IdentityTenantUtil.isTenantQualifiedUrlsEnabled()) { + context = baseUrl + endpoint; + } else { + context = String.format(TENANT_CONTEXT_PATH_COMPONENT, tenantDomain) + baseUrl + endpoint; + } + return context; + } + + /** + * Returns a new InternalServerErrorException. + * + * @param code Code + * @param correlationId Correlation Id + * @return A new InternalServerErrorException with default details as a response + */ + private static InternalServerErrorException buildInternalServerError(String code, String correlationId) { + + ErrorResponse errorResponse = buildErrorResponse(Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, code, + Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, correlationId); + return new InternalServerErrorException(errorResponse); + } + + /** + * Returns a generic error response. + * + * @param code Error code + * @param message Specifies the error message + * @param description Error description + * @param correlationId CorrelationID + * @return A generic error with the specified details + */ + private static ErrorResponse buildErrorResponse(String message, String code, String description, + String correlationId) { + + ErrorResponse errorResponse = new ErrorResponse(); + errorResponse.setCode(code); + errorResponse.setMessage(message); + errorResponse.setDescription(description); + errorResponse.setTraceId(correlationId); + return errorResponse; + } + + /** + * Returns a new PreconditionFailedException. + * + * @param className Class name + * @param tenantDomain Tenant domain + * @param description Description of the exception + * @param code Error code + * @param resetCode Reset code given to the user by confirmation API + * @param correlationId Correlation Id + * @return A new PreconditionFailedException with the specified details as a response + */ + private static PreconditionFailedException buildRetryPasswordResetObject(String className, String tenantDomain, + String description, String code, + String resetCode, String correlationId) { + + // Build next API calls. + ArrayList apiCallsArrayList = new ArrayList<>(); + apiCallsArrayList.add(RecoveryUtil + .buildApiCall(Constants.APICall.RESET_PASSWORD_API.getType(), Constants.RelationStates.NEXT_REL, + buildURIForBody(tenantDomain, Constants.APICall.RESET_PASSWORD_API.getApiUrl(), + Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); + RetryErrorResponse retryErrorResponse = buildRetryErrorResponse( + Constants.STATUS_PRECONDITION_FAILED_MESSAGE_DEFAULT, code, description, resetCode, correlationId, + apiCallsArrayList); + if (StringUtils.isNotBlank(className)) { + description = String.format("%s : %s - %s", LOG_MESSAGE_PREFIX, className, description); + } + log.error(description); + return new PreconditionFailedException(retryErrorResponse); + } + + /** + * Build the RetryErrorResponse for not valid password scenario. + * + * @param message Error message + * @param description Error description + * @param code Error code + * @param resetCode Password reset code + * @param correlationId Trace Id + * @param apiCallsArrayList Available APIs + * @return RetryErrorResponse + */ + private static RetryErrorResponse buildRetryErrorResponse(String message, String description, String code, + String resetCode, String correlationId, + ArrayList apiCallsArrayList) { + + RetryErrorResponse retryErrorResponse = new RetryErrorResponse(); + retryErrorResponse.setCode(code); + retryErrorResponse.setMessage(message); + retryErrorResponse.setDescription(description); + retryErrorResponse.setResetCode(resetCode); + retryErrorResponse.setTraceId(correlationId); + retryErrorResponse.setLinks(apiCallsArrayList); + return retryErrorResponse; + } + + /** + * Returns a new NotAcceptableException. + * + * @param className Class name + * @param description Description of the exception + * @param code Error code + * @param correlationId Correlation Id + * @return A new NotAcceptableException with the specified details as a response + */ + private static NotAcceptableException buildRequestNotAcceptableResponseObject(String className, String description, + String code, String correlationId) { + + ErrorResponse errorResponse = buildErrorResponse(Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, code, + description, correlationId); + if (StringUtils.isNotBlank(className)) { + description = String.format("%s : %s - %s", LOG_MESSAGE_PREFIX, className, description); + } + log.error(description); + return new NotAcceptableException(errorResponse); + } + + /** + * Returns a new NotAcceptableException. + * + * @param className Class name + * @param description Description of the exception + * @param code Error code + * @param correlationId Correlation Id + * @return A new NotAcceptableException with the specified details as a response + */ + private static NotFoundException buildRequestNotFoundResponseObject(String className, String description, + String code, String correlationId) { + + ErrorResponse errorResponse = buildErrorResponse(Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, code, + description, correlationId); + if (StringUtils.isNotBlank(className)) { + description = String.format("%s : %s - %s", LOG_MESSAGE_PREFIX, className, description); + } + log.error(description); + return new NotFoundException(errorResponse); + } + + /** + * Returns a new ConflictException. + * + * @param className Classname + * @param description Description of the exception + * @param code Error code + * @param correlationId CorrelationId + * @return A new ConflictException with the specified details as a response + */ + private static ConflictException buildConflictRequestResponseObject(String className, String description, + String code, String correlationId) { + + ErrorResponse errorResponse = buildErrorResponse(Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, code, + description, correlationId); + if (StringUtils.isNotBlank(className)) { + description = String.format("CorrelationIc: %s : %s : %s - %s", correlationId, LOG_MESSAGE_PREFIX, + className, description); + } + log.error(description); + return new ConflictException(errorResponse); + } + + /** + * Returns a new ForbiddenException. + * + * @param className Class name + * @param description Description of the exception + * @param code Error code + * @param correlationId CorrelationId + * @return A new ForbiddenException with the specified details as a response + */ + private static ForbiddenException buildForbiddenRequestResponseObject(String className, String description, + String code, String correlationId) { + + ErrorResponse errorResponse = buildErrorResponse(Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, code, + description, correlationId); + if (StringUtils.isNotBlank(className)) { + description = String.format("%s : %s - %s", LOG_MESSAGE_PREFIX, className, description); + } + log.error(description); + return new ForbiddenException(errorResponse); + } + + /** + * Prepend the operation scenario to the existing exception error code. + * (Eg: USR-20045) + * + * @param exceptionErrorCode Existing error code. + * @param scenario Operation scenario + * @return New error code with the scenario prepended + */ + private static String prependOperationScenarioToErrorCode(String exceptionErrorCode, String scenario) { + + if (StringUtils.isNotEmpty(exceptionErrorCode)) { + if (exceptionErrorCode.contains(IdentityRecoveryConstants.EXCEPTION_SCENARIO_SEPARATOR)) { + return exceptionErrorCode; + } + if (StringUtils.isNotEmpty(scenario)) { + exceptionErrorCode = + scenario + IdentityRecoveryConstants.EXCEPTION_SCENARIO_SEPARATOR + exceptionErrorCode; + } + } + return exceptionErrorCode; + } + + /** + * Generate the map which categorizes the exceptions for different http error groups. + * + * @return Grouped client error map + */ + private static HashMap generateClientErrorMap() { + + HashMap clientErrorMap = new HashMap<>(); + + // Errors for not enabling account recovery, user account locked, user account disabled. + clientErrorMap + .put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_RECOVERY_WITH_NOTIFICATIONS_NOT_ENABLED + .getCode(), FORBIDDEN_ERROR_CATEGORY); + clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_USERNAME_RECOVERY_NOT_ENABLED.getCode(), + FORBIDDEN_ERROR_CATEGORY); + clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_DISABLED_ACCOUNT.getCode(), + FORBIDDEN_ERROR_CATEGORY); + clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_LOCKED_ACCOUNT.getCode(), + FORBIDDEN_ERROR_CATEGORY); + clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_RECOVERY_NOT_ENABLED.getCode(), + FORBIDDEN_ERROR_CATEGORY); + + // Tenant miss match error. + clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_USER_TENANT_DOMAIN_MISS_MATCH_WITH_CONTEXT + .getCode(), CONFLICT_REQUEST_ERROR_CATEGORY); + + // Multiples users found error. + clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_MULTIPLE_MATCHING_USERS.getCode(), + CONFLICT_REQUEST_ERROR_CATEGORY); + + // No user found error. + clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_USER_FOUND.getCode(), + REQUEST_NOT_FOUND_ERROR_CATEGORY); + + // No recovery code found and no verified channels found errors. + clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_ACCOUNT_RECOVERY_DATA.getCode(), + REQUEST_NOT_FOUND_ERROR_CATEGORY); + clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_VERIFIED_CHANNELS_FOR_USER.getCode(), + REQUEST_NOT_FOUND_ERROR_CATEGORY); + + // Invalid recovery codes errors. + clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode(), + REQUEST_NOT_ACCEPTABLE_ERROR_CATEGORY); + clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RESEND_CODE.getCode(), + REQUEST_NOT_ACCEPTABLE_ERROR_CATEGORY); + clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_EXPIRED_RECOVERY_CODE.getCode(), + REQUEST_NOT_ACCEPTABLE_ERROR_CATEGORY); + + // Password reset password history violation errors and password policy violation errors. + clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_HISTORY_VIOLATION.getCode(), + RETRY_ERROR_CATEGORY); + clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_POLICY_VIOLATION.getCode(), + RETRY_ERROR_CATEGORY); + return clientErrorMap; + } +} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/resources/META-INF/cxf/user-recovery-v2-cxf.xml b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/resources/META-INF/cxf/user-recovery-v2-cxf.xml new file mode 100644 index 00000000..aed37b9e --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/resources/META-INF/cxf/user-recovery-v2-cxf.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/resources/user.account.recovery.yaml b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/resources/user.account.recovery.yaml new file mode 100644 index 00000000..89c0684a --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/resources/user.account.recovery.yaml @@ -0,0 +1,1256 @@ +openapi: 3.0.0 +info: + version: "v1-oas3" + title: WSO2 Identity Server User Account Recovery Rest API + description: > + This is the RESTful API for username and password recovery initated by the + user. + contact: + name: WSO2 Identity Server + url: 'https://wso2.com/identity-and-access-management' + email: architecture@wso2.org + license: + name: Apache 2.0 + url: 'http://www.apache.org/licenses/LICENSE-2.0.html' +paths: + /recovery/username/init: + post: + tags: + - Username Recovery + summary: Initiate Username Recovery + operationId: initiateUsernameRecovery + description: > + - This API is used to initiate username recovery by user. The API will + return available recovery information for username recovery with + notifications. + + - Use the returned __recoveryCode__ and the __channelId__ with + __username recover api__ to confirm the the username recovery and to + recieve recovery notifications via the channel specified by the user. + responses: + '200': + description: >- + User is successfully identified for the given claims and returning + available notification channels for the user. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/AccountRecoveryType' + examples: + response: + value: + - mode: recoverWithNotifications + channelInfo: + recoveryCode: 1234-55678-5668-2345 + channels: + - id: 1 + type: EMAIL + value: wso2***********.com + preferred: true + - id: 2 + type: SMS + value: '**********123' + preferred: false + links: + - rel: next + href: /api/users/v1/recovery/username/recover + type: POST + '400': + description: Bad Request. The request cannot be processed by the server. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: UAR-10001 + message: bad_request + description: bad request + traceId: 23456fghj678vb78 + '403': + description: Username recovery is not enabled. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: UNR-10003 + message: Forbidden + description: Username recovery is not enabled + traceId: 23456fghj678vb78 + '404': + description: >- + No user found for the given set of claims or no recovery channels + are availabe for the user. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: UAR-10002 + message: Not found + description: No user found + traceId: 23456fghj678vb78 + '409': + description: Mutiple users found for the given claims. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: UAR-10008 + message: Conflict + description: Multiple users found for given claims + traceId: 23456fghj678vb78 + '500': + description: Server Error. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: UNR-15001 + message: Internal Error + description: Internal Error + traceId: 23456fghj678vb78 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/InitRequest' + description: >- + Request to initate username recovery process. The request should + contain the claims to identify the user. User claims are `REQUIRED`. + required: true + /recovery/username/recover: + post: + tags: + - Username Recovery + summary: Get Recovery Information + operationId: recoverUsername + description: > + - This API is used to confirm username recovery and send username + recovery information to the user who matches the recovery code via the + channel specified by the channel Id. + - __NOTE__: If the notification channel is __EXTERNAL__, the API will return the username of the user. + responses: + '200': + description: >- + Username is successfully recovered and the __notification channel__ + is `EXTERNAL`. + content: + application/json: + schema: + $ref: '#/components/schemas/UsernameRecoveryNotifyResponse' + examples: + response: + value: + code: UNR-02002 + message: Username recovery information sent externally + notificationChannel: EXTERNAL + username: PRIMARY/sominda1@carbon.super + '202': + description: Username is successfully recovered. + content: + application/json: + schema: + $ref: '#/components/schemas/UsernameRecoveryNotifyResponse' + examples: + response: + value: + code: UNR-02001 + message: >- + Username recovery information sent via user preferred + notification channel + notificationChannel: EMAIL + '400': + description: Bad Request. Request cannot be processed by the server. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: UNR-10001 + message: bad_request + description: bad request + traceId: 23456fghj678vb78 + '404': + description: Recovery code is not found. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: UNR-10001 + message: not_found + description: recovery code not found + traceId: 23456fghj678vb78 + '406': + description: | + - Recovery code given in the request is not valid or expired. + - Channel id is not valid + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: UNR-10001 + message: not acceptable + description: 'invalid error code : 1234-2345-12345-123456' + traceId: 23456fghj678vb78 + '500': + description: Server Error. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: UNR-15001 + message: Internal Error + description: Internal Error + traceId: 23456fghj678vb78 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RecoveryRequest' + description: > + - Request to confirm username recovery and receive recovery + notifications. + + - `recoveryCode` and `channelId` are `REQUIRED`. + + - __NOTE__ `channelId` should always be __larger than 0__. + required: true + /recovery/password/init: + post: + tags: + - Password Recovery + summary: | + Initiate password recovery + operationId: initiatePasswordRecovery + description: > + - This API is used to initiate password recovery by user. The API will + return recovery information for password recovery with challenge + questions and password recovery with notifications. + + - `mode` __recoverWithNotifications__ contains recovery flow confirmation code, available communication channels and a recovery code for password recovery with notifications. + The next API call will be returned in the response. + + - If `password recovery with notifications` is not enabled, the response + will not contain __recoverWithNotifications__ mode. + + - __recoverWithChallengeQuestions__ contains the next API call to begin + the recovery process via challenge questions. + + - If `password recovery with challenge questions` is not enabled, the + response will not contain __recoverWithChallengeQuestions__ mode. + responses: + '200': + description: >- + User is successfully identified for the given claims and returning + available notification channels for the user. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/AccountRecoveryType' + examples: + response: + value: + - mode: recoverWithNotifications + flowConfirmationCode: 1234-1234-1234-1234 + channelInfo: + recoveryCode: 1234-55678-5668-2345 + channels: + - id: 1 + type: EMAIL + value: wso2***********.com + preferred: false + - id: 2 + type: SMS + value: '**********123' + preferred: true + links: + - rel: next + href: /api/users/v1/recovery/password/recovery + type: POST + - mode: recoverWithChallengeQuestions + links: + - rel: next + href: >- + /t/carbon.super/api/identity/recovery/v0.9/security-question?username=sominda + type: GET + '400': + description: Bad Request. The request cannot be processed by the server. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: UAR-10001 + message: bad_request + description: bad request + traceId: 23456fghj678vb78 + '404': + description: >- + No user found for the given set of claims or no recovery channels + are availabe for the user. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: UAR-10002 + message: Not found + description: No user found + traceId: 23456fghj678vb78 + '409': + description: Mutiple users found for the given claims. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: UAR-10008 + message: Conflict + description: Multiple users found for given claims + traceId: 23456fghj678vb78 + '500': + description: Server Error. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: UAR-15001 + message: Internal Error + description: Internal Error + traceId: 23456fghj678vb78 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/InitRequest' + description: >- + Request to initate password recovery process. The request should + contain the claims to identify the user. User claims are `REQUIRED`. + required: true + /recovery/password/recover: + post: + tags: + - Password Recovery + summary: | + Get Recovery Information + operationId: recoverPassword + description: > + - This API is used to send recovery information to the user who matches + the recovery code via the channel specified by the channel Id. The API will return the recovery flow confirmation code. + + - NOTE: If the notification channel is EXTERNAL, the API will return a + confirmationCode. + + - Use the returned confimation code with __password recovery confirm + API__ to verify the password recovery process. + + - The API will return the next API call. + responses: + '200': + description: > + - Password recovery initiated via `EXTERNAL` channel. API will + return a `confirmationCode` to confirm password recovery. + + - Use the confirmation code with __password recovery confirm API__ + to confirm the password recovery. + content: + application/json: + schema: + $ref: '#/components/schemas/PasswordRecoveryExternalNotifyResponse' + examples: + response: + value: + code: PWR-02002 + message: Password recovery information sent externally + flowConfirmationCode: 1234-1234-1234-1234 + notificationChannel: EXTERNAL + confirmationCode: 12345-45678-6789098-8765 + resendCode: 12345-45678-6789098-8765 + links: + - rel: next + href: api/users/v1/recovery/password/confirm + type: POST + - rel: resend + href: api/users/v1/recovery/password/resend + type: POST + '202': + description: > + - Password recovery initiated via internal channels. API will send a + `confirmationCode`/`otp` to the channel specified by the user. + + - Use the confirmation code/OTP with __password recovery confirm API__ + to confirm the password recovery. + content: + application/json: + schema: + $ref: '#/components/schemas/PasswordRecoveryInternalNotifyResponse' + examples: + response: + value: + code: PWR-02002 + message: Password recovery information sent externally + flowConfirmationCode: 1234-1234-1234-1234 + notificationChannel: EMAIL + resendCode: 12345-45678-6789098-8765 + links: + - rel: next + href: api/users/v1/recovery/password/confirm + type: POST + - rel: resend + href: api/users/v1/recovery/password/resend + type: POST + '400': + description: Bad Request. Request cannot be processed by the server. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: PWR-10001 + message: bad_request + description: bad request + traceId: 23456fghj678vb78 + '403': + description: Password recovery is not enabled. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: PWR-10004 + message: Forbidden + description: Password recovery is not enabled + traceId: 23456fghj678vb78 + '404': + description: Recovery code is not found. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: PWR-10001 + message: not_found + description: recovery code not found + traceId: 23456fghj678vb78 + '406': + description: | + - Recovery code given in the request is not valid or expired. + - Channel id is not valid + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: PWR-10003 + message: not acceptable + description: 'invalid error code : 1234-2345-12345-123456' + traceId: 23456fghj678vb78 + '500': + description: Server Error. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: PWR-15001 + message: Internal Error + description: Internal Error + traceId: 23456fghj678vb78 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RecoveryRequest' + description: | + - Request to receive recovery notifications. + - `recoveryCode` and `channelId` are `REQUIRED`. + - __NOTE__ `channelId` should always be __larger than 0__. + required: true + /recovery/password/resend: + post: + tags: + - Password Recovery + summary: | + Resend password recovery confirmation details + operationId: resendConfirmation + description: > + - This API is used to resend a confirmation code/OTP to the user via a user + preferred channel defined at password recovery. + + - NOTE: The API cannot be used when the notification channel is + external. + + - The API will return the next API calls. + responses: + '200': + description: > + - API will return a new `confirmationCode`. + + - Use the confirmation code with __password recovery confirm API__ + to confirm the password recovery. + content: + application/json: + schema: + $ref: '#/components/schemas/ResendConfirmationCodeExternalResponse' + examples: + response: + value: + code: PWR-02002 + message: successful_request + flowConfirmationCode: 1234-1234-1234-1234 + notificationChannel: EXTERNAL + confirmationCode: 1234-12345-234-123456 + resendCode: 1234-12345-234-123456 + links: + - rel: next + href: api/users/v1/recovery/password/recover + type: POST + - rel: resend + href: api/users/v1/recovery/password/resend + type: POST + '202': + description: > + - API will send a `confirmationCode`/`otp` to the channel specified by the + user. + + - Use the confirmation code/OTP with __password recovery confirm API__ + to confirm the password recovery. + content: + application/json: + schema: + $ref: '#/components/schemas/ResendConfirmationCodeInternalResponse' + examples: + response: + value: + code: PWR-02002 + message: successful_request + flowConfirmationCode: 1234-1234-1234-1234 + notificationChannel: EMAIL + resendCode: 1234-12345-234-123456 + links: + - rel: next + href: api/user/v1/recovery/password/recover + type: POST + - rel: resend + href: api/users/v1/recovery/password/resend + type: POST + '400': + description: Bad Request. Request cannot be processed by the server. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: UAR-10001 + message: bad_request + description: bad request + traceId: 23456fghj678vb78 + '404': + description: Resend code is not found. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: UAR-10001 + message: not_found + description: recovery code not found + traceId: 23456fghj678vb78 + '406': + description: Resend code given in the request is not valid or expired. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: UAR-10003 + message: not acceptable + description: 'invalid error code : 1234-2345-12345-123456' + traceId: 23456fghj678vb78 + '500': + description: Server Error. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: UAR-15001 + message: Internal Error + description: Internal Error + traceId: 23456fghj678vb78 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ResendConfirmationRequest' + description: > + - Request to resend the `confirmationCode`/`otp` to the user via a user + preferred channel. + + - Can send additional properties. + required: true + /recovery/password/confirm: + post: + tags: + - Password Recovery + summary: | + Confirm password recovery + operationId: confirmRecovery + description: > + - This API is used to validate the __confirmationCode__/__otp__ given at + password recovery. + + - Use the returned __reset code__ with the __password reset API__ to + reset the password. + + - The API will return the next API call. + responses: + '200': + description: | + - Password reset confirmed. + - `resetCode` is returned. + content: + application/json: + schema: + $ref: '#/components/schemas/ResetCodeResponse' + examples: + response: + value: + resetCode: 2806aed9-fe7c-4b47-a91f-0aa897fac9a2 + links: + - rel: next + href: >- + /t/carbon.super/api/users/v1/recovery/password/reset + type: POST + '400': + description: Bad Request. Request cannot be processed by the server. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: PWR-10001 + message: bad_request + description: bad request + traceId: 23456fghj678vb78 + '404': + description: Confirmation code is not found. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: PWR-10001 + message: not_found + description: recovery code not found + traceId: 23456fghj678vb78 + '406': + description: | + Confirmation code given in the request is not valid or expired. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: PWR-10001 + message: not acceptable + description: 'invalid error code : 1234-2345-12345-123456' + traceId: 23456fghj678vb78 + '500': + description: Server Error. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: PWR-15001 + message: Internal Error + description: Internal Error + traceId: 23456fghj678vb78 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ConfirmRequest' + description: | + - Request to confirm the password recovery. + - `confirmationCode` is `REQUIRED`. + - `otp` is required only for OTP based password recovery. The __flowConfirmationCode__ returned from the password recovery request should be set as the `confirmationCode` for OTP based recovery. + required: true + /recovery/password/reset: + post: + tags: + - Password Recovery + summary: | + Reset password + operationId: resetPassword + description: > + This API is used to reset the password of the user who matches the flowConfirmationCode given by the recover API and the resetCode given by the confirmation API. + responses: + '200': + description: Successful password reset. + content: + application/json: + schema: + $ref: '#/components/schemas/PasswordResetResponse' + examples: + response: + value: + code: PWR-02005 + message: Successful password reset + '400': + description: Bad Request. Request cannot be processed by the server. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: PWR-10001 + message: bad_request + description: bad request + traceId: 23456fghj678vb78 + '404': + description: Reset code is not found. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: PWR-10001 + message: not_found + description: recovery code not found + traceId: 23456fghj678vb78 + '406': + description: Reset code given in the request is not valid or expired. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: PWR-10001 + message: not acceptable + description: 'invalid error code : 1234-2345-12345-123456' + traceId: 23456fghj678vb78 + '412': + description: Password policy violation. + content: + application/json: + schema: + $ref: '#/components/schemas/RetryErrorResponse' + examples: + response: + value: + code: PWR-10001 + message: bad_request + description: password policy violation + traceId: 23456fghj678vb78 + resetCode: 1234-12345-sdf-34567567 + links: [ + { + "rel": "next", + "href": "/t/carbon.super/api/users/v1/recovery/password/reset", + "type": "POST" + } + ] + '500': + description: Server Error. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + response: + value: + code: PWR-15001 + message: Internal Error + description: Internal Error + traceId: 23456fghj678vb78 + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ResetRequest' + description: | + - Request to reset the password. + - `resetCode`, `flowConfirmationCode` and `password` are required. + required: true +servers: + - url: 'https://localhost/api/users/v1' +components: + schemas: + InitRequest: + type: object + description: Request to initate an account recovery + properties: + claims: + type: array + description: User claims to identify the user as UserClaim objects + items: + $ref: '#/components/schemas/UserClaim' + properties: + type: array + description: (OPTIONAL) Additional META properties + items: + $ref: '#/components/schemas/Property' + required: + - claims + RecoveryRequest: + type: object + description: >- + Request to start the recovery for the user who matches the recovery code + via the given channelID + properties: + recoveryCode: + type: string + description: Recovery code for the user + example: 1234-5678-2455-3433 + channelId: + type: string + description: >- + Id of the notification channel that user preferrs to get recovery + notifications. + example: '1' + properties: + type: array + description: (OPTIONAL) Additional META properties + items: + $ref: '#/components/schemas/Property' + required: + - recoveryCode + - channelId + ResendConfirmationRequest: + type: object + description: Request to resend the confirmation code in password recovery + properties: + resendCode: + type: string + description: Resend code returned by the password recovery API + example: 1234-2ws34-1234 + properties: + type: array + description: (OPTIONAL) Additional META properties + items: + $ref: '#/components/schemas/Property' + ConfirmRequest: + type: object + description: Request to confirm password recovery + properties: + confirmationCode: + type: string + description: Confirmation code of the recovery flow + example: 1234-2ws34-12345 + otp: + type: string + description: OTP sent to the user + example: wi8Ivm + properties: + type: array + description: (OPTIONAL) Additional META properties + items: + $ref: '#/components/schemas/Property' + ResetRequest: + type: object + description: Object to reset the password of a user + properties: + resetCode: + type: string + description: resetCode given by the confim API + flowConfirmationCode: + type: string + description: Confirmation code of the recovery flow + password: + type: string + description: New password given by the user + properties: + type: array + description: (OPTIONAL) Additional META properties + items: + $ref: '#/components/schemas/Property' + PasswordRecoveryInternalNotifyResponse: + type: object + properties: + code: + type: string + description: Success status code + example: PWR-02002 + message: + type: string + description: Success status message + example: successful_request + flowConfirmationCode: + type: string + description: Recovery flow confirmation code + example: 1234-1234-1234-1234 + notificationChannel: + type: string + description: Channel that is used to send recovery information + example: EMAIL + resendCode: + type: string + description: >- + Code to resend the confirmation code to the user via user user + selected channel + example: 1234-123456-12345-12345 + links: + type: array + description: Contains available api calls + items: + $ref: '#/components/schemas/APICall' + PasswordRecoveryExternalNotifyResponse: + type: object + properties: + code: + type: string + description: Success status code + example: PWR-02002 + message: + type: string + description: Success status message + example: successful_request + flowConfirmationCode: + type: string + description: Recovery flow confirmation code + example: 1234-1234-1234-1234 + notificationChannel: + type: string + description: Channel that is used to send recovery information + example: EXTERNAL + confirmationCode: + type: string + description: > + - Confirmation code for password recovery when the notifications are + externally managed. + + - The confirmation code will be returned only if the notification + channel is _EXTERNAL_. Use this code with password confirm API to + get a password reset code. + example: 12345-45678-6789098-8765 + resendCode: + type: string + description: >- + Code to get a new confirmation code. + example: 1234-123456-12345-12345 + links: + type: array + description: Contains available api calls + items: + $ref: '#/components/schemas/APICall' + UsernameRecoveryNotifyResponse: + type: object + description: API response for successful username recovery + properties: + code: + type: string + description: Success status code + example: UNR-02001 + message: + type: string + description: Success status message + example: successful_request + notificationChannel: + type: string + description: Channel which the recovery information is sent to the user + example: EXTERNAL + username: + type: string + example: user1 + description: > + - Username of the user + + - Username will be returned _ONLY IF_ the notification channel is + `EXTERNAL` + required: + - code + - message + - notificationChannel + - username + ResetCodeResponse: + properties: + resetCode: + type: string + description: Password reset code to reset the password + example: 1234-55678-5668-2345 + links: + type: array + description: Contains available api calls + items: + $ref: '#/components/schemas/APICall' + PasswordResetResponse: + type: object + description: API response for a successful password reset + properties: + code: + type: string + description: Operation code + example: PWR-02001 + message: + type: string + description: Message regarding the operation. + example: successful_request + ResendConfirmationCodeExternalResponse: + type: object + description: Object encapsulate the details regarding resend confirmation code + properties: + code: + type: string + description: Success status code + example: PWR-02002 + message: + type: string + description: Success status message + example: successful_request + flowConfirmationCode: + type: string + description: Recovery flow confirmation code + example: 1234-1234-1234-1234 + notificationChannel: + type: string + description: Channel that is used to send recovery information + example: EMAIL + confirmationCode: + type: string + description: Confirmation code to confirm the password recovery + example: 1234-12345-234-123456 + resendCode: + type: string + description: Resend code to resend the confirmation code + example: 1234-12345-234-123456 + links: + type: array + description: Contains available api calls + items: + $ref: '#/components/schemas/APICall' + ResendConfirmationCodeInternalResponse: + type: object + description: Object encapsulate the details regarding resend confirmation code + properties: + code: + type: string + description: Success status code + example: PWR-02002 + message: + type: string + description: Success status message + example: successful_request + flowConfirmationCode: + type: string + description: Recovery flow confirmation code + example: 1234-1234-1234-1234 + notificationChannel: + type: string + description: Channel that is used to send recovery information + example: EMAIL + resendCode: + type: string + description: Resend code to resend the confirmation code + example: 1234-12345-234-123456 + links: + type: array + description: Contains available api calls + items: + $ref: '#/components/schemas/APICall' + RetryErrorResponse: + type: object + properties: + code: + type: string + description: Error code corresponding to the error + example: PWR-10004 + message: + type: string + description: Error message + example: Retry + description: + type: string + description: Error description + example: Password policy violation + traceId: + type: string + description: Some Correlation for Error Instance + example: 2345dfgh678h789bhjk + resetCode: + type: string + description: Password reset code used in the request + example: 1234-34567-3456-2345678 + links: + type: array + description: Contains available api calls + items: + $ref: '#/components/schemas/APICall' + ErrorResponse: + type: object + properties: + code: + type: string + description: Error code corresponding to the error + example: UAR-10001 + message: + type: string + description: Error message + example: invalid_request + description: + type: string + description: Description about the error + example: Invalid claim uri + traceId: + type: string + description: Some Correlation for Error Instance + example: 2345dfgh678h789bhjk + AccountRecoveryType: + type: object + description: Object that encapsulates details of the account recovery channel + properties: + mode: + type: string + example: recoverWithNotifications + flowConfirmationCode: + type: string + example: 1234-1234-1234-1234 + channelInfo: + $ref: '#/components/schemas/RecoveryChannelInformation' + links: + type: array + description: Contains available api calls + items: + $ref: '#/components/schemas/APICall' + RecoveryChannelInformation: + description: Response with the recovery ID and the available recovery channels + properties: + recoveryCode: + type: string + description: Code to recovery the user account + example: 1234-55678-5668-2345 + channels: + type: array + description: Availabel recovery channels for the user + items: + $ref: '#/components/schemas/RecoveryChannel' + RecoveryChannel: + type: object + description: Object with notification channel attributes + properties: + id: + type: string + description: Id given to the channel + example: '1' + type: + type: string + description: Type of the chanel + example: EMAIL + value: + type: string + description: Masked channel value + example: wso2***********.com + preferred: + type: boolean + description: Whether the channel is a user preferred channel + example: true + UserClaim: + type: object + description: Object that holds a user claim and the corresponding value + properties: + uri: + type: string + description: Claim uri + example: 'http://wso2.org/claims/givenname' + value: + type: string + description: Value for the claim + example: user1 + Property: + type: object + description: 'object that holds a property as a key, value pair' + properties: + key: + type: string + description: Unique identifier as the key of the peroperty + example: key + value: + type: string + description: Value of the property + example: value + APICall: + type: object + description: Object that holds next API call details + properties: + rel: + type: string + description: Next API call + example: next + href: + type: string + description: Next API url + example: /api/users/recovery/v1/ + type: + type: string + description: HTTP method type + example: POST diff --git a/components/org.wso2.carbon.identity.api.user.recovery/pom.xml b/components/org.wso2.carbon.identity.api.user.recovery/pom.xml index e07c704d..cdea07b2 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/pom.xml +++ b/components/org.wso2.carbon.identity.api.user.recovery/pom.xml @@ -28,6 +28,7 @@ org.wso2.carbon.identity.api.user.recovery.commons org.wso2.carbon.identity.rest.api.user.recovery.v1 + org.wso2.carbon.identity.rest.api.user.recovery.v2 From bcc6761fa2ea0a48dcf0fa34f41a0e1173783c4c Mon Sep 17 00:00:00 2001 From: Rashmini Date: Tue, 29 Aug 2023 16:45:44 +0530 Subject: [PATCH 02/17] Re-generate files --- .../api/user/recovery/v2/RecoveryApi.java | 23 +++++++------ .../user/recovery/v2/RecoveryApiService.java | 1 + .../v2/model/AccountRecoveryType.java | 8 +++-- .../recovery/v2/model/ConfirmRequest.java | 15 ++++---- ...asswordRecoveryExternalNotifyResponse.java | 10 +++--- ...asswordRecoveryInternalNotifyResponse.java | 10 +++--- ...esendConfirmationCodeExternalResponse.java | 10 +++--- ...esendConfirmationCodeInternalResponse.java | 10 +++--- .../user/recovery/v2/model/ResetRequest.java | 18 ++++++---- .../main/resources/user.account.recovery.yaml | 34 +++++++++++-------- 10 files changed, 82 insertions(+), 57 deletions(-) diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/RecoveryApi.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/RecoveryApi.java index 4f95030a..2f317d88 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/RecoveryApi.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/RecoveryApi.java @@ -22,6 +22,7 @@ import org.apache.cxf.jaxrs.ext.multipart.Attachment; import org.apache.cxf.jaxrs.ext.multipart.Multipart; import java.io.InputStream; +import java.util.List; import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.AccountRecoveryType; import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ConfirmRequest; @@ -60,7 +61,7 @@ public class RecoveryApi { @Path("/password/confirm") @Consumes({ "application/json" }) @Produces({ "application/json" }) - @ApiOperation(value = "Confirm password recovery ", notes = "- This API is used to validate the __confirmationCode__ given at password recovery. - Use the returned __reset code__ with the __password reset API__ to reset the password. - The API will return the next API call. ", response = ResetCodeResponse.class, tags={ "Password Recovery", }) + @ApiOperation(value = "Confirm password recovery ", notes = "- This API is used to validate the __confirmationCode__/__otp__ given at password recovery. - Use the returned __reset code__ with the __password reset API__ to reset the password. - The API will return the next API call. ", response = ResetCodeResponse.class, tags={ "Password Recovery", }) @ApiResponses(value = { @ApiResponse(code = 200, message = "- Password reset confirmed. - `resetCode` is returned. ", response = ResetCodeResponse.class), @ApiResponse(code = 400, message = "Bad Request. Request cannot be processed by the server.", response = ErrorResponse.class), @@ -68,7 +69,7 @@ public class RecoveryApi { @ApiResponse(code = 406, message = "Confirmation code given in the request is not valid or expired. ", response = ErrorResponse.class), @ApiResponse(code = 500, message = "Server Error.", response = ErrorResponse.class) }) - public Response confirmRecovery(@ApiParam(value = "- Request to confirm the password recovery. - `confirmationCode` is `REQUIRED`. " ,required=true) @Valid ConfirmRequest confirmRequest) { + public Response confirmRecovery(@ApiParam(value = "- Request to confirm the password recovery. - `confirmationCode` is `REQUIRED`. - `otp` is required only for OTP based password recovery. The __flowConfirmationCode__ returned from the password recovery request should be set as the `confirmationCode` for OTP based recovery. " ,required=true) @Valid ConfirmRequest confirmRequest) { return delegate.confirmRecovery(confirmRequest ); } @@ -78,7 +79,7 @@ public Response confirmRecovery(@ApiParam(value = "- Request to confirm the pass @Path("/password/init") @Consumes({ "application/json" }) @Produces({ "application/json" }) - @ApiOperation(value = "Initiate password recovery ", notes = "- This API is used to initiate password recovery by user. The API will return recovery information for password recovery with challenge questions and password recovery with notifications. - `mode` __recoverWithNotifications__ contains available communication channels and a recovery code for password recovery with notifications. The next API call will be returned in the response. - If `password recovery with notifications` is not enabled, the response will not contain __recoverWithNotifications__ mode. - __recoverWithChallengeQuestions__ contains the next API call to begin the recovery process via challenge questions. - If `password recovery with challenge questions` is not enabled, the response will not contain __recoverWithChallengeQuestions__ mode. ", response = AccountRecoveryType.class, responseContainer = "List", tags={ "Password Recovery", }) + @ApiOperation(value = "Initiate password recovery ", notes = "- This API is used to initiate password recovery by user. The API will return recovery information for password recovery with challenge questions and password recovery with notifications. - `mode` __recoverWithNotifications__ contains recovery flow confirmation code, available communication channels and a recovery code for password recovery with notifications. The next API call will be returned in the response. - If `password recovery with notifications` is not enabled, the response will not contain __recoverWithNotifications__ mode. - __recoverWithChallengeQuestions__ contains the next API call to begin the recovery process via challenge questions. - If `password recovery with challenge questions` is not enabled, the response will not contain __recoverWithChallengeQuestions__ mode. ", response = AccountRecoveryType.class, responseContainer = "List", tags={ "Password Recovery", }) @ApiResponses(value = { @ApiResponse(code = 200, message = "User is successfully identified for the given claims and returning available notification channels for the user.", response = AccountRecoveryType.class, responseContainer = "List"), @ApiResponse(code = 400, message = "Bad Request. The request cannot be processed by the server.", response = ErrorResponse.class), @@ -115,10 +116,10 @@ public Response initiateUsernameRecovery(@ApiParam(value = "Request to initate u @Path("/password/recover") @Consumes({ "application/json" }) @Produces({ "application/json" }) - @ApiOperation(value = "Get Recovery Information ", notes = "- This API is used to send recovery information to the user who matches the recovery code via the channel specified by the channel Id. - NOTE: If the notification channel is EXTERNAL, the API will return a confirmationCode. - Use the returned confimation code with __password recpvery confirm API__ to verify the password recovery process. - The API will return the next API call. ", response = PasswordRecoveryExternalNotifyResponse.class, tags={ "Password Recovery", }) + @ApiOperation(value = "Get Recovery Information ", notes = "- This API is used to send recovery information to the user who matches the recovery code via the channel specified by the channel Id. The API will return the recovery flow confirmation code. - NOTE: If the notification channel is EXTERNAL, the API will return a confirmationCode. - Use the returned confimation code with __password recovery confirm API__ to verify the password recovery process. - The API will return the next API call. ", response = PasswordRecoveryExternalNotifyResponse.class, tags={ "Password Recovery", }) @ApiResponses(value = { - @ApiResponse(code = 200, message = "- Password recovery initiated via `EXTERNAL` channel. API will return a `confirmationCode` to confirm password recovery. - Use the confirmation code with __password recpvery confirm API__ to confirm the password recovery. ", response = PasswordRecoveryExternalNotifyResponse.class), - @ApiResponse(code = 202, message = "- Password recovery initiated via internal channels. API will send a `confirmationCode` to the channel specified by the user. - Use the confirmation code with __password recovery confirm API__ to confirm the password recovery. ", response = PasswordRecoveryInternalNotifyResponse.class), + @ApiResponse(code = 200, message = "- Password recovery initiated via `EXTERNAL` channel. API will return a `confirmationCode` to confirm password recovery. - Use the confirmation code with __password recovery confirm API__ to confirm the password recovery. ", response = PasswordRecoveryExternalNotifyResponse.class), + @ApiResponse(code = 202, message = "- Password recovery initiated via internal channels. API will send a `confirmationCode`/`otp` to the channel specified by the user. - Use the confirmation code/OTP with __password recovery confirm API__ to confirm the password recovery. ", response = PasswordRecoveryInternalNotifyResponse.class), @ApiResponse(code = 400, message = "Bad Request. Request cannot be processed by the server.", response = ErrorResponse.class), @ApiResponse(code = 403, message = "Password recovery is not enabled.", response = ErrorResponse.class), @ApiResponse(code = 404, message = "Recovery code is not found.", response = ErrorResponse.class), @@ -154,16 +155,16 @@ public Response recoverUsername(@ApiParam(value = "- Request to confirm username @Path("/password/resend") @Consumes({ "application/json" }) @Produces({ "application/json" }) - @ApiOperation(value = "Resend password recovery confirmation details ", notes = "- This API is used to resend a confirmation code to the user via a user preferred channel defined at password recovery. - NOTE: The API cannot be used when the notification channel is external. - The API will return the next API calls. ", response = ResendConfirmationCodeExternalResponse.class, tags={ "Password Recovery", }) + @ApiOperation(value = "Resend password recovery confirmation details ", notes = "- This API is used to resend a confirmation code/OTP to the user via a user preferred channel defined at password recovery. - NOTE: The API cannot be used when the notification channel is external. - The API will return the next API calls. ", response = ResendConfirmationCodeExternalResponse.class, tags={ "Password Recovery", }) @ApiResponses(value = { @ApiResponse(code = 200, message = "- API will return a new `confirmationCode`. - Use the confirmation code with __password recovery confirm API__ to confirm the password recovery. ", response = ResendConfirmationCodeExternalResponse.class), - @ApiResponse(code = 202, message = "- API will send a `confirmationCode` to the channel specified by the user. - Use the confirmation code with __password recovery confirm API__ to confirm the password recovery. ", response = ResendConfirmationCodeInternalResponse.class), + @ApiResponse(code = 202, message = "- API will send a `confirmationCode`/`otp` to the channel specified by the user. - Use the confirmation code/OTP with __password recovery confirm API__ to confirm the password recovery. ", response = ResendConfirmationCodeInternalResponse.class), @ApiResponse(code = 400, message = "Bad Request. Request cannot be processed by the server.", response = ErrorResponse.class), @ApiResponse(code = 404, message = "Resend code is not found.", response = ErrorResponse.class), @ApiResponse(code = 406, message = "Resend code given in the request is not valid or expired.", response = ErrorResponse.class), @ApiResponse(code = 500, message = "Server Error.", response = ErrorResponse.class) }) - public Response resendConfirmation(@ApiParam(value = "- Request to resend the `confirmationCode` to the user via a user preferred channel. - Can send additional properties. " ,required=true) @Valid ResendConfirmationRequest resendConfirmationRequest) { + public Response resendConfirmation(@ApiParam(value = "- Request to resend the `confirmationCode`/`otp` to the user via a user preferred channel. - Can send additional properties. " ,required=true) @Valid ResendConfirmationRequest resendConfirmationRequest) { return delegate.resendConfirmation(resendConfirmationRequest ); } @@ -173,7 +174,7 @@ public Response resendConfirmation(@ApiParam(value = "- Request to resend the `c @Path("/password/reset") @Consumes({ "application/json" }) @Produces({ "application/json" }) - @ApiOperation(value = "Reset password ", notes = "This API is used to reset the password of the user who matches the resetCode given by the confirmation API. ", response = PasswordResetResponse.class, tags={ "Password Recovery" }) + @ApiOperation(value = "Reset password ", notes = "This API is used to reset the password of the user who matches the flowConfirmationCode given by the recover API and the resetCode given by the confirmation API. ", response = PasswordResetResponse.class, tags={ "Password Recovery" }) @ApiResponses(value = { @ApiResponse(code = 200, message = "Successful password reset.", response = PasswordResetResponse.class), @ApiResponse(code = 400, message = "Bad Request. Request cannot be processed by the server.", response = ErrorResponse.class), @@ -182,7 +183,7 @@ public Response resendConfirmation(@ApiParam(value = "- Request to resend the `c @ApiResponse(code = 412, message = "Password policy violation.", response = RetryErrorResponse.class), @ApiResponse(code = 500, message = "Server Error.", response = ErrorResponse.class) }) - public Response resetPassword(@ApiParam(value = "- Request to reset the password. - `resetCode` and `password` are required. " ,required=true) @Valid ResetRequest resetRequest) { + public Response resetPassword(@ApiParam(value = "- Request to reset the password. - `resetCode`, `flowConfirmationCode` and `password` are required. " ,required=true) @Valid ResetRequest resetRequest) { return delegate.resetPassword(resetRequest ); } diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/RecoveryApiService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/RecoveryApiService.java index 54a2dc51..4d78dedf 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/RecoveryApiService.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/RecoveryApiService.java @@ -23,6 +23,7 @@ import org.apache.cxf.jaxrs.ext.multipart.Attachment; import org.apache.cxf.jaxrs.ext.multipart.Multipart; import java.io.InputStream; +import java.util.List; import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.AccountRecoveryType; import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ConfirmRequest; import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/AccountRecoveryType.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/AccountRecoveryType.java index 1aedc7ee..320407ee 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/AccountRecoveryType.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/AccountRecoveryType.java @@ -64,14 +64,14 @@ public void setMode(String mode) { } /** - **/ + **/ public AccountRecoveryType flowConfirmationCode(String flowConfirmationCode) { this.flowConfirmationCode = flowConfirmationCode; return this; } - - @ApiModelProperty(value = "") + + @ApiModelProperty(example = "1234-1234-1234-1234", value = "") @JsonProperty("flowConfirmationCode") @Valid public String getFlowConfirmationCode() { @@ -126,6 +126,8 @@ public AccountRecoveryType addLinksItem(APICall linksItem) { return this; } + + @Override public boolean equals(java.lang.Object o) { diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ConfirmRequest.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ConfirmRequest.java index 31dfa0c3..90927de1 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ConfirmRequest.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ConfirmRequest.java @@ -51,11 +51,12 @@ public ConfirmRequest confirmationCode(String confirmationCode) { this.confirmationCode = confirmationCode; return this; } - - @ApiModelProperty(example = "1234-2ws34-12345", value = "Confirmation code of the recovery flow") + + @ApiModelProperty(example = "1234-2ws34-12345", required = true, value = "Confirmation code of the recovery flow") @JsonProperty("confirmationCode") @Valid @NotNull(message = "Property confirmationCode cannot be null.") + public String getConfirmationCode() { return confirmationCode; } @@ -64,21 +65,21 @@ public void setConfirmationCode(String confirmationCode) { } /** - * OTP sent to the user - **/ + * OTP sent to the user + **/ public ConfirmRequest otp(String otp) { this.otp = otp; return this; } - - @ApiModelProperty(example = "abc123", value = "OTP sent to the user") + + @ApiModelProperty(example = "wi8Ivm", value = "OTP sent to the user") @JsonProperty("otp") @Valid public String getOtp() { return otp; } - public void seOtp(String otp) { + public void setOtp(String otp) { this.otp = otp; } diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordRecoveryExternalNotifyResponse.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordRecoveryExternalNotifyResponse.java index 2bc683b6..369c4e34 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordRecoveryExternalNotifyResponse.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordRecoveryExternalNotifyResponse.java @@ -83,15 +83,15 @@ public void setMessage(String message) { } /** - * Recovery flow confirmation code - **/ + * Recovery flow confirmation code + **/ public PasswordRecoveryExternalNotifyResponse flowConfirmationCode(String flowConfirmationCode) { this.flowConfirmationCode = flowConfirmationCode; return this; } - - @ApiModelProperty(example = "1234-1234-1234-1234", value = "Flow confirmation code of the recovery flow") + + @ApiModelProperty(example = "1234-1234-1234-1234", value = "Recovery flow confirmation code") @JsonProperty("flowConfirmationCode") @Valid public String getFlowConfirmationCode() { @@ -185,6 +185,8 @@ public PasswordRecoveryExternalNotifyResponse addLinksItem(APICall linksItem) { return this; } + + @Override public boolean equals(java.lang.Object o) { diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordRecoveryInternalNotifyResponse.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordRecoveryInternalNotifyResponse.java index f8e86ff6..d9bf97e8 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordRecoveryInternalNotifyResponse.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/PasswordRecoveryInternalNotifyResponse.java @@ -82,15 +82,15 @@ public void setMessage(String message) { } /** - * Recovery flow confirmation code - **/ + * Recovery flow confirmation code + **/ public PasswordRecoveryInternalNotifyResponse flowConfirmationCode(String flowConfirmationCode) { this.flowConfirmationCode = flowConfirmationCode; return this; } - - @ApiModelProperty(example = "1234-1234-1234-1234", value = "Flow confirmation code of the recovery flow") + + @ApiModelProperty(example = "1234-1234-1234-1234", value = "Recovery flow confirmation code") @JsonProperty("flowConfirmationCode") @Valid public String getFlowConfirmationCode() { @@ -165,6 +165,8 @@ public PasswordRecoveryInternalNotifyResponse addLinksItem(APICall linksItem) { return this; } + + @Override public boolean equals(java.lang.Object o) { diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationCodeExternalResponse.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationCodeExternalResponse.java index 49c6ca66..d4164367 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationCodeExternalResponse.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationCodeExternalResponse.java @@ -86,15 +86,15 @@ public void setMessage(String message) { } /** - * Recovery flow confirmation code - **/ + * Recovery flow confirmation code + **/ public ResendConfirmationCodeExternalResponse flowConfirmationCode(String flowConfirmationCode) { this.flowConfirmationCode = flowConfirmationCode; return this; } - - @ApiModelProperty(example = "1234-1234-1234-1234", value = "Flow confirmation code of the recovery flow") + + @ApiModelProperty(example = "1234-1234-1234-1234", value = "Recovery flow confirmation code") @JsonProperty("flowConfirmationCode") @Valid public String getFlowConfirmationCode() { @@ -188,6 +188,8 @@ public ResendConfirmationCodeExternalResponse addLinksItem(APICall linksItem) { return this; } + + @Override public boolean equals(java.lang.Object o) { diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationCodeInternalResponse.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationCodeInternalResponse.java index 437706d2..9aa90690 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationCodeInternalResponse.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResendConfirmationCodeInternalResponse.java @@ -85,15 +85,15 @@ public void setMessage(String message) { } /** - * Recovery flow confirmation code - **/ + * Recovery flow confirmation code + **/ public ResendConfirmationCodeInternalResponse flowConfirmationCode(String flowConfirmationCode) { this.flowConfirmationCode = flowConfirmationCode; return this; } - - @ApiModelProperty(example = "1234-1234-1234-1234", value = "Flow confirmation code of the recovery flow") + + @ApiModelProperty(example = "1234-1234-1234-1234", value = "Recovery flow confirmation code") @JsonProperty("flowConfirmationCode") @Valid public String getFlowConfirmationCode() { @@ -168,6 +168,8 @@ public ResendConfirmationCodeInternalResponse addLinksItem(APICall linksItem) { return this; } + + @Override public boolean equals(java.lang.Object o) { diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResetRequest.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResetRequest.java index f7448454..0d669ee8 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResetRequest.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResetRequest.java @@ -53,10 +53,11 @@ public ResetRequest resetCode(String resetCode) { return this; } - @ApiModelProperty(value = "resetCode given by the confim API") + @ApiModelProperty(required = true, value = "resetCode given by the confim API") @JsonProperty("resetCode") @Valid @NotNull(message = "Property resetCode cannot be null.") + public String getResetCode() { return resetCode; } @@ -65,18 +66,19 @@ public void setResetCode(String resetCode) { } /** - * Confirmation code of the recovery flow - **/ + * Confirmation code of the recovery flow + **/ public ResetRequest flowConfirmationCode(String flowConfirmationCode) { this.flowConfirmationCode = flowConfirmationCode; return this; } - - @ApiModelProperty(example = "1234-2ws34-12345", value = "Confirmation code of the recovery flow") + + @ApiModelProperty(required = true, value = "Confirmation code of the recovery flow") @JsonProperty("flowConfirmationCode") @Valid @NotNull(message = "Property flowConfirmationCode cannot be null.") + public String getFlowConfirmationCode() { return flowConfirmationCode; } @@ -93,9 +95,11 @@ public ResetRequest password(String password) { return this; } - @ApiModelProperty(value = "New password given by the user") + @ApiModelProperty(required = true, value = "New password given by the user") @JsonProperty("password") @Valid + @NotNull(message = "Property password cannot be null.") + public String getPassword() { return password; } @@ -130,6 +134,8 @@ public ResetRequest addPropertiesItem(Property propertiesItem) { return this; } + + @Override public boolean equals(java.lang.Object o) { diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/resources/user.account.recovery.yaml b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/resources/user.account.recovery.yaml index 89c0684a..679b6adf 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/resources/user.account.recovery.yaml +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/resources/user.account.recovery.yaml @@ -55,7 +55,7 @@ paths: preferred: false links: - rel: next - href: /api/users/v1/recovery/username/recover + href: /api/users/v2/recovery/username/recover type: POST '400': description: Bad Request. The request cannot be processed by the server. @@ -293,7 +293,7 @@ paths: preferred: true links: - rel: next - href: /api/users/v1/recovery/password/recovery + href: /api/users/v2/recovery/password/recovery type: POST - mode: recoverWithChallengeQuestions links: @@ -405,10 +405,10 @@ paths: resendCode: 12345-45678-6789098-8765 links: - rel: next - href: api/users/v1/recovery/password/confirm + href: api/users/v2/recovery/password/confirm type: POST - rel: resend - href: api/users/v1/recovery/password/resend + href: api/users/v2/recovery/password/resend type: POST '202': description: > @@ -431,10 +431,10 @@ paths: resendCode: 12345-45678-6789098-8765 links: - rel: next - href: api/users/v1/recovery/password/confirm + href: api/users/v2/recovery/password/confirm type: POST - rel: resend - href: api/users/v1/recovery/password/resend + href: api/users/v2/recovery/password/resend type: POST '400': description: Bad Request. Request cannot be processed by the server. @@ -550,10 +550,10 @@ paths: resendCode: 1234-12345-234-123456 links: - rel: next - href: api/users/v1/recovery/password/recover + href: api/users/v2/recovery/password/recover type: POST - rel: resend - href: api/users/v1/recovery/password/resend + href: api/users/v2/recovery/password/resend type: POST '202': description: > @@ -576,10 +576,10 @@ paths: resendCode: 1234-12345-234-123456 links: - rel: next - href: api/user/v1/recovery/password/recover + href: api/user/v2/recovery/password/recover type: POST - rel: resend - href: api/users/v1/recovery/password/resend + href: api/users/v2/recovery/password/resend type: POST '400': description: Bad Request. Request cannot be processed by the server. @@ -675,7 +675,7 @@ paths: links: - rel: next href: >- - /t/carbon.super/api/users/v1/recovery/password/reset + /t/carbon.super/api/users/v2/recovery/password/reset type: POST '400': description: Bad Request. Request cannot be processed by the server. @@ -817,7 +817,7 @@ paths: links: [ { "rel": "next", - "href": "/t/carbon.super/api/users/v1/recovery/password/reset", + "href": "/t/carbon.super/api/users/v2/recovery/password/reset", "type": "POST" } ] @@ -844,7 +844,7 @@ paths: - `resetCode`, `flowConfirmationCode` and `password` are required. required: true servers: - - url: 'https://localhost/api/users/v1' + - url: 'https://localhost/api/users/v2' components: schemas: InitRequest: @@ -903,6 +903,8 @@ components: ConfirmRequest: type: object description: Request to confirm password recovery + required: + - confirmationCode properties: confirmationCode: type: string @@ -920,6 +922,10 @@ components: ResetRequest: type: object description: Object to reset the password of a user + required: + - resetCode + - flowConfirmationCode + - password properties: resetCode: type: string @@ -1249,7 +1255,7 @@ components: href: type: string description: Next API url - example: /api/users/recovery/v1/ + example: /api/users/recovery/v2/ type: type: string description: HTTP method type From e70ec1e4f6ae43fb67f7dea0c139494935bdd1ca Mon Sep 17 00:00:00 2001 From: Rashmini Date: Tue, 12 Sep 2023 11:40:30 +0530 Subject: [PATCH 03/17] Fix comments --- .../v2/impl/core/PasswordRecoveryService.java | 14 ++--- .../v2/impl/core/utils/RecoveryUtil.java | 59 +++++++------------ 2 files changed, 27 insertions(+), 46 deletions(-) diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java index 86090364..96d5be44 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java @@ -61,7 +61,7 @@ */ public class PasswordRecoveryService { - private static final Log log = LogFactory.getLog(PasswordRecoveryService.class.getName()); + private static final Log LOG = LogFactory.getLog(PasswordRecoveryService.class.getName()); /** * Initiate Password Recovery from POST. @@ -81,9 +81,9 @@ public Response initiatePasswordRecovery(InitRequest initRequest) { RecoveryUtil.buildPropertiesMap(initRequest.getProperties())); // If RecoveryChannelInfoDTO is null throw not found error. if (recoveryInformationDTO == null) { - if (log.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { String message = "No recovery information for password recovery request"; - log.debug(message); + LOG.debug(message); } return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } @@ -115,10 +115,10 @@ public Response recoverPassword(RecoveryRequest recoveryRequest) { .notify(recoveryId, channelId, tenantDomain, RecoveryUtil.buildPropertiesMap(recoveryRequest.getProperties())); if (passwordRecoverDTO == null) { - if (log.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { String message = String .format("No password recovery data object for recovery code : %s", recoveryId); - log.debug(message); + LOG.debug(message); } return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } @@ -202,8 +202,8 @@ public Response resendConfirmation(ResendConfirmationRequest resendConfirmationR UserAccountRecoveryServiceDataHolder.getPasswordRecoveryManager() .resend(tenantDomain, resendCode, properties); if (resendConfirmationDTO == null) { - if (log.isDebugEnabled()) { - log.debug("No ResendConfirmationDTO data for resend code :" + resendCode); + if (LOG.isDebugEnabled()) { + LOG.debug("No ResendConfirmationDTO data for resend code :" + resendCode); } return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java index 8d25e223..82fd19b3 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java @@ -111,7 +111,7 @@ public static HashMap buildPropertiesMap(List property */ public static List buildRecoveryChannelInformation(NotificationChannelDTO[] channels) { - List recoveryChannelDTOS = new ArrayList<>(); + List recoveryChannelDTOs = new ArrayList<>(); if (channels != null) { // Create a response object and add the details to each object. for (NotificationChannelDTO channel : channels) { @@ -122,10 +122,10 @@ public static List buildRecoveryChannelInformation(Notification if (StringUtils.isNotEmpty(channel.getValue())) { recoveryChannel.setPreferred(channel.isPreferred()); } - recoveryChannelDTOS.add(recoveryChannel); + recoveryChannelDTOs.add(recoveryChannel); } } - return recoveryChannelDTOS; + return recoveryChannelDTOs; } /** @@ -147,12 +147,12 @@ public static WebApplicationException handleClientExceptions(String className, S /** * Handle client errors with specific http codes. * - * @param className Class name - * @param scenario Recovery scenario - * @param code Recovery code - * @param exception IdentityRecoveryClientException + * @param className Class name. + * @param scenario Recovery scenario. + * @param code Recovery code. + * @param exception IdentityRecoveryClientException. * @return WebApplicationException (NOTE: Returns null when the client error is for no user available or for - * multiple users available + * multiple users available. */ public static WebApplicationException handleClientExceptions(String className, String tenantDomain, String scenario, String code, String correlationId, @@ -211,12 +211,12 @@ public static WebApplicationException handleClientExceptions(String className, S /** * Logs the error, builds a internalServerErrorException with specified details and throws it. * - * @param className Class name - * @param message Error message - * @param code Error code - * @param correlationId Correlation Id - * @param throwable Error - * @return WebApplicationException + * @param className Class name. + * @param message Error message. + * @param code Error code. + * @param correlationId Correlation Id. + * @param throwable Error. + * @return WebApplicationException. */ public static WebApplicationException buildInternalServerErrorResponse(String className, String message, String code, String correlationId, @@ -236,11 +236,11 @@ public static WebApplicationException buildInternalServerErrorResponse(String cl /** * Build API call information. * - * @param type Type of the API call - * @param rel API relation - * @param apiUrl Url of the API - * @param data Additional data - * @return APICall {@link APICall} which encapsulates the API name and the url + * @param type Type of the API call. + * @param rel API relation. + * @param apiUrl Url of the API. + * @param data Additional data. + * @return APICall {@link APICall} which encapsulates the API name and the url. */ public static APICall buildApiCall(String type, String rel, String apiUrl, String data) { @@ -254,25 +254,6 @@ public static APICall buildApiCall(String type, String rel, String apiUrl, Strin return apiCall; } - /** - * @deprecated This was deprecated because the requirement is to get the absolute and relative URIs by using the - * {@link ServiceURLBuilder} methods. - * @since 1.1.6 - * - * Please use {@link #buildURIForBody(String, String, String)} method to build URIs for body. - * - * Build the relative url. - * @param tenantDomain Tenant Domain - * @param endpoint API endpoint - * @return Url - */ - public static String buildUri(String tenantDomain, String endpoint, String baseUrl) { - - String tenantQualifiedRelativePath = - String.format(TENANT_CONTEXT_PATH_COMPONENT, tenantDomain) + baseUrl; - return tenantQualifiedRelativePath + endpoint; - } - /** * Builds URI prepending the user API context with the proxy context path to the endpoint. * Ex: /t//api/users/ @@ -468,7 +449,7 @@ private static ConflictException buildConflictRequestResponseObject(String class ErrorResponse errorResponse = buildErrorResponse(Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, code, description, correlationId); if (StringUtils.isNotBlank(className)) { - description = String.format("CorrelationIc: %s : %s : %s - %s", correlationId, LOG_MESSAGE_PREFIX, + description = String.format("CorrelationId: %s : %s : %s - %s", correlationId, LOG_MESSAGE_PREFIX, className, description); } log.error(description); From 31b91ab698b67991081a9253fdb5e4ff95962b54 Mon Sep 17 00:00:00 2001 From: Rashmini Date: Fri, 15 Sep 2023 10:08:52 +0530 Subject: [PATCH 04/17] Remove required check for flow confirmation code in reset request --- .../rest/api/user/recovery/v2/model/ResetRequest.java | 4 +--- .../src/main/resources/user.account.recovery.yaml | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResetRequest.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResetRequest.java index 0d669ee8..54d7e496 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResetRequest.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/gen/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/model/ResetRequest.java @@ -74,11 +74,9 @@ public ResetRequest flowConfirmationCode(String flowConfirmationCode) { return this; } - @ApiModelProperty(required = true, value = "Confirmation code of the recovery flow") + @ApiModelProperty(value = "Confirmation code of the recovery flow") @JsonProperty("flowConfirmationCode") @Valid - @NotNull(message = "Property flowConfirmationCode cannot be null.") - public String getFlowConfirmationCode() { return flowConfirmationCode; } diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/resources/user.account.recovery.yaml b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/resources/user.account.recovery.yaml index 679b6adf..ae94b991 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/resources/user.account.recovery.yaml +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/resources/user.account.recovery.yaml @@ -924,7 +924,6 @@ components: description: Object to reset the password of a user required: - resetCode - - flowConfirmationCode - password properties: resetCode: From 902246a9079439fe90306d9f70061f4f2c0dd94e Mon Sep 17 00:00:00 2001 From: Rashmini Date: Mon, 18 Sep 2023 09:14:59 +0530 Subject: [PATCH 05/17] Improve error handling --- .../v2/impl/core/PasswordRecoveryService.java | 35 ++-- .../v2/impl/core/UsernameRecoveryService.java | 20 +-- .../core/exceptions/BadRequestException.java | 64 ------- .../core/exceptions/ConflictException.java | 3 +- .../core/exceptions/ForbiddenException.java | 3 +- .../InternalServerErrorException.java | 66 ------- .../exceptions/NotAcceptableException.java | 3 +- .../core/exceptions/NotFoundException.java | 3 +- .../PreconditionFailedException.java | 14 +- .../v2/impl/core/utils/RecoveryUtil.java | 162 ++++++------------ 10 files changed, 96 insertions(+), 277 deletions(-) delete mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/BadRequestException.java delete mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/InternalServerErrorException.java diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java index 96d5be44..7379be8b 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java @@ -90,11 +90,12 @@ public Response initiatePasswordRecovery(InitRequest initRequest) { return Response.ok().entity(buildPasswordRecoveryInitResponse(tenantDomain, recoveryInformationDTO)) .build(); } catch (IdentityRecoveryClientException e) { - throw RecoveryUtil.handleClientExceptions(PasswordRecoveryService.class.getName(), tenantDomain, + throw RecoveryUtil.handleClientExceptions(tenantDomain, IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation(), e); } catch (IdentityRecoveryException e) { - throw RecoveryUtil.buildInternalServerErrorResponse(PasswordRecoveryService.class.getName(), - Constants.SERVER_ERROR, e.getErrorCode(), Util.getCorrelation(), e); + throw RecoveryUtil.handleException(e, e.getErrorCode(), + Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, + Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); } } @@ -125,11 +126,12 @@ public Response recoverPassword(RecoveryRequest recoveryRequest) { return buildPasswordRecoveryResponse(tenantDomain, passwordRecoverDTO.getNotificationChannel(), passwordRecoverDTO); } catch (IdentityRecoveryClientException e) { - throw RecoveryUtil.handleClientExceptions(PasswordRecoveryService.class.getName(), tenantDomain, + throw RecoveryUtil.handleClientExceptions(tenantDomain, IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation(), e); } catch (IdentityRecoveryException e) { - throw RecoveryUtil.buildInternalServerErrorResponse(PasswordRecoveryService.class.getName(), - Constants.SERVER_ERROR, e.getErrorCode(), Util.getCorrelation(), e); + throw RecoveryUtil.handleException(e, e.getErrorCode(), + Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, + Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); } } @@ -149,11 +151,12 @@ public Response confirmRecovery(ConfirmRequest confirmRequest) { RecoveryUtil.buildPropertiesMap(confirmRequest.getProperties())); return Response.ok().entity(buildResetCodeResponse(tenantDomain, passwordResetCodeDTO)).build(); } catch (IdentityRecoveryClientException e) { - throw RecoveryUtil.handleClientExceptions(PasswordRecoveryService.class.getName(), tenantDomain, + throw RecoveryUtil.handleClientExceptions(tenantDomain, IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation(), e); } catch (IdentityRecoveryException e) { - throw RecoveryUtil.buildInternalServerErrorResponse(PasswordRecoveryService.class.getName(), - Constants.SERVER_ERROR, e.getErrorCode(), Util.getCorrelation(), e); + throw RecoveryUtil.handleException(e, e.getErrorCode(), + Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, + Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); } } @@ -176,12 +179,13 @@ public Response resetPassword(ResetRequest resetRequest) { return Response.ok().entity(buildPasswordResetResponse(successfulPasswordResetDTO)).build(); } catch (IdentityRecoveryClientException e) { // Send the reset code again for a retry attempt. - throw RecoveryUtil.handleClientExceptions(PasswordRecoveryService.class.getName(), tenantDomain, + throw RecoveryUtil.handleClientExceptions(tenantDomain, IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, resetRequest.getResetCode(), Util.getCorrelation(), e); } catch (IdentityRecoveryException e) { - throw RecoveryUtil.buildInternalServerErrorResponse(PasswordRecoveryService.class.getName(), - Constants.SERVER_ERROR, e.getErrorCode(), Util.getCorrelation(), e); + throw RecoveryUtil.handleException(e, e.getErrorCode(), + Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, + Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); } } @@ -209,11 +213,12 @@ public Response resendConfirmation(ResendConfirmationRequest resendConfirmationR } return buildResendConfirmationResponse(tenantDomain, resendConfirmationDTO); } catch (IdentityRecoveryClientException e) { - throw RecoveryUtil.handleClientExceptions(PasswordRecoveryService.class.getName(), tenantDomain, + throw RecoveryUtil.handleClientExceptions(tenantDomain, IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation(), e); } catch (IdentityRecoveryException e) { - throw RecoveryUtil.buildInternalServerErrorResponse(PasswordRecoveryService.class.getName(), - Constants.SERVER_ERROR, e.getErrorCode(), Util.getCorrelation(), e); + throw RecoveryUtil.handleException(e, e.getErrorCode(), + Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, + Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); } } diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java index 2e306601..9155915c 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java @@ -81,12 +81,12 @@ public Response initiateUsernameRecovery(InitRequest initRequest) { return Response.ok().entity(buildUsernameRecoveryInitResponse(recoveryInformationDTO, tenantDomain)) .build(); } catch (IdentityRecoveryClientException e) { - throw RecoveryUtil - .handleClientExceptions(UsernameRecoveryService.class.getName(), tenantDomain, - IdentityRecoveryConstants.USER_NAME_RECOVERY, Util.getCorrelation(), e); + throw RecoveryUtil.handleClientExceptions(tenantDomain, IdentityRecoveryConstants.USER_NAME_RECOVERY, + Util.getCorrelation(), e); } catch (IdentityRecoveryException e) { - throw RecoveryUtil.buildInternalServerErrorResponse(UsernameRecoveryService.class.getName(), - Constants.SERVER_ERROR, e.getErrorCode(), Util.getCorrelation(), e); + throw RecoveryUtil.handleException(e, e.getErrorCode(), + Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, + Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); } } @@ -115,12 +115,12 @@ public Response recoverUsername(RecoveryRequest recoveryRequest) { } return buildUsernameRecoveryResponse(usernameRecoverDTO.getNotificationChannel(), usernameRecoverDTO); } catch (IdentityRecoveryClientException e) { - throw RecoveryUtil - .handleClientExceptions(UsernameRecoveryService.class.getName(), tenantDomain, - IdentityRecoveryConstants.USER_NAME_RECOVERY, StringUtils.EMPTY, Util.getCorrelation(), e); + throw RecoveryUtil.handleClientExceptions(tenantDomain, IdentityRecoveryConstants.USER_NAME_RECOVERY, + StringUtils.EMPTY, Util.getCorrelation(), e); } catch (IdentityRecoveryException e) { - throw RecoveryUtil.buildInternalServerErrorResponse(UsernameRecoveryService.class.getName(), - Constants.SERVER_ERROR, e.getErrorCode(), Util.getCorrelation(), e); + throw RecoveryUtil.handleException(e, e.getErrorCode(), + Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, + Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); } } diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/BadRequestException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/BadRequestException.java deleted file mode 100644 index 2dfa4002..00000000 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/BadRequestException.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions; - -import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; -import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; - -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.Response; - -/** - * BadRequestException class. - */ -public class BadRequestException extends WebApplicationException { - - /** - * Exception message. - */ - private String message; - - /** - * Constructs a new exception from the ErrorDTO{@link ErrorResponse} object. - * - * @param errorResponse ErrorResponse{@link ErrorResponse} object holding the error code and the message - */ - public BadRequestException(ErrorResponse errorResponse) { - super(Response.status(Response.Status.BAD_REQUEST).entity(errorResponse) - .header(Constants.HEADER_CONTENT_TYPE, Constants.DEFAULT_RESPONSE_CONTENT_TYPE).build()); - message = errorResponse.getDescription(); - } - - /** - * Constructs a new exception instance. - */ - public BadRequestException() { - super(Response.Status.BAD_REQUEST); - } - - /** - * Get exception message. - * - * @return Exception message - */ - @Override - public String getMessage() { - return message; - } -} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ConflictException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ConflictException.java index beb0bf34..a66a410b 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ConflictException.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ConflictException.java @@ -18,8 +18,9 @@ package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions; +import org.wso2.carbon.identity.api.user.common.error.ErrorResponse; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; -import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; +//import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ForbiddenException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ForbiddenException.java index 86661e8e..4fe4b71f 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ForbiddenException.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ForbiddenException.java @@ -18,8 +18,9 @@ package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions; +import org.wso2.carbon.identity.api.user.common.error.ErrorResponse; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; -import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; +//import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/InternalServerErrorException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/InternalServerErrorException.java deleted file mode 100644 index 123a80f6..00000000 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/InternalServerErrorException.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions; - -import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; -import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; - -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.Response; - -/** - * InternalServerErrorException class. - */ -public class InternalServerErrorException extends WebApplicationException { - - /** - * Exception message. - */ - private String message; - - public InternalServerErrorException(Throwable e) { - super(e, Response.Status.INTERNAL_SERVER_ERROR); - } - - /** - * Constructs a new exception instance. - */ - public InternalServerErrorException() { - super(Response.Status.INTERNAL_SERVER_ERROR); - } - - public InternalServerErrorException(String message, Throwable e) { - super(message, e, Response.Status.INTERNAL_SERVER_ERROR); - } - - public InternalServerErrorException(String message) { - super(message, Response.Status.INTERNAL_SERVER_ERROR); - } - - /** - * Constructs a new exception from the ErrorDTO{@link ErrorResponse} object. - * - * @param errorResponse ErrorResponse{@link ErrorResponse} object holding the error code and the message - */ - public InternalServerErrorException(ErrorResponse errorResponse) { - - super(Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errorResponse) - .header(Constants.HEADER_CONTENT_TYPE, Constants.DEFAULT_RESPONSE_CONTENT_TYPE).build()); - } -} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotAcceptableException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotAcceptableException.java index ea2a0eec..25ec0a53 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotAcceptableException.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotAcceptableException.java @@ -18,8 +18,9 @@ package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions; +import org.wso2.carbon.identity.api.user.common.error.ErrorResponse; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; -import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; +//import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotFoundException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotFoundException.java index 1202b0a6..dfb373e0 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotFoundException.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotFoundException.java @@ -18,8 +18,9 @@ package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions; +import org.wso2.carbon.identity.api.user.common.error.ErrorResponse; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; -import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; +//import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/PreconditionFailedException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/PreconditionFailedException.java index 883dddb1..7757667f 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/PreconditionFailedException.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/PreconditionFailedException.java @@ -19,7 +19,7 @@ package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; -import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; +//import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RetryErrorResponse; import javax.ws.rs.WebApplicationException; @@ -40,12 +40,12 @@ public class PreconditionFailedException extends WebApplicationException { * * @param errorResponse ErrorResponse{@link ErrorResponse} object holding the error code and the message */ - public PreconditionFailedException(ErrorResponse errorResponse) { - - super(Response.status(Response.Status.PRECONDITION_FAILED).entity(errorResponse) - .header(Constants.HEADER_CONTENT_TYPE, Constants.DEFAULT_RESPONSE_CONTENT_TYPE).build()); - message = errorResponse.getDescription(); - } +// public PreconditionFailedException(ErrorResponse errorResponse) { +// +// super(Response.status(Response.Status.PRECONDITION_FAILED).entity(errorResponse) +// .header(Constants.HEADER_CONTENT_TYPE, Constants.DEFAULT_RESPONSE_CONTENT_TYPE).build()); +// message = errorResponse.getDescription(); +// } /** * Constructs a new exception from the RetryErrorDTO{@link RetryErrorResponse} object. diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java index 82fd19b3..1673d309 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java @@ -23,23 +23,23 @@ import org.apache.commons.logging.LogFactory; import org.wso2.carbon.identity.api.user.common.error.APIError; +import org.wso2.carbon.identity.api.user.common.error.ErrorResponse; import org.wso2.carbon.identity.core.ServiceURLBuilder; import org.wso2.carbon.identity.core.URLBuilderException; import org.wso2.carbon.identity.core.util.IdentityTenantUtil; import org.wso2.carbon.identity.core.util.IdentityUtil; import org.wso2.carbon.identity.recovery.IdentityRecoveryClientException; import org.wso2.carbon.identity.recovery.IdentityRecoveryConstants; +import org.wso2.carbon.identity.recovery.IdentityRecoveryException; import org.wso2.carbon.identity.recovery.dto.NotificationChannelDTO; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions.ConflictException; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions.ForbiddenException; -import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions.InternalServerErrorException; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions.NotAcceptableException; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions.NotFoundException; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions.PreconditionFailedException; import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.APICall; -import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.Property; import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RecoveryChannel; import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RetryErrorResponse; @@ -131,36 +131,33 @@ public static List buildRecoveryChannelInformation(Notification /** * Handle client errors with specific http codes. * - * @param className Class name * @param scenario Recovery scenario * @param exception IdentityRecoveryClientException * @return WebApplicationException (NOTE: Returns null when the client error is for no user available or for * multiple users available */ - public static WebApplicationException handleClientExceptions(String className, String tenantDomain, + public static WebApplicationException handleClientExceptions(String tenantDomain, String scenario, String correlationId, IdentityRecoveryClientException exception) { - return handleClientExceptions(className, tenantDomain, scenario, StringUtils.EMPTY, correlationId, exception); + return handleClientExceptions(tenantDomain, scenario, StringUtils.EMPTY, correlationId, exception); } /** * Handle client errors with specific http codes. * - * @param className Class name. * @param scenario Recovery scenario. * @param code Recovery code. * @param exception IdentityRecoveryClientException. * @return WebApplicationException (NOTE: Returns null when the client error is for no user available or for * multiple users available. */ - public static WebApplicationException handleClientExceptions(String className, String tenantDomain, String scenario, + public static WebApplicationException handleClientExceptions(String tenantDomain, String scenario, String code, String correlationId, IdentityRecoveryClientException exception) { if (StringUtils.isEmpty(exception.getErrorCode())) { - return buildConflictRequestResponseObject(className, exception.getMessage(), exception.getErrorCode(), - correlationId); + return buildConflictRequestResponseObject(exception, exception.getMessage(), exception.getErrorCode()); } String errorCode = prependOperationScenarioToErrorCode(exception.getErrorCode(), scenario); @@ -170,8 +167,7 @@ public static WebApplicationException handleClientExceptions(String className, S // Throw errors according to exception category. switch (errorCategory) { case FORBIDDEN_ERROR_CATEGORY: - return buildForbiddenRequestResponseObject(className, exception.getMessage(), errorCode, - correlationId); + return buildForbiddenRequestResponseObject(exception, exception.getMessage(), errorCode); case CONFLICT_REQUEST_ERROR_CATEGORY: if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_MULTIPLE_MATCHING_USERS.getCode() .equals(errorCode)) { @@ -181,8 +177,8 @@ public static WebApplicationException handleClientExceptions(String className, S return new WebApplicationException(Response.accepted().build()); } } - return buildConflictRequestResponseObject(className, exception.getMessage(), - exception.getErrorCode(), correlationId); + return buildConflictRequestResponseObject(exception, exception.getMessage(), + exception.getErrorCode()); case REQUEST_NOT_FOUND_ERROR_CATEGORY: if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_USER_FOUND.getCode().equals(errorCode)) { // If user notify is not enabled, throw a accepted response. @@ -191,48 +187,20 @@ public static WebApplicationException handleClientExceptions(String className, S return new WebApplicationException(Response.accepted().build()); } } - return buildRequestNotFoundResponseObject(className, exception.getMessage(), errorCode, - correlationId); + return buildRequestNotFoundResponseObject(exception, errorCode, exception.getMessage()); case REQUEST_NOT_ACCEPTABLE_ERROR_CATEGORY: - return buildRequestNotAcceptableResponseObject(className, exception.getMessage(), errorCode, - correlationId); + return buildRequestNotAcceptableResponseObject(exception, errorCode, exception.getMessage()); case RETRY_ERROR_CATEGORY: - return buildRetryPasswordResetObject(className, tenantDomain, exception.getMessage(), errorCode, + return buildRetryPasswordResetObject(tenantDomain, exception.getMessage(), errorCode, code, correlationId); default: - return buildConflictRequestResponseObject(className, exception.getMessage(), errorCode, - correlationId); + return buildConflictRequestResponseObject(exception, exception.getMessage(), errorCode); } } else { - return buildConflictRequestResponseObject(className, exception.getMessage(), errorCode, correlationId); + return buildConflictRequestResponseObject(exception, exception.getMessage(), errorCode); } } - /** - * Logs the error, builds a internalServerErrorException with specified details and throws it. - * - * @param className Class name. - * @param message Error message. - * @param code Error code. - * @param correlationId Correlation Id. - * @param throwable Error. - * @return WebApplicationException. - */ - public static WebApplicationException buildInternalServerErrorResponse(String className, String message, - String code, String correlationId, - Throwable throwable) { - - if (StringUtils.isNotBlank(className)) { - message = String.format("%s : %s - %s", LOG_MESSAGE_PREFIX, className, message); - } - if (throwable == null) { - log.error(message); - } else { - log.error(message, throwable); - } - return buildInternalServerError(code, correlationId); - } - /** * Build API call information. * @@ -270,7 +238,7 @@ public static String buildURIForBody(String tenantDomain, String endpoint, Strin url = ServiceURLBuilder.create().addPath(context).build().getRelativePublicURL(); } catch (URLBuilderException e) { String errorDescription = "Server encountered an error while building URL for response body."; - org.wso2.carbon.identity.api.user.common.error.ErrorResponse errorResponse = + ErrorResponse errorResponse = new org.wso2.carbon.identity.api.user.common.error.ErrorResponse.Builder() .withCode(UNEXPECTED_SERVER_ERROR.getCode()) .withMessage("Error while building response.") @@ -305,41 +273,33 @@ private static String getContext(String tenantDomain, String endpoint, String ba /** * Returns a new InternalServerErrorException. * - * @param code Code - * @param correlationId Correlation Id * @return A new InternalServerErrorException with default details as a response */ - private static InternalServerErrorException buildInternalServerError(String code, String correlationId) { + public static APIError handleException(IdentityRecoveryException e, String errorCode, String errorMessage, + String errorDescription, Response.Status status) { - ErrorResponse errorResponse = buildErrorResponse(Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, code, - Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, correlationId); - return new InternalServerErrorException(errorResponse); + ErrorResponse errorResponse = buildErrorResponse(e, errorCode, errorMessage, errorDescription); + return new APIError(status, errorResponse); } - /** - * Returns a generic error response. - * - * @param code Error code - * @param message Specifies the error message - * @param description Error description - * @param correlationId CorrelationID - * @return A generic error with the specified details - */ - private static ErrorResponse buildErrorResponse(String message, String code, String description, - String correlationId) { - - ErrorResponse errorResponse = new ErrorResponse(); - errorResponse.setCode(code); - errorResponse.setMessage(message); - errorResponse.setDescription(description); - errorResponse.setTraceId(correlationId); + private static ErrorResponse buildErrorResponse(IdentityRecoveryException e, String errorCode, String errorMessage, + String errorDescription) { + + ErrorResponse errorResponse = getErrorBuilder(errorCode, errorMessage, errorDescription).build(log, e, + errorMessage); return errorResponse; } + private static ErrorResponse.Builder getErrorBuilder(String errorCode, String errorMsg, String errorDescription) { + + return new ErrorResponse.Builder().withCode(errorCode) + .withMessage(errorMsg) + .withDescription(errorDescription); + } + /** * Returns a new PreconditionFailedException. * - * @param className Class name * @param tenantDomain Tenant domain * @param description Description of the exception * @param code Error code @@ -347,9 +307,9 @@ private static ErrorResponse buildErrorResponse(String message, String code, Str * @param correlationId Correlation Id * @return A new PreconditionFailedException with the specified details as a response */ - private static PreconditionFailedException buildRetryPasswordResetObject(String className, String tenantDomain, - String description, String code, - String resetCode, String correlationId) { + private static PreconditionFailedException buildRetryPasswordResetObject(String tenantDomain, String description, + String code, String resetCode, + String correlationId) { // Build next API calls. ArrayList apiCallsArrayList = new ArrayList<>(); @@ -360,9 +320,6 @@ private static PreconditionFailedException buildRetryPasswordResetObject(String RetryErrorResponse retryErrorResponse = buildRetryErrorResponse( Constants.STATUS_PRECONDITION_FAILED_MESSAGE_DEFAULT, code, description, resetCode, correlationId, apiCallsArrayList); - if (StringUtils.isNotBlank(className)) { - description = String.format("%s : %s - %s", LOG_MESSAGE_PREFIX, className, description); - } log.error(description); return new PreconditionFailedException(retryErrorResponse); } @@ -401,15 +358,11 @@ private static RetryErrorResponse buildRetryErrorResponse(String message, String * @param correlationId Correlation Id * @return A new NotAcceptableException with the specified details as a response */ - private static NotAcceptableException buildRequestNotAcceptableResponseObject(String className, String description, - String code, String correlationId) { + private static NotAcceptableException buildRequestNotAcceptableResponseObject(IdentityRecoveryException e, + String code, String description) { - ErrorResponse errorResponse = buildErrorResponse(Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, code, - description, correlationId); - if (StringUtils.isNotBlank(className)) { - description = String.format("%s : %s - %s", LOG_MESSAGE_PREFIX, className, description); - } - log.error(description); + ErrorResponse errorResponse = buildErrorResponse(e, code, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, + description); return new NotAcceptableException(errorResponse); } @@ -422,15 +375,11 @@ private static NotAcceptableException buildRequestNotAcceptableResponseObject(St * @param correlationId Correlation Id * @return A new NotAcceptableException with the specified details as a response */ - private static NotFoundException buildRequestNotFoundResponseObject(String className, String description, - String code, String correlationId) { + private static NotFoundException buildRequestNotFoundResponseObject(IdentityRecoveryException e, String code, + String description) { - ErrorResponse errorResponse = buildErrorResponse(Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, code, - description, correlationId); - if (StringUtils.isNotBlank(className)) { - description = String.format("%s : %s - %s", LOG_MESSAGE_PREFIX, className, description); - } - log.error(description); + ErrorResponse errorResponse = buildErrorResponse(e, code, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + description); return new NotFoundException(errorResponse); } @@ -443,16 +392,11 @@ private static NotFoundException buildRequestNotFoundResponseObject(String class * @param correlationId CorrelationId * @return A new ConflictException with the specified details as a response */ - private static ConflictException buildConflictRequestResponseObject(String className, String description, - String code, String correlationId) { - - ErrorResponse errorResponse = buildErrorResponse(Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, code, - description, correlationId); - if (StringUtils.isNotBlank(className)) { - description = String.format("CorrelationId: %s : %s : %s - %s", correlationId, LOG_MESSAGE_PREFIX, - className, description); - } - log.error(description); + private static ConflictException buildConflictRequestResponseObject(IdentityRecoveryException e, String description, + String code) { + + ErrorResponse errorResponse = buildErrorResponse(e, code, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + description); return new ConflictException(errorResponse); } @@ -465,15 +409,11 @@ private static ConflictException buildConflictRequestResponseObject(String class * @param correlationId CorrelationId * @return A new ForbiddenException with the specified details as a response */ - private static ForbiddenException buildForbiddenRequestResponseObject(String className, String description, - String code, String correlationId) { + private static ForbiddenException buildForbiddenRequestResponseObject(IdentityRecoveryException e, + String description, String code) { - ErrorResponse errorResponse = buildErrorResponse(Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, code, - description, correlationId); - if (StringUtils.isNotBlank(className)) { - description = String.format("%s : %s - %s", LOG_MESSAGE_PREFIX, className, description); - } - log.error(description); + ErrorResponse errorResponse = buildErrorResponse(e, code, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, + description); return new ForbiddenException(errorResponse); } From ec6f98ed22d918c11e45bab39f16b89ddc935101 Mon Sep 17 00:00:00 2001 From: Rashmini Date: Mon, 18 Sep 2023 09:38:48 +0530 Subject: [PATCH 06/17] Update comments and fix formatting issues --- .../core/exceptions/ConflictException.java | 1 - .../core/exceptions/ForbiddenException.java | 1 - .../exceptions/NotAcceptableException.java | 1 - .../core/exceptions/NotFoundException.java | 1 - .../PreconditionFailedException.java | 13 -- .../v2/impl/core/utils/RecoveryUtil.java | 125 ++++++++++-------- 6 files changed, 72 insertions(+), 70 deletions(-) diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ConflictException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ConflictException.java index a66a410b..465b4d9a 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ConflictException.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ConflictException.java @@ -20,7 +20,6 @@ import org.wso2.carbon.identity.api.user.common.error.ErrorResponse; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; -//import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ForbiddenException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ForbiddenException.java index 4fe4b71f..ab0ed0d8 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ForbiddenException.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ForbiddenException.java @@ -20,7 +20,6 @@ import org.wso2.carbon.identity.api.user.common.error.ErrorResponse; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; -//import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotAcceptableException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotAcceptableException.java index 25ec0a53..f947ec81 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotAcceptableException.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotAcceptableException.java @@ -20,7 +20,6 @@ import org.wso2.carbon.identity.api.user.common.error.ErrorResponse; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; -//import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotFoundException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotFoundException.java index dfb373e0..84e6529e 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotFoundException.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotFoundException.java @@ -20,7 +20,6 @@ import org.wso2.carbon.identity.api.user.common.error.ErrorResponse; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; -//import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/PreconditionFailedException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/PreconditionFailedException.java index 7757667f..26e6b8e6 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/PreconditionFailedException.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/PreconditionFailedException.java @@ -19,7 +19,6 @@ package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; -//import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.ErrorResponse; import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.RetryErrorResponse; import javax.ws.rs.WebApplicationException; @@ -35,18 +34,6 @@ public class PreconditionFailedException extends WebApplicationException { */ private String message; - /** - * Constructs a new exception from the ErrorDTO{@link ErrorResponse} object. - * - * @param errorResponse ErrorResponse{@link ErrorResponse} object holding the error code and the message - */ -// public PreconditionFailedException(ErrorResponse errorResponse) { -// -// super(Response.status(Response.Status.PRECONDITION_FAILED).entity(errorResponse) -// .header(Constants.HEADER_CONTENT_TYPE, Constants.DEFAULT_RESPONSE_CONTENT_TYPE).build()); -// message = errorResponse.getDescription(); -// } - /** * Constructs a new exception from the RetryErrorDTO{@link RetryErrorResponse} object. * diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java index 1673d309..3e303027 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java @@ -73,8 +73,8 @@ public class RecoveryUtil { /** * Converts a list of UserClaim in to a UserClaim array. * - * @param userClaimsList UserClaims List - * @return Map of user claims + * @param userClaimsList UserClaims List. + * @return Map of user claims. */ public static HashMap buildUserClaimsMap(List userClaimsList) { @@ -88,8 +88,8 @@ public static HashMap buildUserClaimsMap(List userCla /** * Convert the list of Properties in to an array. * - * @param propertyList List of {@link Property} objects - * @return Map of properties + * @param propertyList List of {@link Property} objects. + * @return Map of properties. */ public static HashMap buildPropertiesMap(List propertyList) { @@ -106,8 +106,8 @@ public static HashMap buildPropertiesMap(List property /** * Build the channel response object list. * - * @param channels Available notification channels list as objects of {@link NotificationChannelDTO} - * @return List of RecoveryChannels {@link RecoveryChannel} + * @param channels Available notification channels list as objects of {@link NotificationChannelDTO}. + * @return List of RecoveryChannels {@link RecoveryChannel}. */ public static List buildRecoveryChannelInformation(NotificationChannelDTO[] channels) { @@ -131,10 +131,10 @@ public static List buildRecoveryChannelInformation(Notification /** * Handle client errors with specific http codes. * - * @param scenario Recovery scenario - * @param exception IdentityRecoveryClientException + * @param scenario Recovery scenario. + * @param exception IdentityRecoveryClientException. * @return WebApplicationException (NOTE: Returns null when the client error is for no user available or for - * multiple users available + * multiple users available. */ public static WebApplicationException handleClientExceptions(String tenantDomain, String scenario, String correlationId, @@ -251,6 +251,23 @@ public static String buildURIForBody(String tenantDomain, String endpoint, Strin return url; } + /** + * Builds API error to be thrown. + * + * @param e Identity Recovery Exception. + * @param errorCode Error code. + * @param errorMessage Error message. + * @param errorDescription Error description. + * @param status HTTP status. + * @return APIError object which contains the error description. + */ + public static APIError handleException(IdentityRecoveryException e, String errorCode, String errorMessage, + String errorDescription, Response.Status status) { + + ErrorResponse errorResponse = buildErrorResponse(e, errorCode, errorMessage, errorDescription); + return new APIError(status, errorResponse); + } + /** * Builds the API context on whether the tenant qualified url is enabled or not. In tenant qualified mode the * ServiceURLBuilder appends the tenant domain to the URI as a path param automatically. But @@ -271,17 +288,14 @@ private static String getContext(String tenantDomain, String endpoint, String ba } /** - * Returns a new InternalServerErrorException. + * Builds error response. * - * @return A new InternalServerErrorException with default details as a response + * @param e Identity Recovery Exception. + * @param errorCode Error code. + * @param errorMessage Error message. + * @param errorDescription Error description. + * @return ErrorResponse. */ - public static APIError handleException(IdentityRecoveryException e, String errorCode, String errorMessage, - String errorDescription, Response.Status status) { - - ErrorResponse errorResponse = buildErrorResponse(e, errorCode, errorMessage, errorDescription); - return new APIError(status, errorResponse); - } - private static ErrorResponse buildErrorResponse(IdentityRecoveryException e, String errorCode, String errorMessage, String errorDescription) { @@ -290,22 +304,31 @@ private static ErrorResponse buildErrorResponse(IdentityRecoveryException e, Str return errorResponse; } - private static ErrorResponse.Builder getErrorBuilder(String errorCode, String errorMsg, String errorDescription) { + /** + * Get ErrorResponse Builder + * + * @param errorCode Error code. + * @param errorMessage Error message. + * @param errorDescription Error description. + * @return ErrorResponse.Builder. + */ + private static ErrorResponse.Builder getErrorBuilder(String errorCode, String errorMessage, + String errorDescription) { return new ErrorResponse.Builder().withCode(errorCode) - .withMessage(errorMsg) + .withMessage(errorMessage) .withDescription(errorDescription); } /** * Returns a new PreconditionFailedException. * - * @param tenantDomain Tenant domain - * @param description Description of the exception - * @param code Error code - * @param resetCode Reset code given to the user by confirmation API - * @param correlationId Correlation Id - * @return A new PreconditionFailedException with the specified details as a response + * @param tenantDomain Tenant domain. + * @param description Description of the exception. + * @param code Error code. + * @param resetCode Reset code given to the user by confirmation API. + * @param correlationId Correlation Id. + * @return A new PreconditionFailedException with the specified details as a response. */ private static PreconditionFailedException buildRetryPasswordResetObject(String tenantDomain, String description, String code, String resetCode, @@ -327,13 +350,13 @@ private static PreconditionFailedException buildRetryPasswordResetObject(String /** * Build the RetryErrorResponse for not valid password scenario. * - * @param message Error message - * @param description Error description - * @param code Error code - * @param resetCode Password reset code - * @param correlationId Trace Id - * @param apiCallsArrayList Available APIs - * @return RetryErrorResponse + * @param message Error message. + * @param description Error description. + * @param code Error code. + * @param resetCode Password reset code. + * @param correlationId Trace Id. + * @param apiCallsArrayList Available APIs. + * @return RetryErrorResponse. */ private static RetryErrorResponse buildRetryErrorResponse(String message, String description, String code, String resetCode, String correlationId, @@ -352,11 +375,10 @@ private static RetryErrorResponse buildRetryErrorResponse(String message, String /** * Returns a new NotAcceptableException. * - * @param className Class name - * @param description Description of the exception - * @param code Error code - * @param correlationId Correlation Id - * @return A new NotAcceptableException with the specified details as a response + * @param e IdentityRecoveryException. + * @param code Error code. + * @param description Description of the exception. + * @return A new NotAcceptableException with the specified details as a response. */ private static NotAcceptableException buildRequestNotAcceptableResponseObject(IdentityRecoveryException e, String code, String description) { @@ -369,11 +391,10 @@ private static NotAcceptableException buildRequestNotAcceptableResponseObject(Id /** * Returns a new NotAcceptableException. * - * @param className Class name - * @param description Description of the exception - * @param code Error code - * @param correlationId Correlation Id - * @return A new NotAcceptableException with the specified details as a response + * @param e IdentityRecoveryException. + * @param code Error code. + * @param description Description of the exception. + * @return A new NotAcceptableException with the specified details as a response. */ private static NotFoundException buildRequestNotFoundResponseObject(IdentityRecoveryException e, String code, String description) { @@ -386,10 +407,9 @@ private static NotFoundException buildRequestNotFoundResponseObject(IdentityReco /** * Returns a new ConflictException. * - * @param className Classname + * @param e IdentityRecoveryException. * @param description Description of the exception * @param code Error code - * @param correlationId CorrelationId * @return A new ConflictException with the specified details as a response */ private static ConflictException buildConflictRequestResponseObject(IdentityRecoveryException e, String description, @@ -403,11 +423,10 @@ private static ConflictException buildConflictRequestResponseObject(IdentityReco /** * Returns a new ForbiddenException. * - * @param className Class name - * @param description Description of the exception - * @param code Error code - * @param correlationId CorrelationId - * @return A new ForbiddenException with the specified details as a response + * @param e IdentityRecoveryException. + * @param description Description of the exception. + * @param code Error code. + * @return A new ForbiddenException with the specified details as a response. */ private static ForbiddenException buildForbiddenRequestResponseObject(IdentityRecoveryException e, String description, String code) { @@ -422,8 +441,8 @@ private static ForbiddenException buildForbiddenRequestResponseObject(IdentityRe * (Eg: USR-20045) * * @param exceptionErrorCode Existing error code. - * @param scenario Operation scenario - * @return New error code with the scenario prepended + * @param scenario Operation scenario. + * @return New error code with the scenario prepended. */ private static String prependOperationScenarioToErrorCode(String exceptionErrorCode, String scenario) { @@ -442,7 +461,7 @@ private static String prependOperationScenarioToErrorCode(String exceptionErrorC /** * Generate the map which categorizes the exceptions for different http error groups. * - * @return Grouped client error map + * @return Grouped client error map. */ private static HashMap generateClientErrorMap() { From 8fcb4f9e9a0a03c22b2c5f59a8e543fafc47aff7 Mon Sep 17 00:00:00 2001 From: Rashmini Date: Mon, 18 Sep 2023 09:44:45 +0530 Subject: [PATCH 07/17] Bump component version --- .../org.wso2.carbon.identity.rest.api.user.recovery.v2/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/pom.xml b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/pom.xml index bfdfba89..c3365450 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/pom.xml +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.api.user.recovery org.wso2.carbon.identity.user.api - 1.3.19-SNAPSHOT + 1.3.20-SNAPSHOT ../pom.xml 4.0.0 From d5419aabc898110152ca8a268b1e84a5aa519ac7 Mon Sep 17 00:00:00 2001 From: Rashmini Date: Mon, 18 Sep 2023 10:33:28 +0530 Subject: [PATCH 08/17] Move APICall enum to a separate class --- .../user/recovery/v2/impl/core/APICalls.java | 83 +++++++++++++++++++ .../user/recovery/v2/impl/core/Constants.java | 64 -------------- .../v2/impl/core/PasswordRecoveryService.java | 28 +++---- .../v2/impl/core/UsernameRecoveryService.java | 4 +- .../v2/impl/core/utils/RecoveryUtil.java | 5 +- 5 files changed, 102 insertions(+), 82 deletions(-) create mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/APICalls.java diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/APICalls.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/APICalls.java new file mode 100644 index 00000000..109005ca --- /dev/null +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/APICalls.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core; + +/** + * Enum contains the recovery api names and the corresponding urls. + */ +public enum APICalls { + + INITIATE_USERNAME_RECOVERY_API("POST", "initiate_username_recovery", + "/recovery/username/init"), + INITIATE_PASSWORD_RECOVERY_API("POST", "initiate_password_recovery", + "/recovery/password/init"), + RECOVER_USERNAME_API("POST", "recover_username", + "/recovery/username/recover"), + RECOVER_PASSWORD_API("POST", "recover_password", + "/recovery/password/recover"), + CONFIRM_PASSWORD_RECOVERY_API("POST", "confirm_password_recovery", + "/recovery/password/confirm"), + RESET_PASSWORD_API("POST", "reset_password", + "/recovery/password/reset"), + RESEND_CONFIRMATION_API("POST", "resend_confirmation", + "/recovery/password/resend"), + RECOVER_WITH_SECURITY_QUESTIONS_API("GET", "security_questions_api", + "/security-question?username=%s"); + + /** + * Name of the API. + */ + private final String apiName; + + /** + * Url of the API. + */ + private final String apiUrl; + + /** + * Http method call. + */ + private String type; + + APICalls(String type, String apiName, String apiUrl) { + + this.type = type; + this.apiName = apiName; + this.apiUrl = apiUrl; + } + + /** + * Get http method type. + * + * @return Get http method type + */ + public String getType() { + return type; + } + + /** + * Get the url of the API. + * + * @return API url + */ + public String getApiUrl() { + + return apiUrl; + } +} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/Constants.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/Constants.java index 061aae10..dde101bf 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/Constants.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/Constants.java @@ -54,68 +54,4 @@ public static class RelationStates { public static final String NEXT_REL = "next"; public static final String RESEND_REL = "resend"; } - - /** - * Enum contains the recovery api names and the corresponding urls. - */ - public enum APICall { - - INITIATE_USERNAME_RECOVERY_API("POST", "initiate_username_recovery", - "/recovery/username/init"), - INITIATE_PASSWORD_RECOVERY_API("POST", "initiate_password_recovery", - "/recovery/password/init"), - RECOVER_USERNAME_API("POST", "recover_username", - "/recovery/username/recover"), - RECOVER_PASSWORD_API("POST", "recover_password", - "/recovery/password/recover"), - CONFIRM_PASSWORD_RECOVERY_API("POST", "confirm_password_recovery", - "/recovery/password/confirm"), - RESET_PASSWORD_API("POST", "reset_password", - "/recovery/password/reset"), - RESEND_CONFIRMATION_API("POST", "resend_confirmation", - "/recovery/password/resend"), - RECOVER_WITH_SECURITY_QUESTIONS_API("GET", "security_questions_api", - "/security-question?username=%s"); - - /** - * Name of the API. - */ - private final String apiName; - - /** - * Url of the API. - */ - private final String apiUrl; - - /** - * Http method call. - */ - private String type; - - APICall(String type, String apiName, String apiUrl) { - - this.type = type; - this.apiName = apiName; - this.apiUrl = apiUrl; - } - - /** - * Get http method type. - * - * @return Get http method type - */ - public String getType() { - return type; - } - - /** - * Get the url of the API. - * - * @return API url - */ - public String getApiUrl() { - - return apiUrl; - } - } } diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java index 7379be8b..4cf3ce3e 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java @@ -234,14 +234,14 @@ private Response buildResendConfirmationResponse(String tenantDomain, ArrayList apiCallsArrayList = new ArrayList<>(); // Add confirm API call information. - apiCallsArrayList.add(RecoveryUtil.buildApiCall(Constants.APICall.CONFIRM_PASSWORD_RECOVERY_API.getType(), + apiCallsArrayList.add(RecoveryUtil.buildApiCall(APICalls.CONFIRM_PASSWORD_RECOVERY_API.getType(), Constants.RelationStates.NEXT_REL, RecoveryUtil - .buildURIForBody(tenantDomain, Constants.APICall.CONFIRM_PASSWORD_RECOVERY_API.getApiUrl(), + .buildURIForBody(tenantDomain, APICalls.CONFIRM_PASSWORD_RECOVERY_API.getApiUrl(), Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); // Add resend confirmation code API call information. - apiCallsArrayList.add(RecoveryUtil.buildApiCall(Constants.APICall.RESEND_CONFIRMATION_API.getType(), + apiCallsArrayList.add(RecoveryUtil.buildApiCall(APICalls.RESEND_CONFIRMATION_API.getType(), Constants.RelationStates.RESEND_REL, RecoveryUtil - .buildURIForBody(tenantDomain, Constants.APICall.RESEND_CONFIRMATION_API.getApiUrl(), + .buildURIForBody(tenantDomain, APICalls.RESEND_CONFIRMATION_API.getApiUrl(), Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); if (NotificationChannels.EXTERNAL_CHANNEL.getChannelType() .equals(resendConfirmationDTO.getNotificationChannel())) { @@ -299,8 +299,8 @@ private ResetCodeResponse buildResetCodeResponse(String tenantDomain, // Build next API calls list. ArrayList apiCallsArrayList = new ArrayList<>(); apiCallsArrayList.add(RecoveryUtil - .buildApiCall(Constants.APICall.RESET_PASSWORD_API.getType(), Constants.RelationStates.NEXT_REL, - RecoveryUtil.buildURIForBody(tenantDomain, Constants.APICall.RESET_PASSWORD_API.getApiUrl(), + .buildApiCall(APICalls.RESET_PASSWORD_API.getType(), Constants.RelationStates.NEXT_REL, + RecoveryUtil.buildURIForBody(tenantDomain, APICalls.RESET_PASSWORD_API.getApiUrl(), Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); ResetCodeResponse resetCodeResponseDTO = new ResetCodeResponse(); resetCodeResponseDTO.setResetCode(passwordResetCodeDTO.getPasswordResetCode()); @@ -321,14 +321,14 @@ private Response buildPasswordRecoveryResponse(String tenantDomain, String notif // Build next API calls. ArrayList apiCallsArrayList = new ArrayList<>(); - apiCallsArrayList.add(RecoveryUtil.buildApiCall(Constants.APICall.CONFIRM_PASSWORD_RECOVERY_API.getType(), + apiCallsArrayList.add(RecoveryUtil.buildApiCall(APICalls.CONFIRM_PASSWORD_RECOVERY_API.getType(), Constants.RelationStates.NEXT_REL, RecoveryUtil - .buildURIForBody(tenantDomain, Constants.APICall.CONFIRM_PASSWORD_RECOVERY_API.getApiUrl(), + .buildURIForBody(tenantDomain, APICalls.CONFIRM_PASSWORD_RECOVERY_API.getApiUrl(), Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); // Add resend confirmation code API call information. - apiCallsArrayList.add(RecoveryUtil.buildApiCall(Constants.APICall.RESEND_CONFIRMATION_API.getType(), + apiCallsArrayList.add(RecoveryUtil.buildApiCall(APICalls.RESEND_CONFIRMATION_API.getType(), Constants.RelationStates.RESEND_REL, RecoveryUtil - .buildURIForBody(tenantDomain, Constants.APICall.RESEND_CONFIRMATION_API.getApiUrl(), + .buildURIForBody(tenantDomain, APICalls.RESEND_CONFIRMATION_API.getApiUrl(), Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); if (NotificationChannels.EXTERNAL_CHANNEL.getChannelType().equals(notificationChannel)) { return Response.ok() @@ -438,9 +438,9 @@ private List buildPasswordRecoveryInitResponse(String tenan String recoveryFlowId = recoveryInformationDTO.getRecoveryFlowId(); // Build next API calls list. ArrayList apiCallsArrayList = new ArrayList<>(); - apiCallsArrayList.add(RecoveryUtil.buildApiCall(Constants.APICall.RECOVER_PASSWORD_API.getType(), + apiCallsArrayList.add(RecoveryUtil.buildApiCall(APICalls.RECOVER_PASSWORD_API.getType(), Constants.RelationStates.NEXT_REL, RecoveryUtil - .buildURIForBody(tenantDomain, Constants.APICall.RECOVER_PASSWORD_API.getApiUrl(), + .buildURIForBody(tenantDomain, APICalls.RECOVER_PASSWORD_API.getApiUrl(), Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); RecoveryChannelInformation recoveryChannelInformation = buildRecoveryChannelInformation( recoveryInformationDTO); @@ -453,9 +453,9 @@ private List buildPasswordRecoveryInitResponse(String tenan // Build next API calls list. ArrayList apiCallsArrayList = new ArrayList<>(); apiCallsArrayList.add(RecoveryUtil - .buildApiCall(Constants.APICall.RECOVER_WITH_SECURITY_QUESTIONS_API.getType(), + .buildApiCall(APICalls.RECOVER_WITH_SECURITY_QUESTIONS_API.getType(), Constants.RelationStates.NEXT_REL, RecoveryUtil.buildURIForBody(tenantDomain, - Constants.APICall.RECOVER_WITH_SECURITY_QUESTIONS_API.getApiUrl(), + APICalls.RECOVER_WITH_SECURITY_QUESTIONS_API.getApiUrl(), Constants.CHALLENGE_QUESTIONS_ENDPOINT_BASEPATH), recoveryInformationDTO.getUsername())); // Build recovery information for recover with security questions. diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java index 9155915c..fe347490 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java @@ -166,8 +166,8 @@ private List buildUsernameRecoveryInitResponse( // Build next API calls. ArrayList apiCallsArrayList = new ArrayList<>(); apiCallsArrayList.add(RecoveryUtil - .buildApiCall(Constants.APICall.RECOVER_USERNAME_API.getType(), Constants.RelationStates.NEXT_REL, - RecoveryUtil.buildURIForBody(tenantDomain, Constants.APICall.RECOVER_USERNAME_API.getApiUrl(), + .buildApiCall(APICalls.RECOVER_USERNAME_API.getType(), Constants.RelationStates.NEXT_REL, + RecoveryUtil.buildURIForBody(tenantDomain, APICalls.RECOVER_USERNAME_API.getApiUrl(), Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); // Build recovery type information. AccountRecoveryType accountRecoveryType = new AccountRecoveryType(); diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java index 3e303027..40218f55 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java @@ -32,6 +32,7 @@ import org.wso2.carbon.identity.recovery.IdentityRecoveryConstants; import org.wso2.carbon.identity.recovery.IdentityRecoveryException; import org.wso2.carbon.identity.recovery.dto.NotificationChannelDTO; +import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.APICalls; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions.ConflictException; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions.ForbiddenException; @@ -337,8 +338,8 @@ private static PreconditionFailedException buildRetryPasswordResetObject(String // Build next API calls. ArrayList apiCallsArrayList = new ArrayList<>(); apiCallsArrayList.add(RecoveryUtil - .buildApiCall(Constants.APICall.RESET_PASSWORD_API.getType(), Constants.RelationStates.NEXT_REL, - buildURIForBody(tenantDomain, Constants.APICall.RESET_PASSWORD_API.getApiUrl(), + .buildApiCall(APICalls.RESET_PASSWORD_API.getType(), Constants.RelationStates.NEXT_REL, + buildURIForBody(tenantDomain, APICalls.RESET_PASSWORD_API.getApiUrl(), Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); RetryErrorResponse retryErrorResponse = buildRetryErrorResponse( Constants.STATUS_PRECONDITION_FAILED_MESSAGE_DEFAULT, code, description, resetCode, correlationId, From 9817f1c6420aa1968231957e9f3114ec2253b03b Mon Sep 17 00:00:00 2001 From: Rashmini Date: Mon, 18 Sep 2023 13:09:04 +0530 Subject: [PATCH 09/17] Fix comments --- .../v2/impl/core/PasswordRecoveryService.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java index 4cf3ce3e..b1d57266 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java @@ -72,6 +72,9 @@ public class PasswordRecoveryService { */ public Response initiatePasswordRecovery(InitRequest initRequest) { + if (initRequest == null) { + return Response.status(Response.Status.BAD_REQUEST).build(); + } String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); Map userClaims = RecoveryUtil.buildUserClaimsMap(initRequest.getClaims()); try { @@ -79,14 +82,6 @@ public Response initiatePasswordRecovery(InitRequest initRequest) { RecoveryInformationDTO recoveryInformationDTO = UserAccountRecoveryServiceDataHolder.getPasswordRecoveryManager().initiate(userClaims, tenantDomain, RecoveryUtil.buildPropertiesMap(initRequest.getProperties())); - // If RecoveryChannelInfoDTO is null throw not found error. - if (recoveryInformationDTO == null) { - if (LOG.isDebugEnabled()) { - String message = "No recovery information for password recovery request"; - LOG.debug(message); - } - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); - } return Response.ok().entity(buildPasswordRecoveryInitResponse(tenantDomain, recoveryInformationDTO)) .build(); } catch (IdentityRecoveryClientException e) { @@ -108,6 +103,9 @@ public Response initiatePasswordRecovery(InitRequest initRequest) { */ public Response recoverPassword(RecoveryRequest recoveryRequest) { + if (recoveryRequest == null) { + return Response.status(Response.Status.BAD_REQUEST).build(); + } String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); String recoveryId = recoveryRequest.getRecoveryCode(); String channelId = recoveryRequest.getChannelId(); @@ -143,6 +141,9 @@ public Response recoverPassword(RecoveryRequest recoveryRequest) { */ public Response confirmRecovery(ConfirmRequest confirmRequest) { + if (confirmRequest == null) { + return Response.status(Response.Status.BAD_REQUEST).build(); + } String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); try { PasswordResetCodeDTO passwordResetCodeDTO = @@ -169,6 +170,9 @@ public Response confirmRecovery(ConfirmRequest confirmRequest) { */ public Response resetPassword(ResetRequest resetRequest) { + if (resetRequest == null) { + return Response.status(Response.Status.BAD_REQUEST).build(); + } String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); char[] password = resetRequest.getPassword().toCharArray(); try { @@ -198,6 +202,9 @@ public Response resetPassword(ResetRequest resetRequest) { */ public Response resendConfirmation(ResendConfirmationRequest resendConfirmationRequest) { + if (resendConfirmationRequest == null) { + return Response.status(Response.Status.BAD_REQUEST).build(); + } String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); String resendCode = resendConfirmationRequest.getResendCode(); Map properties = RecoveryUtil.buildPropertiesMap(resendConfirmationRequest.getProperties()); From 418d50cd1c7cac91ee67bfe3b49914657ed1f14c Mon Sep 17 00:00:00 2001 From: Rashmini Date: Wed, 20 Sep 2023 10:10:13 +0530 Subject: [PATCH 10/17] Bump identity-governance version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fca748a1..a3c3a21b 100644 --- a/pom.xml +++ b/pom.xml @@ -421,7 +421,7 @@ 1.4 1.2.4 4.9.0 - 1.4.28 + 1.8.71 5.25.90 5.3.7 3.0.5 From 8a2f0038bc637d7c63dfadb78a4141d72c17b316 Mon Sep 17 00:00:00 2001 From: Rashmini Date: Thu, 21 Sep 2023 13:33:15 +0530 Subject: [PATCH 11/17] Fix comments --- .../v2/impl/core/PasswordRecoveryService.java | 20 ++++++------- .../v2/impl/core/UsernameRecoveryService.java | 8 ++--- .../v2/impl/core/utils/RecoveryUtil.java | 29 ++++++++++--------- 3 files changed, 29 insertions(+), 28 deletions(-) diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java index b1d57266..26ee3a04 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java @@ -85,8 +85,8 @@ public Response initiatePasswordRecovery(InitRequest initRequest) { return Response.ok().entity(buildPasswordRecoveryInitResponse(tenantDomain, recoveryInformationDTO)) .build(); } catch (IdentityRecoveryClientException e) { - throw RecoveryUtil.handleClientExceptions(tenantDomain, - IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation(), e); + throw RecoveryUtil.handleClientException(e, tenantDomain, + IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation()); } catch (IdentityRecoveryException e) { throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, @@ -124,8 +124,8 @@ public Response recoverPassword(RecoveryRequest recoveryRequest) { return buildPasswordRecoveryResponse(tenantDomain, passwordRecoverDTO.getNotificationChannel(), passwordRecoverDTO); } catch (IdentityRecoveryClientException e) { - throw RecoveryUtil.handleClientExceptions(tenantDomain, - IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation(), e); + throw RecoveryUtil.handleClientException(e, tenantDomain, + IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation()); } catch (IdentityRecoveryException e) { throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, @@ -152,8 +152,8 @@ public Response confirmRecovery(ConfirmRequest confirmRequest) { RecoveryUtil.buildPropertiesMap(confirmRequest.getProperties())); return Response.ok().entity(buildResetCodeResponse(tenantDomain, passwordResetCodeDTO)).build(); } catch (IdentityRecoveryClientException e) { - throw RecoveryUtil.handleClientExceptions(tenantDomain, - IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation(), e); + throw RecoveryUtil.handleClientException(e, tenantDomain, + IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation()); } catch (IdentityRecoveryException e) { throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, @@ -183,9 +183,9 @@ public Response resetPassword(ResetRequest resetRequest) { return Response.ok().entity(buildPasswordResetResponse(successfulPasswordResetDTO)).build(); } catch (IdentityRecoveryClientException e) { // Send the reset code again for a retry attempt. - throw RecoveryUtil.handleClientExceptions(tenantDomain, + throw RecoveryUtil.handleClientException(e, tenantDomain, IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, resetRequest.getResetCode(), - Util.getCorrelation(), e); + Util.getCorrelation()); } catch (IdentityRecoveryException e) { throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, @@ -220,8 +220,8 @@ public Response resendConfirmation(ResendConfirmationRequest resendConfirmationR } return buildResendConfirmationResponse(tenantDomain, resendConfirmationDTO); } catch (IdentityRecoveryClientException e) { - throw RecoveryUtil.handleClientExceptions(tenantDomain, - IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation(), e); + throw RecoveryUtil.handleClientException(e, tenantDomain, + IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation()); } catch (IdentityRecoveryException e) { throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java index fe347490..ee511e28 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java @@ -81,8 +81,8 @@ public Response initiateUsernameRecovery(InitRequest initRequest) { return Response.ok().entity(buildUsernameRecoveryInitResponse(recoveryInformationDTO, tenantDomain)) .build(); } catch (IdentityRecoveryClientException e) { - throw RecoveryUtil.handleClientExceptions(tenantDomain, IdentityRecoveryConstants.USER_NAME_RECOVERY, - Util.getCorrelation(), e); + throw RecoveryUtil.handleClientException(e, tenantDomain, IdentityRecoveryConstants.USER_NAME_RECOVERY, + Util.getCorrelation()); } catch (IdentityRecoveryException e) { throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, @@ -115,8 +115,8 @@ public Response recoverUsername(RecoveryRequest recoveryRequest) { } return buildUsernameRecoveryResponse(usernameRecoverDTO.getNotificationChannel(), usernameRecoverDTO); } catch (IdentityRecoveryClientException e) { - throw RecoveryUtil.handleClientExceptions(tenantDomain, IdentityRecoveryConstants.USER_NAME_RECOVERY, - StringUtils.EMPTY, Util.getCorrelation(), e); + throw RecoveryUtil.handleClientException(e, tenantDomain, IdentityRecoveryConstants.USER_NAME_RECOVERY, + StringUtils.EMPTY, Util.getCorrelation()); } catch (IdentityRecoveryException e) { throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java index 40218f55..4623f0e2 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java @@ -49,6 +49,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; @@ -69,7 +70,7 @@ public class RecoveryUtil { private static final String RETRY_ERROR_CATEGORY = "RETRY_ERROR_CATEGORY"; // Map with the error codes categorized in to different error groups. - private static final HashMap clientErrorMap = generateClientErrorMap(); + private static final Map clientErrorMap = generateClientErrorMap(); /** * Converts a list of UserClaim in to a UserClaim array. @@ -77,9 +78,9 @@ public class RecoveryUtil { * @param userClaimsList UserClaims List. * @return Map of user claims. */ - public static HashMap buildUserClaimsMap(List userClaimsList) { + public static Map buildUserClaimsMap(List userClaimsList) { - HashMap userClaims = new HashMap<>(); + Map userClaims = new HashMap<>(); for (UserClaim userClaimModel : userClaimsList) { userClaims.put(userClaimModel.getUri(), userClaimModel.getValue()); } @@ -92,9 +93,9 @@ public static HashMap buildUserClaimsMap(List userCla * @param propertyList List of {@link Property} objects. * @return Map of properties. */ - public static HashMap buildPropertiesMap(List propertyList) { + public static Map buildPropertiesMap(List propertyList) { - HashMap properties = new HashMap<>(); + Map properties = new HashMap<>(); if (propertyList == null) { return properties; } @@ -137,11 +138,11 @@ public static List buildRecoveryChannelInformation(Notification * @return WebApplicationException (NOTE: Returns null when the client error is for no user available or for * multiple users available. */ - public static WebApplicationException handleClientExceptions(String tenantDomain, - String scenario, String correlationId, - IdentityRecoveryClientException exception) { + public static WebApplicationException handleClientException(IdentityRecoveryClientException exception, + String tenantDomain, String scenario, + String correlationId) { - return handleClientExceptions(tenantDomain, scenario, StringUtils.EMPTY, correlationId, exception); + return handleClientException(exception, tenantDomain, scenario, StringUtils.EMPTY, correlationId); } /** @@ -153,9 +154,9 @@ public static WebApplicationException handleClientExceptions(String tenantDomain * @return WebApplicationException (NOTE: Returns null when the client error is for no user available or for * multiple users available. */ - public static WebApplicationException handleClientExceptions(String tenantDomain, String scenario, - String code, String correlationId, - IdentityRecoveryClientException exception) { + public static WebApplicationException handleClientException(IdentityRecoveryClientException exception, + String tenantDomain, String scenario, String code, + String correlationId) { if (StringUtils.isEmpty(exception.getErrorCode())) { return buildConflictRequestResponseObject(exception, exception.getMessage(), exception.getErrorCode()); @@ -464,9 +465,9 @@ private static String prependOperationScenarioToErrorCode(String exceptionErrorC * * @return Grouped client error map. */ - private static HashMap generateClientErrorMap() { + private static Map generateClientErrorMap() { - HashMap clientErrorMap = new HashMap<>(); + Map clientErrorMap = new HashMap<>(); // Errors for not enabling account recovery, user account locked, user account disabled. clientErrorMap From c65b79e8aeca3857bf0551f9f0e63cafc386da94 Mon Sep 17 00:00:00 2001 From: Rashmini Date: Thu, 21 Sep 2023 14:42:48 +0530 Subject: [PATCH 12/17] Fix exceptions --- .../core/exceptions/ConflictException.java | 67 -------------- .../core/exceptions/ForbiddenException.java | 65 -------------- .../exceptions/NotAcceptableException.java | 65 -------------- .../core/exceptions/NotFoundException.java | 65 -------------- .../v2/impl/core/utils/RecoveryUtil.java | 90 +++---------------- 5 files changed, 14 insertions(+), 338 deletions(-) delete mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ConflictException.java delete mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ForbiddenException.java delete mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotAcceptableException.java delete mode 100644 components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotFoundException.java diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ConflictException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ConflictException.java deleted file mode 100644 index 465b4d9a..00000000 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ConflictException.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions; - -import org.wso2.carbon.identity.api.user.common.error.ErrorResponse; -import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; - -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.Response; - -/** - * ConflictException class. - */ -public class ConflictException extends WebApplicationException { - - /** - * Exception message. - */ - private String message; - - /** - * Constructs a new exception from the ErrorDTO{@link ErrorResponse} object. - * - * @param errorResponse ErrorResponse{@link ErrorResponse} object holding the error code and the message - */ - public ConflictException(ErrorResponse errorResponse) { - - super(Response.status(Response.Status.CONFLICT).entity(errorResponse) - .header(Constants.HEADER_CONTENT_TYPE, Constants.DEFAULT_RESPONSE_CONTENT_TYPE).build()); - message = errorResponse.getDescription(); - } - - /** - * Constructs a new exception instance. - */ - public ConflictException() { - - super(Response.Status.CONFLICT); - } - - /** - * Get exception message. - * - * @return Exception message - */ - @Override - public String getMessage() { - - return message; - } -} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ForbiddenException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ForbiddenException.java deleted file mode 100644 index ab0ed0d8..00000000 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/ForbiddenException.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions; - -import org.wso2.carbon.identity.api.user.common.error.ErrorResponse; -import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; - -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.Response; - -/** - * ForbiddenException class. - */ -public class ForbiddenException extends WebApplicationException { - - /** - * Exception message. - */ - private String message; - - /** - * Constructs a new exception from the ErrorDTO{@link ErrorResponse} object. - * - * @param errorResponse ErrorResponse{@link ErrorResponse} object holding the error code and the message - */ - public ForbiddenException(ErrorResponse errorResponse) { - - super(Response.status(Response.Status.FORBIDDEN).entity(errorResponse) - .header(Constants.HEADER_CONTENT_TYPE, Constants.DEFAULT_RESPONSE_CONTENT_TYPE).build()); - message = errorResponse.getDescription(); - } - - /** - * Constructs a new exception instance. - */ - public ForbiddenException() { - super(Response.Status.FORBIDDEN); - } - - /** - * Get exception message. - * - * @return Exception message - */ - @Override - public String getMessage() { - return message; - } -} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotAcceptableException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotAcceptableException.java deleted file mode 100644 index f947ec81..00000000 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotAcceptableException.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions; - -import org.wso2.carbon.identity.api.user.common.error.ErrorResponse; -import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; - -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.Response; - -/** - * NotAcceptableException class. - */ -public class NotAcceptableException extends WebApplicationException { - - /** - * Exception message. - */ - private String message; - - /** - * Constructs a new exception from the ErrorDTO{@link ErrorResponse} object. - * - * @param errorResponse ErrorResponse{@link ErrorResponse} object holding the error code and the message - */ - public NotAcceptableException(ErrorResponse errorResponse) { - - super(Response.status(Response.Status.NOT_ACCEPTABLE).entity(errorResponse) - .header(Constants.HEADER_CONTENT_TYPE, Constants.DEFAULT_RESPONSE_CONTENT_TYPE).build()); - message = errorResponse.getDescription(); - } - - /** - * Constructs a new exception instance. - */ - public NotAcceptableException() { - super(Response.Status.NOT_ACCEPTABLE); - } - - /** - * Get exception message. - * - * @return Exception message - */ - @Override - public String getMessage() { - return message; - } -} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotFoundException.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotFoundException.java deleted file mode 100644 index 84e6529e..00000000 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/exceptions/NotFoundException.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions; - -import org.wso2.carbon.identity.api.user.common.error.ErrorResponse; -import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; - -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.Response; - -/** - * NotFoundException class. - */ -public class NotFoundException extends WebApplicationException { - - /** - * Exception message. - */ - private String message; - - /** - * Constructs a new exception from the ErrorDTO{@link ErrorResponse} object. - * - * @param errorResponse ErrorResponse{@link ErrorResponse} object holding the error code and the message - */ - public NotFoundException(ErrorResponse errorResponse) { - - super(Response.status(Response.Status.NOT_FOUND).entity(errorResponse) - .header(Constants.HEADER_CONTENT_TYPE, Constants.DEFAULT_RESPONSE_CONTENT_TYPE).build()); - message = errorResponse.getDescription(); - } - - /** - * Constructs a new exception instance. - */ - public NotFoundException() { - super(Response.Status.NOT_ACCEPTABLE); - } - - /** - * Get exception message. - * - * @return Exception message - */ - @Override - public String getMessage() { - return message; - } -} diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java index 4623f0e2..26bc5db8 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java @@ -34,10 +34,6 @@ import org.wso2.carbon.identity.recovery.dto.NotificationChannelDTO; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.APICalls; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.Constants; -import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions.ConflictException; -import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions.ForbiddenException; -import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions.NotAcceptableException; -import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions.NotFoundException; import org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core.exceptions.PreconditionFailedException; import org.wso2.carbon.identity.rest.api.user.recovery.v2.model.APICall; @@ -159,7 +155,8 @@ public static WebApplicationException handleClientException(IdentityRecoveryClie String correlationId) { if (StringUtils.isEmpty(exception.getErrorCode())) { - return buildConflictRequestResponseObject(exception, exception.getMessage(), exception.getErrorCode()); + return handleException(exception, exception.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + exception.getMessage(), Response.Status.CONFLICT); } String errorCode = prependOperationScenarioToErrorCode(exception.getErrorCode(), scenario); @@ -169,7 +166,8 @@ public static WebApplicationException handleClientException(IdentityRecoveryClie // Throw errors according to exception category. switch (errorCategory) { case FORBIDDEN_ERROR_CATEGORY: - return buildForbiddenRequestResponseObject(exception, exception.getMessage(), errorCode); + return handleException(exception, errorCode, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, + exception.getMessage(), Response.Status.FORBIDDEN); case CONFLICT_REQUEST_ERROR_CATEGORY: if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_MULTIPLE_MATCHING_USERS.getCode() .equals(errorCode)) { @@ -179,8 +177,8 @@ public static WebApplicationException handleClientException(IdentityRecoveryClie return new WebApplicationException(Response.accepted().build()); } } - return buildConflictRequestResponseObject(exception, exception.getMessage(), - exception.getErrorCode()); + return handleException(exception, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + exception.getMessage(), Response.Status.CONFLICT); case REQUEST_NOT_FOUND_ERROR_CATEGORY: if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_USER_FOUND.getCode().equals(errorCode)) { // If user notify is not enabled, throw a accepted response. @@ -189,17 +187,21 @@ public static WebApplicationException handleClientException(IdentityRecoveryClie return new WebApplicationException(Response.accepted().build()); } } - return buildRequestNotFoundResponseObject(exception, errorCode, exception.getMessage()); + return handleException(exception, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + exception.getMessage(), Response.Status.NOT_FOUND); case REQUEST_NOT_ACCEPTABLE_ERROR_CATEGORY: - return buildRequestNotAcceptableResponseObject(exception, errorCode, exception.getMessage()); + return handleException(exception, errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, + exception.getMessage(), Response.Status.NOT_ACCEPTABLE); case RETRY_ERROR_CATEGORY: return buildRetryPasswordResetObject(tenantDomain, exception.getMessage(), errorCode, code, correlationId); default: - return buildConflictRequestResponseObject(exception, exception.getMessage(), errorCode); + return handleException(exception, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + exception.getMessage(), Response.Status.CONFLICT); } } else { - return buildConflictRequestResponseObject(exception, exception.getMessage(), errorCode); + return handleException(exception, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + exception.getMessage(), Response.Status.CONFLICT); } } @@ -374,70 +376,6 @@ private static RetryErrorResponse buildRetryErrorResponse(String message, String return retryErrorResponse; } - /** - * Returns a new NotAcceptableException. - * - * @param e IdentityRecoveryException. - * @param code Error code. - * @param description Description of the exception. - * @return A new NotAcceptableException with the specified details as a response. - */ - private static NotAcceptableException buildRequestNotAcceptableResponseObject(IdentityRecoveryException e, - String code, String description) { - - ErrorResponse errorResponse = buildErrorResponse(e, code, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, - description); - return new NotAcceptableException(errorResponse); - } - - /** - * Returns a new NotAcceptableException. - * - * @param e IdentityRecoveryException. - * @param code Error code. - * @param description Description of the exception. - * @return A new NotAcceptableException with the specified details as a response. - */ - private static NotFoundException buildRequestNotFoundResponseObject(IdentityRecoveryException e, String code, - String description) { - - ErrorResponse errorResponse = buildErrorResponse(e, code, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, - description); - return new NotFoundException(errorResponse); - } - - /** - * Returns a new ConflictException. - * - * @param e IdentityRecoveryException. - * @param description Description of the exception - * @param code Error code - * @return A new ConflictException with the specified details as a response - */ - private static ConflictException buildConflictRequestResponseObject(IdentityRecoveryException e, String description, - String code) { - - ErrorResponse errorResponse = buildErrorResponse(e, code, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - description); - return new ConflictException(errorResponse); - } - - /** - * Returns a new ForbiddenException. - * - * @param e IdentityRecoveryException. - * @param description Description of the exception. - * @param code Error code. - * @return A new ForbiddenException with the specified details as a response. - */ - private static ForbiddenException buildForbiddenRequestResponseObject(IdentityRecoveryException e, - String description, String code) { - - ErrorResponse errorResponse = buildErrorResponse(e, code, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, - description); - return new ForbiddenException(errorResponse); - } - /** * Prepend the operation scenario to the existing exception error code. * (Eg: USR-20045) From 3fc7797e443c28b950cd5fecae635d03ba6f3897 Mon Sep 17 00:00:00 2001 From: Rashmini Date: Mon, 25 Sep 2023 13:43:24 +0530 Subject: [PATCH 13/17] Refactor error handling --- .../v2/impl/core/PasswordRecoveryService.java | 154 ++++++++++- .../v2/impl/core/UsernameRecoveryService.java | 71 ++++- .../v2/impl/core/utils/RecoveryUtil.java | 245 ++++-------------- 3 files changed, 255 insertions(+), 215 deletions(-) diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java index 26ee3a04..e986993f 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java @@ -18,11 +18,13 @@ package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.identity.api.user.common.Util; import org.wso2.carbon.identity.api.user.recovery.commons.UserAccountRecoveryServiceDataHolder; +import org.wso2.carbon.identity.core.util.IdentityUtil; import org.wso2.carbon.identity.governance.service.notification.NotificationChannels; import org.wso2.carbon.identity.recovery.IdentityRecoveryClientException; import org.wso2.carbon.identity.recovery.IdentityRecoveryConstants; @@ -54,6 +56,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; /** @@ -85,8 +88,44 @@ public Response initiatePasswordRecovery(InitRequest initRequest) { return Response.ok().entity(buildPasswordRecoveryInitResponse(tenantDomain, recoveryInformationDTO)) .build(); } catch (IdentityRecoveryClientException e) { - throw RecoveryUtil.handleClientException(e, tenantDomain, - IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation()); + if (StringUtils.isEmpty(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.CONFLICT); + } + String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), + IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO); + if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_DISABLED_ACCOUNT.getCode().equals(e.getErrorCode()) + || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_LOCKED_ACCOUNT.getCode().equals( + e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages. + ERROR_CODE_PASSWORD_RECOVERY_NOT_ENABLED.getCode().equals(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.FORBIDDEN); + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_MULTIPLE_MATCHING_USERS.getCode().equals( + e.getErrorCode())) { + // If user notify is not enabled, throw a accepted response. + if (!Boolean.parseBoolean(IdentityUtil + .getProperty(IdentityRecoveryConstants.ConnectorConfig.NOTIFY_USER_EXISTENCE))) { + throw new WebApplicationException(Response.accepted().build()); + } + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.CONFLICT); + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_USER_FOUND.getCode().equals( + e.getErrorCode())) { + // If user notify is not enabled, throw a accepted response. + if (!Boolean.parseBoolean(IdentityUtil + .getProperty(IdentityRecoveryConstants.ConnectorConfig.NOTIFY_USER_EXISTENCE))) { + throw new WebApplicationException(Response.accepted().build()); + } + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.NOT_FOUND); + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_VERIFIED_CHANNELS_FOR_USER. + getCode().equals(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.NOT_FOUND); + } else { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.CONFLICT); + } } catch (IdentityRecoveryException e) { throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, @@ -124,8 +163,31 @@ public Response recoverPassword(RecoveryRequest recoveryRequest) { return buildPasswordRecoveryResponse(tenantDomain, passwordRecoverDTO.getNotificationChannel(), passwordRecoverDTO); } catch (IdentityRecoveryClientException e) { - throw RecoveryUtil.handleClientException(e, tenantDomain, - IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation()); + if (StringUtils.isEmpty(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.CONFLICT); + } + String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), + IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO); + if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_RECOVERY_WITH_NOTIFICATIONS_NOT_ENABLED. + getCode().equals(e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages. + ERROR_CODE_DISABLED_ACCOUNT.getCode().equals(e.getErrorCode()) || IdentityRecoveryConstants. + ErrorMessages.ERROR_CODE_LOCKED_ACCOUNT.getCode().equals(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.FORBIDDEN); + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_ACCOUNT_RECOVERY_DATA.getCode().equals( + e.getErrorCode())) { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.NOT_FOUND); + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals( + e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_EXPIRED_RECOVERY_CODE + .getCode().equals(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.NOT_ACCEPTABLE); + } else { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.CONFLICT); + } } catch (IdentityRecoveryException e) { throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, @@ -152,8 +214,29 @@ public Response confirmRecovery(ConfirmRequest confirmRequest) { RecoveryUtil.buildPropertiesMap(confirmRequest.getProperties())); return Response.ok().entity(buildResetCodeResponse(tenantDomain, passwordResetCodeDTO)).build(); } catch (IdentityRecoveryClientException e) { - throw RecoveryUtil.handleClientException(e, tenantDomain, - IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation()); + if (StringUtils.isEmpty(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.CONFLICT); + } + String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), + IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO); + if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_USER_TENANT_DOMAIN_MISS_MATCH_WITH_CONTEXT.getCode(). + equals(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.CONFLICT); + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_ACCOUNT_RECOVERY_DATA.getCode().equals( + e.getErrorCode())) { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.NOT_FOUND); + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals( + e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_EXPIRED_RECOVERY_CODE + .getCode().equals(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.NOT_ACCEPTABLE); + } else { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.CONFLICT); + } } catch (IdentityRecoveryException e) { throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, @@ -182,10 +265,35 @@ public Response resetPassword(ResetRequest resetRequest) { RecoveryUtil.buildPropertiesMap(resetRequest.getProperties())); return Response.ok().entity(buildPasswordResetResponse(successfulPasswordResetDTO)).build(); } catch (IdentityRecoveryClientException e) { - // Send the reset code again for a retry attempt. - throw RecoveryUtil.handleClientException(e, tenantDomain, - IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, resetRequest.getResetCode(), - Util.getCorrelation()); + if (StringUtils.isEmpty(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.CONFLICT); + } + String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), + IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO); + if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_USER_TENANT_DOMAIN_MISS_MATCH_WITH_CONTEXT.getCode(). + equals(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.CONFLICT); + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_ACCOUNT_RECOVERY_DATA.getCode().equals( + e.getErrorCode())) { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.NOT_FOUND); + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals( + e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_EXPIRED_RECOVERY_CODE. + getCode().equals(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.NOT_ACCEPTABLE); + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_HISTORY_VIOLATION.getCode().equals( + e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_POLICY_VIOLATION. + getCode().equals(e.getErrorCode())) { + // Send the reset code again for a retry attempt. + throw RecoveryUtil.buildRetryPasswordResetObject(tenantDomain, e.getMessage(), errorCode, + resetRequest.getResetCode(), Util.getCorrelation()); + } else { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.CONFLICT); + } } catch (IdentityRecoveryException e) { throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, @@ -220,8 +328,30 @@ public Response resendConfirmation(ResendConfirmationRequest resendConfirmationR } return buildResendConfirmationResponse(tenantDomain, resendConfirmationDTO); } catch (IdentityRecoveryClientException e) { - throw RecoveryUtil.handleClientException(e, tenantDomain, - IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation()); + if (StringUtils.isEmpty(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.CONFLICT); + } + String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), + IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO); + if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_USER_TENANT_DOMAIN_MISS_MATCH_WITH_CONTEXT.getCode(). + equals(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.CONFLICT); + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_ACCOUNT_RECOVERY_DATA.getCode().equals( + e.getErrorCode())) { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.NOT_FOUND); + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals( + e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RESEND_CODE. + getCode().equals(e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages. + ERROR_CODE_EXPIRED_RECOVERY_CODE.getCode().equals(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.NOT_ACCEPTABLE); + } else { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.CONFLICT); + } } catch (IdentityRecoveryException e) { throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java index ee511e28..8ccae416 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java @@ -23,8 +23,8 @@ import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.PrivilegedCarbonContext; -import org.wso2.carbon.identity.api.user.common.Util; import org.wso2.carbon.identity.api.user.recovery.commons.UserAccountRecoveryServiceDataHolder; +import org.wso2.carbon.identity.core.util.IdentityUtil; import org.wso2.carbon.identity.governance.service.notification.NotificationChannels; import org.wso2.carbon.identity.recovery.IdentityRecoveryClientException; import org.wso2.carbon.identity.recovery.IdentityRecoveryConstants; @@ -45,6 +45,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; /** @@ -57,8 +58,7 @@ public class UsernameRecoveryService { /** * Initiate userName recovery from POST. * - * @param initRequest {@link InitRequest} object which holds the information in the account recovery - * request + * @param initRequest {@link InitRequest} object which holds the information in the account recovery request * @return Response */ public Response initiateUsernameRecovery(InitRequest initRequest) { @@ -81,8 +81,44 @@ public Response initiateUsernameRecovery(InitRequest initRequest) { return Response.ok().entity(buildUsernameRecoveryInitResponse(recoveryInformationDTO, tenantDomain)) .build(); } catch (IdentityRecoveryClientException e) { - throw RecoveryUtil.handleClientException(e, tenantDomain, IdentityRecoveryConstants.USER_NAME_RECOVERY, - Util.getCorrelation()); + if (StringUtils.isEmpty(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.CONFLICT); + } + String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), + IdentityRecoveryConstants.USER_NAME_RECOVERY); + if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_USERNAME_RECOVERY_NOT_ENABLED.getCode().equals( + e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_DISABLED_ACCOUNT.getCode(). + equals(e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_LOCKED_ACCOUNT. + getCode().equals(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.FORBIDDEN); + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_MULTIPLE_MATCHING_USERS.getCode().equals( + e.getErrorCode())) { + // If user notify is not enabled, throw a accepted response. + if (!Boolean.parseBoolean(IdentityUtil + .getProperty(IdentityRecoveryConstants.ConnectorConfig.NOTIFY_USER_EXISTENCE))) { + throw new WebApplicationException(Response.accepted().build()); + } + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.CONFLICT); + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_USER_FOUND.getCode().equals( + e.getErrorCode())) { + // If user notify is not enabled, throw a accepted response. + if (!Boolean.parseBoolean(IdentityUtil + .getProperty(IdentityRecoveryConstants.ConnectorConfig.NOTIFY_USER_EXISTENCE))) { + throw new WebApplicationException(Response.accepted().build()); + } + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.NOT_FOUND); + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_VERIFIED_CHANNELS_FOR_USER. + getCode().equals(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.NOT_FOUND); + } else { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.CONFLICT); + } } catch (IdentityRecoveryException e) { throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, @@ -115,8 +151,29 @@ public Response recoverUsername(RecoveryRequest recoveryRequest) { } return buildUsernameRecoveryResponse(usernameRecoverDTO.getNotificationChannel(), usernameRecoverDTO); } catch (IdentityRecoveryClientException e) { - throw RecoveryUtil.handleClientException(e, tenantDomain, IdentityRecoveryConstants.USER_NAME_RECOVERY, - StringUtils.EMPTY, Util.getCorrelation()); + if (StringUtils.isEmpty(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.CONFLICT); + } + String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), + IdentityRecoveryConstants.USER_NAME_RECOVERY); + if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_USERNAME_RECOVERY_NOT_ENABLED.getCode().equals( + e.getErrorCode())) { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.FORBIDDEN); + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_ACCOUNT_RECOVERY_DATA.getCode().equals( + e.getErrorCode())) { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.NOT_FOUND); + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals( + e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_EXPIRED_RECOVERY_CODE. + getCode().equals(e.getErrorCode())) { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.NOT_ACCEPTABLE); + } else { + throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + e.getMessage(), Response.Status.CONFLICT); + } } catch (IdentityRecoveryException e) { throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java index 26bc5db8..ebe0b101 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java @@ -27,8 +27,6 @@ import org.wso2.carbon.identity.core.ServiceURLBuilder; import org.wso2.carbon.identity.core.URLBuilderException; import org.wso2.carbon.identity.core.util.IdentityTenantUtil; -import org.wso2.carbon.identity.core.util.IdentityUtil; -import org.wso2.carbon.identity.recovery.IdentityRecoveryClientException; import org.wso2.carbon.identity.recovery.IdentityRecoveryConstants; import org.wso2.carbon.identity.recovery.IdentityRecoveryException; import org.wso2.carbon.identity.recovery.dto.NotificationChannelDTO; @@ -46,7 +44,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; import static org.wso2.carbon.identity.api.user.common.Constants.TENANT_CONTEXT_PATH_COMPONENT; @@ -58,15 +55,6 @@ public class RecoveryUtil { private static final Log log = LogFactory.getLog(RecoveryUtil.class); - private static final String LOG_MESSAGE_PREFIX = "INITIATOR"; - private static final String FORBIDDEN_ERROR_CATEGORY = "FORBIDDEN_ERROR_CATEGORY"; - private static final String CONFLICT_REQUEST_ERROR_CATEGORY = "CONFLICT_REQUEST_ERROR_CATEGORY"; - private static final String REQUEST_NOT_FOUND_ERROR_CATEGORY = "REQUEST_NOT_FOUND_ERROR_CATEGORY"; - private static final String REQUEST_NOT_ACCEPTABLE_ERROR_CATEGORY = "REQUEST_NOT_ACCEPTABLE_ERROR_CATEGORY"; - private static final String RETRY_ERROR_CATEGORY = "RETRY_ERROR_CATEGORY"; - - // Map with the error codes categorized in to different error groups. - private static final Map clientErrorMap = generateClientErrorMap(); /** * Converts a list of UserClaim in to a UserClaim array. @@ -126,85 +114,6 @@ public static List buildRecoveryChannelInformation(Notification return recoveryChannelDTOs; } - /** - * Handle client errors with specific http codes. - * - * @param scenario Recovery scenario. - * @param exception IdentityRecoveryClientException. - * @return WebApplicationException (NOTE: Returns null when the client error is for no user available or for - * multiple users available. - */ - public static WebApplicationException handleClientException(IdentityRecoveryClientException exception, - String tenantDomain, String scenario, - String correlationId) { - - return handleClientException(exception, tenantDomain, scenario, StringUtils.EMPTY, correlationId); - } - - /** - * Handle client errors with specific http codes. - * - * @param scenario Recovery scenario. - * @param code Recovery code. - * @param exception IdentityRecoveryClientException. - * @return WebApplicationException (NOTE: Returns null when the client error is for no user available or for - * multiple users available. - */ - public static WebApplicationException handleClientException(IdentityRecoveryClientException exception, - String tenantDomain, String scenario, String code, - String correlationId) { - - if (StringUtils.isEmpty(exception.getErrorCode())) { - return handleException(exception, exception.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - exception.getMessage(), Response.Status.CONFLICT); - } - String errorCode = prependOperationScenarioToErrorCode(exception.getErrorCode(), scenario); - - if (clientErrorMap.containsKey(errorCode)) { - String errorCategory = clientErrorMap.get(errorCode); - - // Throw errors according to exception category. - switch (errorCategory) { - case FORBIDDEN_ERROR_CATEGORY: - return handleException(exception, errorCode, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, - exception.getMessage(), Response.Status.FORBIDDEN); - case CONFLICT_REQUEST_ERROR_CATEGORY: - if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_MULTIPLE_MATCHING_USERS.getCode() - .equals(errorCode)) { - // If user notify is not enabled, throw a accepted response. - if (!Boolean.parseBoolean(IdentityUtil - .getProperty(IdentityRecoveryConstants.ConnectorConfig.NOTIFY_USER_EXISTENCE))) { - return new WebApplicationException(Response.accepted().build()); - } - } - return handleException(exception, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - exception.getMessage(), Response.Status.CONFLICT); - case REQUEST_NOT_FOUND_ERROR_CATEGORY: - if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_USER_FOUND.getCode().equals(errorCode)) { - // If user notify is not enabled, throw a accepted response. - if (!Boolean.parseBoolean(IdentityUtil - .getProperty(IdentityRecoveryConstants.ConnectorConfig.NOTIFY_USER_EXISTENCE))) { - return new WebApplicationException(Response.accepted().build()); - } - } - return handleException(exception, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, - exception.getMessage(), Response.Status.NOT_FOUND); - case REQUEST_NOT_ACCEPTABLE_ERROR_CATEGORY: - return handleException(exception, errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, - exception.getMessage(), Response.Status.NOT_ACCEPTABLE); - case RETRY_ERROR_CATEGORY: - return buildRetryPasswordResetObject(tenantDomain, exception.getMessage(), errorCode, - code, correlationId); - default: - return handleException(exception, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - exception.getMessage(), Response.Status.CONFLICT); - } - } else { - return handleException(exception, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - exception.getMessage(), Response.Status.CONFLICT); - } - } - /** * Build API call information. * @@ -272,6 +181,55 @@ public static APIError handleException(IdentityRecoveryException e, String error return new APIError(status, errorResponse); } + /** + * Returns a new PreconditionFailedException. + * + * @param tenantDomain Tenant domain. + * @param description Description of the exception. + * @param code Error code. + * @param resetCode Reset code given to the user by confirmation API. + * @param correlationId Correlation Id. + * @return A new PreconditionFailedException with the specified details as a response. + */ + public static PreconditionFailedException buildRetryPasswordResetObject(String tenantDomain, String description, + String code, String resetCode, + String correlationId) { + + // Build next API calls. + ArrayList apiCallsArrayList = new ArrayList<>(); + apiCallsArrayList.add(RecoveryUtil + .buildApiCall(APICalls.RESET_PASSWORD_API.getType(), Constants.RelationStates.NEXT_REL, + buildURIForBody(tenantDomain, APICalls.RESET_PASSWORD_API.getApiUrl(), + Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); + RetryErrorResponse retryErrorResponse = buildRetryErrorResponse( + Constants.STATUS_PRECONDITION_FAILED_MESSAGE_DEFAULT, code, description, resetCode, correlationId, + apiCallsArrayList); + log.error(description); + return new PreconditionFailedException(retryErrorResponse); + } + + /** + * Prepend the operation scenario to the existing exception error code. + * (Eg: USR-20045) + * + * @param exceptionErrorCode Existing error code. + * @param scenario Operation scenario. + * @return New error code with the scenario prepended. + */ + public static String prependOperationScenarioToErrorCode(String exceptionErrorCode, String scenario) { + + if (StringUtils.isNotEmpty(exceptionErrorCode)) { + if (exceptionErrorCode.contains(IdentityRecoveryConstants.EXCEPTION_SCENARIO_SEPARATOR)) { + return exceptionErrorCode; + } + if (StringUtils.isNotEmpty(scenario)) { + exceptionErrorCode = + scenario + IdentityRecoveryConstants.EXCEPTION_SCENARIO_SEPARATOR + exceptionErrorCode; + } + } + return exceptionErrorCode; + } + /** * Builds the API context on whether the tenant qualified url is enabled or not. In tenant qualified mode the * ServiceURLBuilder appends the tenant domain to the URI as a path param automatically. But @@ -324,33 +282,6 @@ private static ErrorResponse.Builder getErrorBuilder(String errorCode, String er .withDescription(errorDescription); } - /** - * Returns a new PreconditionFailedException. - * - * @param tenantDomain Tenant domain. - * @param description Description of the exception. - * @param code Error code. - * @param resetCode Reset code given to the user by confirmation API. - * @param correlationId Correlation Id. - * @return A new PreconditionFailedException with the specified details as a response. - */ - private static PreconditionFailedException buildRetryPasswordResetObject(String tenantDomain, String description, - String code, String resetCode, - String correlationId) { - - // Build next API calls. - ArrayList apiCallsArrayList = new ArrayList<>(); - apiCallsArrayList.add(RecoveryUtil - .buildApiCall(APICalls.RESET_PASSWORD_API.getType(), Constants.RelationStates.NEXT_REL, - buildURIForBody(tenantDomain, APICalls.RESET_PASSWORD_API.getApiUrl(), - Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); - RetryErrorResponse retryErrorResponse = buildRetryErrorResponse( - Constants.STATUS_PRECONDITION_FAILED_MESSAGE_DEFAULT, code, description, resetCode, correlationId, - apiCallsArrayList); - log.error(description); - return new PreconditionFailedException(retryErrorResponse); - } - /** * Build the RetryErrorResponse for not valid password scenario. * @@ -375,82 +306,4 @@ private static RetryErrorResponse buildRetryErrorResponse(String message, String retryErrorResponse.setLinks(apiCallsArrayList); return retryErrorResponse; } - - /** - * Prepend the operation scenario to the existing exception error code. - * (Eg: USR-20045) - * - * @param exceptionErrorCode Existing error code. - * @param scenario Operation scenario. - * @return New error code with the scenario prepended. - */ - private static String prependOperationScenarioToErrorCode(String exceptionErrorCode, String scenario) { - - if (StringUtils.isNotEmpty(exceptionErrorCode)) { - if (exceptionErrorCode.contains(IdentityRecoveryConstants.EXCEPTION_SCENARIO_SEPARATOR)) { - return exceptionErrorCode; - } - if (StringUtils.isNotEmpty(scenario)) { - exceptionErrorCode = - scenario + IdentityRecoveryConstants.EXCEPTION_SCENARIO_SEPARATOR + exceptionErrorCode; - } - } - return exceptionErrorCode; - } - - /** - * Generate the map which categorizes the exceptions for different http error groups. - * - * @return Grouped client error map. - */ - private static Map generateClientErrorMap() { - - Map clientErrorMap = new HashMap<>(); - - // Errors for not enabling account recovery, user account locked, user account disabled. - clientErrorMap - .put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_RECOVERY_WITH_NOTIFICATIONS_NOT_ENABLED - .getCode(), FORBIDDEN_ERROR_CATEGORY); - clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_USERNAME_RECOVERY_NOT_ENABLED.getCode(), - FORBIDDEN_ERROR_CATEGORY); - clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_DISABLED_ACCOUNT.getCode(), - FORBIDDEN_ERROR_CATEGORY); - clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_LOCKED_ACCOUNT.getCode(), - FORBIDDEN_ERROR_CATEGORY); - clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_RECOVERY_NOT_ENABLED.getCode(), - FORBIDDEN_ERROR_CATEGORY); - - // Tenant miss match error. - clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_USER_TENANT_DOMAIN_MISS_MATCH_WITH_CONTEXT - .getCode(), CONFLICT_REQUEST_ERROR_CATEGORY); - - // Multiples users found error. - clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_MULTIPLE_MATCHING_USERS.getCode(), - CONFLICT_REQUEST_ERROR_CATEGORY); - - // No user found error. - clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_USER_FOUND.getCode(), - REQUEST_NOT_FOUND_ERROR_CATEGORY); - - // No recovery code found and no verified channels found errors. - clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_ACCOUNT_RECOVERY_DATA.getCode(), - REQUEST_NOT_FOUND_ERROR_CATEGORY); - clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_VERIFIED_CHANNELS_FOR_USER.getCode(), - REQUEST_NOT_FOUND_ERROR_CATEGORY); - - // Invalid recovery codes errors. - clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode(), - REQUEST_NOT_ACCEPTABLE_ERROR_CATEGORY); - clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RESEND_CODE.getCode(), - REQUEST_NOT_ACCEPTABLE_ERROR_CATEGORY); - clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_EXPIRED_RECOVERY_CODE.getCode(), - REQUEST_NOT_ACCEPTABLE_ERROR_CATEGORY); - - // Password reset password history violation errors and password policy violation errors. - clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_HISTORY_VIOLATION.getCode(), - RETRY_ERROR_CATEGORY); - clientErrorMap.put(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_POLICY_VIOLATION.getCode(), - RETRY_ERROR_CATEGORY); - return clientErrorMap; - } } From ecbea0fc3ec6e96e3268a2a1e03600e824ef04f1 Mon Sep 17 00:00:00 2001 From: Rashmini Date: Mon, 25 Sep 2023 14:32:29 +0530 Subject: [PATCH 14/17] Change client error logs to debug logs --- .../v2/impl/core/PasswordRecoveryService.java | 62 +++++++++---------- .../v2/impl/core/UsernameRecoveryService.java | 26 ++++---- .../v2/impl/core/utils/RecoveryUtil.java | 44 +++++++++++-- 3 files changed, 83 insertions(+), 49 deletions(-) diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java index e986993f..f5cbf7a9 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java @@ -89,7 +89,7 @@ public Response initiatePasswordRecovery(InitRequest initRequest) { .build(); } catch (IdentityRecoveryClientException e) { if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, e.getMessage(), Response.Status.CONFLICT); } String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), @@ -98,7 +98,7 @@ public Response initiatePasswordRecovery(InitRequest initRequest) { || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_LOCKED_ACCOUNT.getCode().equals( e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages. ERROR_CODE_PASSWORD_RECOVERY_NOT_ENABLED.getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, e.getMessage(), Response.Status.FORBIDDEN); } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_MULTIPLE_MATCHING_USERS.getCode().equals( e.getErrorCode())) { @@ -107,7 +107,7 @@ public Response initiatePasswordRecovery(InitRequest initRequest) { .getProperty(IdentityRecoveryConstants.ConnectorConfig.NOTIFY_USER_EXISTENCE))) { throw new WebApplicationException(Response.accepted().build()); } - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, e.getMessage(), Response.Status.CONFLICT); } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_USER_FOUND.getCode().equals( e.getErrorCode())) { @@ -116,18 +116,18 @@ public Response initiatePasswordRecovery(InitRequest initRequest) { .getProperty(IdentityRecoveryConstants.ConnectorConfig.NOTIFY_USER_EXISTENCE))) { throw new WebApplicationException(Response.accepted().build()); } - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, e.getMessage(), Response.Status.NOT_FOUND); } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_VERIFIED_CHANNELS_FOR_USER. getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, e.getMessage(), Response.Status.NOT_FOUND); } else { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, e.getMessage(), Response.Status.CONFLICT); } } catch (IdentityRecoveryException e) { - throw RecoveryUtil.handleException(e, e.getErrorCode(), + throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); } @@ -164,7 +164,7 @@ public Response recoverPassword(RecoveryRequest recoveryRequest) { passwordRecoverDTO); } catch (IdentityRecoveryClientException e) { if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, e.getMessage(), Response.Status.CONFLICT); } String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), @@ -173,23 +173,23 @@ public Response recoverPassword(RecoveryRequest recoveryRequest) { getCode().equals(e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages. ERROR_CODE_DISABLED_ACCOUNT.getCode().equals(e.getErrorCode()) || IdentityRecoveryConstants. ErrorMessages.ERROR_CODE_LOCKED_ACCOUNT.getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, e.getMessage(), Response.Status.FORBIDDEN); } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_ACCOUNT_RECOVERY_DATA.getCode().equals( e.getErrorCode())) { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, e.getMessage(), Response.Status.NOT_FOUND); } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals( e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_EXPIRED_RECOVERY_CODE .getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, e.getMessage(), Response.Status.NOT_ACCEPTABLE); } else { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, e.getMessage(), Response.Status.CONFLICT); } } catch (IdentityRecoveryException e) { - throw RecoveryUtil.handleException(e, e.getErrorCode(), + throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); } @@ -215,30 +215,30 @@ public Response confirmRecovery(ConfirmRequest confirmRequest) { return Response.ok().entity(buildResetCodeResponse(tenantDomain, passwordResetCodeDTO)).build(); } catch (IdentityRecoveryClientException e) { if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, e.getMessage(), Response.Status.CONFLICT); } String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO); if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_USER_TENANT_DOMAIN_MISS_MATCH_WITH_CONTEXT.getCode(). equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, e.getMessage(), Response.Status.CONFLICT); } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_ACCOUNT_RECOVERY_DATA.getCode().equals( e.getErrorCode())) { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, e.getMessage(), Response.Status.NOT_FOUND); } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals( e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_EXPIRED_RECOVERY_CODE .getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, e.getMessage(), Response.Status.NOT_ACCEPTABLE); } else { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, e.getMessage(), Response.Status.CONFLICT); } } catch (IdentityRecoveryException e) { - throw RecoveryUtil.handleException(e, e.getErrorCode(), + throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); } @@ -266,23 +266,23 @@ public Response resetPassword(ResetRequest resetRequest) { return Response.ok().entity(buildPasswordResetResponse(successfulPasswordResetDTO)).build(); } catch (IdentityRecoveryClientException e) { if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, e.getMessage(), Response.Status.CONFLICT); } String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO); if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_USER_TENANT_DOMAIN_MISS_MATCH_WITH_CONTEXT.getCode(). equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, e.getMessage(), Response.Status.CONFLICT); } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_ACCOUNT_RECOVERY_DATA.getCode().equals( e.getErrorCode())) { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, e.getMessage(), Response.Status.NOT_FOUND); } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals( e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_EXPIRED_RECOVERY_CODE. getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, e.getMessage(), Response.Status.NOT_ACCEPTABLE); } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_HISTORY_VIOLATION.getCode().equals( e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_POLICY_VIOLATION. @@ -291,11 +291,11 @@ public Response resetPassword(ResetRequest resetRequest) { throw RecoveryUtil.buildRetryPasswordResetObject(tenantDomain, e.getMessage(), errorCode, resetRequest.getResetCode(), Util.getCorrelation()); } else { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, e.getMessage(), Response.Status.CONFLICT); } } catch (IdentityRecoveryException e) { - throw RecoveryUtil.handleException(e, e.getErrorCode(), + throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); } @@ -329,31 +329,31 @@ public Response resendConfirmation(ResendConfirmationRequest resendConfirmationR return buildResendConfirmationResponse(tenantDomain, resendConfirmationDTO); } catch (IdentityRecoveryClientException e) { if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, e.getMessage(), Response.Status.CONFLICT); } String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO); if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_USER_TENANT_DOMAIN_MISS_MATCH_WITH_CONTEXT.getCode(). equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, e.getMessage(), Response.Status.CONFLICT); } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_ACCOUNT_RECOVERY_DATA.getCode().equals( e.getErrorCode())) { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, e.getMessage(), Response.Status.NOT_FOUND); } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals( e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RESEND_CODE. getCode().equals(e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages. ERROR_CODE_EXPIRED_RECOVERY_CODE.getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, e.getMessage(), Response.Status.NOT_ACCEPTABLE); } else { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, e.getMessage(), Response.Status.CONFLICT); } } catch (IdentityRecoveryException e) { - throw RecoveryUtil.handleException(e, e.getErrorCode(), + throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); } diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java index 8ccae416..46b822c1 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java @@ -82,7 +82,7 @@ public Response initiateUsernameRecovery(InitRequest initRequest) { .build(); } catch (IdentityRecoveryClientException e) { if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, e.getMessage(), Response.Status.CONFLICT); } String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), @@ -91,7 +91,7 @@ public Response initiateUsernameRecovery(InitRequest initRequest) { e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_DISABLED_ACCOUNT.getCode(). equals(e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_LOCKED_ACCOUNT. getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, e.getMessage(), Response.Status.FORBIDDEN); } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_MULTIPLE_MATCHING_USERS.getCode().equals( e.getErrorCode())) { @@ -100,7 +100,7 @@ public Response initiateUsernameRecovery(InitRequest initRequest) { .getProperty(IdentityRecoveryConstants.ConnectorConfig.NOTIFY_USER_EXISTENCE))) { throw new WebApplicationException(Response.accepted().build()); } - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, e.getMessage(), Response.Status.CONFLICT); } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_USER_FOUND.getCode().equals( e.getErrorCode())) { @@ -109,18 +109,18 @@ public Response initiateUsernameRecovery(InitRequest initRequest) { .getProperty(IdentityRecoveryConstants.ConnectorConfig.NOTIFY_USER_EXISTENCE))) { throw new WebApplicationException(Response.accepted().build()); } - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, e.getMessage(), Response.Status.NOT_FOUND); } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_VERIFIED_CHANNELS_FOR_USER. getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, e.getMessage(), Response.Status.NOT_FOUND); } else { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, e.getMessage(), Response.Status.CONFLICT); } } catch (IdentityRecoveryException e) { - throw RecoveryUtil.handleException(e, e.getErrorCode(), + throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); } @@ -152,30 +152,30 @@ public Response recoverUsername(RecoveryRequest recoveryRequest) { return buildUsernameRecoveryResponse(usernameRecoverDTO.getNotificationChannel(), usernameRecoverDTO); } catch (IdentityRecoveryClientException e) { if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, e.getMessage(), Response.Status.CONFLICT); } String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), IdentityRecoveryConstants.USER_NAME_RECOVERY); if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_USERNAME_RECOVERY_NOT_ENABLED.getCode().equals( e.getErrorCode())) { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, e.getMessage(), Response.Status.FORBIDDEN); } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_ACCOUNT_RECOVERY_DATA.getCode().equals( e.getErrorCode())) { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, e.getMessage(), Response.Status.NOT_FOUND); } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals( e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_EXPIRED_RECOVERY_CODE. getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, e.getMessage(), Response.Status.NOT_ACCEPTABLE); } else { - throw RecoveryUtil.handleException(e, errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, + throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, e.getMessage(), Response.Status.CONFLICT); } } catch (IdentityRecoveryException e) { - throw RecoveryUtil.handleException(e, e.getErrorCode(), + throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); } diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java index ebe0b101..8676a77e 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java @@ -167,6 +167,22 @@ public static String buildURIForBody(String tenantDomain, String endpoint, Strin /** * Builds API error to be thrown. * + * @param errorCode Error code. + * @param errorMessage Error message. + * @param errorDescription Error description. + * @param status HTTP status. + * @return APIError object which contains the error description. + */ + public static APIError handleException(String errorCode, String errorMessage, String errorDescription, + Response.Status status) { + + ErrorResponse errorResponse = buildErrorResponse(errorCode, errorMessage, errorDescription); + return new APIError(status, errorResponse); + } + + /** + * Builds API error to be thrown for server errors. + * * @param e Identity Recovery Exception. * @param errorCode Error code. * @param errorMessage Error message. @@ -174,10 +190,10 @@ public static String buildURIForBody(String tenantDomain, String endpoint, Strin * @param status HTTP status. * @return APIError object which contains the error description. */ - public static APIError handleException(IdentityRecoveryException e, String errorCode, String errorMessage, + public static APIError handleInternalServerError(IdentityRecoveryException e, String errorCode, String errorMessage, String errorDescription, Response.Status status) { - ErrorResponse errorResponse = buildErrorResponse(e, errorCode, errorMessage, errorDescription); + ErrorResponse errorResponse = buildServerErrorResponse(e, errorCode, errorMessage, errorDescription); return new APIError(status, errorResponse); } @@ -204,7 +220,10 @@ public static PreconditionFailedException buildRetryPasswordResetObject(String t RetryErrorResponse retryErrorResponse = buildRetryErrorResponse( Constants.STATUS_PRECONDITION_FAILED_MESSAGE_DEFAULT, code, description, resetCode, correlationId, apiCallsArrayList); - log.error(description); + //log.error(description); + if (log.isDebugEnabled()) { + log.debug(description); + } return new PreconditionFailedException(retryErrorResponse); } @@ -252,14 +271,29 @@ private static String getContext(String tenantDomain, String endpoint, String ba /** * Builds error response. * + * @param errorCode Error code. + * @param errorMessage Error message. + * @param errorDescription Error description. + * @return ErrorResponse. + */ + private static ErrorResponse buildErrorResponse(String errorCode, String errorMessage, String errorDescription) { + + ErrorResponse errorResponse = getErrorBuilder(errorCode, errorMessage, errorDescription).build(log, + errorMessage); + return errorResponse; + } + + /** + * Builds server error response. + * * @param e Identity Recovery Exception. * @param errorCode Error code. * @param errorMessage Error message. * @param errorDescription Error description. * @return ErrorResponse. */ - private static ErrorResponse buildErrorResponse(IdentityRecoveryException e, String errorCode, String errorMessage, - String errorDescription) { + private static ErrorResponse buildServerErrorResponse(IdentityRecoveryException e, String errorCode, + String errorMessage, String errorDescription) { ErrorResponse errorResponse = getErrorBuilder(errorCode, errorMessage, errorDescription).build(log, e, errorMessage); From da0025d1be8455d8f69669c5faa63f4e72f1712a Mon Sep 17 00:00:00 2001 From: Rashmini Date: Mon, 25 Sep 2023 14:35:36 +0530 Subject: [PATCH 15/17] Remove unwanted comment --- .../rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java | 1 - 1 file changed, 1 deletion(-) diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java index 8676a77e..163dbf66 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java @@ -220,7 +220,6 @@ public static PreconditionFailedException buildRetryPasswordResetObject(String t RetryErrorResponse retryErrorResponse = buildRetryErrorResponse( Constants.STATUS_PRECONDITION_FAILED_MESSAGE_DEFAULT, code, description, resetCode, correlationId, apiCallsArrayList); - //log.error(description); if (log.isDebugEnabled()) { log.debug(description); } From 8a5d4f0274d4bc026253b69400b0714ad6acf7a7 Mon Sep 17 00:00:00 2001 From: Rashmini Date: Mon, 25 Sep 2023 16:59:34 +0530 Subject: [PATCH 16/17] Fix comments --- .../v2/impl/core/PasswordRecoveryService.java | 30 ++++++++++++------- .../v2/impl/core/UsernameRecoveryService.java | 18 ++++++----- .../v2/impl/core/utils/RecoveryUtil.java | 16 ++++------ 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java index f5cbf7a9..4659fa6b 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java @@ -89,8 +89,10 @@ public Response initiatePasswordRecovery(InitRequest initRequest) { .build(); } catch (IdentityRecoveryClientException e) { if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleException(e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.CONFLICT); + throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), + Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, + Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, + Response.Status.INTERNAL_SERVER_ERROR); } String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO); @@ -164,8 +166,10 @@ public Response recoverPassword(RecoveryRequest recoveryRequest) { passwordRecoverDTO); } catch (IdentityRecoveryClientException e) { if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleException(e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.CONFLICT); + throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), + Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, + Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, + Response.Status.INTERNAL_SERVER_ERROR); } String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO); @@ -215,8 +219,10 @@ public Response confirmRecovery(ConfirmRequest confirmRequest) { return Response.ok().entity(buildResetCodeResponse(tenantDomain, passwordResetCodeDTO)).build(); } catch (IdentityRecoveryClientException e) { if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleException(e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.CONFLICT); + throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), + Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, + Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, + Response.Status.INTERNAL_SERVER_ERROR); } String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO); @@ -266,8 +272,10 @@ public Response resetPassword(ResetRequest resetRequest) { return Response.ok().entity(buildPasswordResetResponse(successfulPasswordResetDTO)).build(); } catch (IdentityRecoveryClientException e) { if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleException(e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.CONFLICT); + throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), + Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, + Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, + Response.Status.INTERNAL_SERVER_ERROR); } String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO); @@ -329,8 +337,10 @@ public Response resendConfirmation(ResendConfirmationRequest resendConfirmationR return buildResendConfirmationResponse(tenantDomain, resendConfirmationDTO); } catch (IdentityRecoveryClientException e) { if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleException(e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.CONFLICT); + throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), + Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, + Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, + Response.Status.INTERNAL_SERVER_ERROR); } String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO); diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java index 46b822c1..4b7af102 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java @@ -72,18 +72,18 @@ public Response initiateUsernameRecovery(InitRequest initRequest) { RecoveryUtil.buildPropertiesMap(initRequest.getProperties())); if (recoveryInformationDTO == null) { // If RecoveryChannelInfoDTO is null throw not found error. - if (log.isDebugEnabled()) { - String message = "No recovery information username recovery request"; - log.debug(message); - } + String message = "No recovery information username recovery request"; + log.debug(message); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } return Response.ok().entity(buildUsernameRecoveryInitResponse(recoveryInformationDTO, tenantDomain)) .build(); } catch (IdentityRecoveryClientException e) { if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleException(e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.CONFLICT); + throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), + Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, + Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, + Response.Status.INTERNAL_SERVER_ERROR); } String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), IdentityRecoveryConstants.USER_NAME_RECOVERY); @@ -152,8 +152,10 @@ public Response recoverUsername(RecoveryRequest recoveryRequest) { return buildUsernameRecoveryResponse(usernameRecoverDTO.getNotificationChannel(), usernameRecoverDTO); } catch (IdentityRecoveryClientException e) { if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleException(e.getErrorCode(), Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.CONFLICT); + throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), + Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, + Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, + Response.Status.INTERNAL_SERVER_ERROR); } String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), IdentityRecoveryConstants.USER_NAME_RECOVERY); diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java index 163dbf66..d4e5a3c3 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java @@ -54,7 +54,7 @@ */ public class RecoveryUtil { - private static final Log log = LogFactory.getLog(RecoveryUtil.class); + private static final Log LOG = LogFactory.getLog(RecoveryUtil.class); /** * Converts a list of UserClaim in to a UserClaim array. @@ -156,7 +156,7 @@ public static String buildURIForBody(String tenantDomain, String endpoint, Strin .withCode(UNEXPECTED_SERVER_ERROR.getCode()) .withMessage("Error while building response.") .withDescription(errorDescription) - .build(log, e, errorDescription); + .build(LOG, e, errorDescription); Response.Status status = Response.Status.INTERNAL_SERVER_ERROR; throw new APIError(status, errorResponse); @@ -220,9 +220,7 @@ public static PreconditionFailedException buildRetryPasswordResetObject(String t RetryErrorResponse retryErrorResponse = buildRetryErrorResponse( Constants.STATUS_PRECONDITION_FAILED_MESSAGE_DEFAULT, code, description, resetCode, correlationId, apiCallsArrayList); - if (log.isDebugEnabled()) { - log.debug(description); - } + LOG.debug(description); return new PreconditionFailedException(retryErrorResponse); } @@ -277,9 +275,7 @@ private static String getContext(String tenantDomain, String endpoint, String ba */ private static ErrorResponse buildErrorResponse(String errorCode, String errorMessage, String errorDescription) { - ErrorResponse errorResponse = getErrorBuilder(errorCode, errorMessage, errorDescription).build(log, - errorMessage); - return errorResponse; + return getErrorBuilder(errorCode, errorMessage, errorDescription).build(LOG, errorMessage); } /** @@ -294,9 +290,7 @@ private static ErrorResponse buildErrorResponse(String errorCode, String errorMe private static ErrorResponse buildServerErrorResponse(IdentityRecoveryException e, String errorCode, String errorMessage, String errorDescription) { - ErrorResponse errorResponse = getErrorBuilder(errorCode, errorMessage, errorDescription).build(log, e, - errorMessage); - return errorResponse; + return getErrorBuilder(errorCode, errorMessage, errorDescription).build(LOG, e, errorMessage); } /** From 089d7d6472464375905b2d59aff6abdbd8caec21 Mon Sep 17 00:00:00 2001 From: Rashmini Date: Tue, 26 Sep 2023 10:53:34 +0530 Subject: [PATCH 17/17] Refactor error handling --- .../v2/impl/core/PasswordRecoveryService.java | 185 ++-------------- .../v2/impl/core/UsernameRecoveryService.java | 82 +------ .../v2/impl/core/utils/RecoveryUtil.java | 200 +++++++++++++----- 3 files changed, 165 insertions(+), 302 deletions(-) diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java index 4659fa6b..31d01193 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/PasswordRecoveryService.java @@ -18,15 +18,12 @@ package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core; -import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.identity.api.user.common.Util; import org.wso2.carbon.identity.api.user.recovery.commons.UserAccountRecoveryServiceDataHolder; -import org.wso2.carbon.identity.core.util.IdentityUtil; import org.wso2.carbon.identity.governance.service.notification.NotificationChannels; -import org.wso2.carbon.identity.recovery.IdentityRecoveryClientException; import org.wso2.carbon.identity.recovery.IdentityRecoveryConstants; import org.wso2.carbon.identity.recovery.IdentityRecoveryException; import org.wso2.carbon.identity.recovery.dto.PasswordRecoverDTO; @@ -56,7 +53,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; /** @@ -87,51 +83,9 @@ public Response initiatePasswordRecovery(InitRequest initRequest) { RecoveryUtil.buildPropertiesMap(initRequest.getProperties())); return Response.ok().entity(buildPasswordRecoveryInitResponse(tenantDomain, recoveryInformationDTO)) .build(); - } catch (IdentityRecoveryClientException e) { - if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), - Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, - Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, - Response.Status.INTERNAL_SERVER_ERROR); - } - String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), - IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO); - if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_DISABLED_ACCOUNT.getCode().equals(e.getErrorCode()) - || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_LOCKED_ACCOUNT.getCode().equals( - e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages. - ERROR_CODE_PASSWORD_RECOVERY_NOT_ENABLED.getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.FORBIDDEN); - } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_MULTIPLE_MATCHING_USERS.getCode().equals( - e.getErrorCode())) { - // If user notify is not enabled, throw a accepted response. - if (!Boolean.parseBoolean(IdentityUtil - .getProperty(IdentityRecoveryConstants.ConnectorConfig.NOTIFY_USER_EXISTENCE))) { - throw new WebApplicationException(Response.accepted().build()); - } - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.CONFLICT); - } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_USER_FOUND.getCode().equals( - e.getErrorCode())) { - // If user notify is not enabled, throw a accepted response. - if (!Boolean.parseBoolean(IdentityUtil - .getProperty(IdentityRecoveryConstants.ConnectorConfig.NOTIFY_USER_EXISTENCE))) { - throw new WebApplicationException(Response.accepted().build()); - } - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.NOT_FOUND); - } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_VERIFIED_CHANNELS_FOR_USER. - getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.NOT_FOUND); - } else { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.CONFLICT); - } } catch (IdentityRecoveryException e) { - throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), - Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, - Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); + throw RecoveryUtil.handleIdentityRecoveryException(e, tenantDomain, + IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation()); } } @@ -164,38 +118,9 @@ public Response recoverPassword(RecoveryRequest recoveryRequest) { } return buildPasswordRecoveryResponse(tenantDomain, passwordRecoverDTO.getNotificationChannel(), passwordRecoverDTO); - } catch (IdentityRecoveryClientException e) { - if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), - Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, - Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, - Response.Status.INTERNAL_SERVER_ERROR); - } - String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), - IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO); - if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_RECOVERY_WITH_NOTIFICATIONS_NOT_ENABLED. - getCode().equals(e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages. - ERROR_CODE_DISABLED_ACCOUNT.getCode().equals(e.getErrorCode()) || IdentityRecoveryConstants. - ErrorMessages.ERROR_CODE_LOCKED_ACCOUNT.getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.FORBIDDEN); - } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_ACCOUNT_RECOVERY_DATA.getCode().equals( - e.getErrorCode())) { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.NOT_FOUND); - } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals( - e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_EXPIRED_RECOVERY_CODE - .getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.NOT_ACCEPTABLE); - } else { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.CONFLICT); - } } catch (IdentityRecoveryException e) { - throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), - Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, - Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); + throw RecoveryUtil.handleIdentityRecoveryException(e, tenantDomain, + IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation()); } } @@ -217,36 +142,9 @@ public Response confirmRecovery(ConfirmRequest confirmRequest) { .confirm(confirmRequest.getOtp(), confirmRequest.getConfirmationCode(), tenantDomain, RecoveryUtil.buildPropertiesMap(confirmRequest.getProperties())); return Response.ok().entity(buildResetCodeResponse(tenantDomain, passwordResetCodeDTO)).build(); - } catch (IdentityRecoveryClientException e) { - if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), - Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, - Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, - Response.Status.INTERNAL_SERVER_ERROR); - } - String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), - IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO); - if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_USER_TENANT_DOMAIN_MISS_MATCH_WITH_CONTEXT.getCode(). - equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.CONFLICT); - } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_ACCOUNT_RECOVERY_DATA.getCode().equals( - e.getErrorCode())) { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.NOT_FOUND); - } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals( - e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_EXPIRED_RECOVERY_CODE - .getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.NOT_ACCEPTABLE); - } else { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.CONFLICT); - } } catch (IdentityRecoveryException e) { - throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), - Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, - Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); + throw RecoveryUtil.handleIdentityRecoveryException(e, tenantDomain, + IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation()); } } @@ -270,42 +168,11 @@ public Response resetPassword(ResetRequest resetRequest) { .reset(resetRequest.getResetCode(), resetRequest.getFlowConfirmationCode(), password, RecoveryUtil.buildPropertiesMap(resetRequest.getProperties())); return Response.ok().entity(buildPasswordResetResponse(successfulPasswordResetDTO)).build(); - } catch (IdentityRecoveryClientException e) { - if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), - Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, - Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, - Response.Status.INTERNAL_SERVER_ERROR); - } - String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), - IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO); - if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_USER_TENANT_DOMAIN_MISS_MATCH_WITH_CONTEXT.getCode(). - equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.CONFLICT); - } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_ACCOUNT_RECOVERY_DATA.getCode().equals( - e.getErrorCode())) { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.NOT_FOUND); - } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals( - e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_EXPIRED_RECOVERY_CODE. - getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.NOT_ACCEPTABLE); - } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_HISTORY_VIOLATION.getCode().equals( - e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_POLICY_VIOLATION. - getCode().equals(e.getErrorCode())) { - // Send the reset code again for a retry attempt. - throw RecoveryUtil.buildRetryPasswordResetObject(tenantDomain, e.getMessage(), errorCode, - resetRequest.getResetCode(), Util.getCorrelation()); - } else { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.CONFLICT); - } } catch (IdentityRecoveryException e) { - throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), - Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, - Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); + // Send the reset code again for a retry attempt. + throw RecoveryUtil.handleIdentityRecoveryException(e, tenantDomain, + IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, resetRequest.getResetCode(), + Util.getCorrelation()); } } @@ -335,37 +202,9 @@ public Response resendConfirmation(ResendConfirmationRequest resendConfirmationR return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } return buildResendConfirmationResponse(tenantDomain, resendConfirmationDTO); - } catch (IdentityRecoveryClientException e) { - if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), - Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, - Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, - Response.Status.INTERNAL_SERVER_ERROR); - } - String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), - IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO); - if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_USER_TENANT_DOMAIN_MISS_MATCH_WITH_CONTEXT.getCode(). - equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.CONFLICT); - } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_ACCOUNT_RECOVERY_DATA.getCode().equals( - e.getErrorCode())) { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.NOT_FOUND); - } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals( - e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RESEND_CODE. - getCode().equals(e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages. - ERROR_CODE_EXPIRED_RECOVERY_CODE.getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.NOT_ACCEPTABLE); - } else { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.CONFLICT); - } } catch (IdentityRecoveryException e) { - throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), - Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, - Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); + throw RecoveryUtil.handleIdentityRecoveryException(e, tenantDomain, + IdentityRecoveryConstants.PASSWORD_RECOVERY_SCENARIO, Util.getCorrelation()); } } diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java index 4b7af102..c0e8fc29 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/UsernameRecoveryService.java @@ -18,15 +18,13 @@ package org.wso2.carbon.identity.rest.api.user.recovery.v2.impl.core; -import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.identity.api.user.common.Util; import org.wso2.carbon.identity.api.user.recovery.commons.UserAccountRecoveryServiceDataHolder; -import org.wso2.carbon.identity.core.util.IdentityUtil; import org.wso2.carbon.identity.governance.service.notification.NotificationChannels; -import org.wso2.carbon.identity.recovery.IdentityRecoveryClientException; import org.wso2.carbon.identity.recovery.IdentityRecoveryConstants; import org.wso2.carbon.identity.recovery.IdentityRecoveryException; import org.wso2.carbon.identity.recovery.dto.RecoveryChannelInfoDTO; @@ -45,7 +43,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; /** @@ -78,51 +75,9 @@ public Response initiateUsernameRecovery(InitRequest initRequest) { } return Response.ok().entity(buildUsernameRecoveryInitResponse(recoveryInformationDTO, tenantDomain)) .build(); - } catch (IdentityRecoveryClientException e) { - if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), - Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, - Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, - Response.Status.INTERNAL_SERVER_ERROR); - } - String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), - IdentityRecoveryConstants.USER_NAME_RECOVERY); - if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_USERNAME_RECOVERY_NOT_ENABLED.getCode().equals( - e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_DISABLED_ACCOUNT.getCode(). - equals(e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_LOCKED_ACCOUNT. - getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.FORBIDDEN); - } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_MULTIPLE_MATCHING_USERS.getCode().equals( - e.getErrorCode())) { - // If user notify is not enabled, throw a accepted response. - if (!Boolean.parseBoolean(IdentityUtil - .getProperty(IdentityRecoveryConstants.ConnectorConfig.NOTIFY_USER_EXISTENCE))) { - throw new WebApplicationException(Response.accepted().build()); - } - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.CONFLICT); - } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_USER_FOUND.getCode().equals( - e.getErrorCode())) { - // If user notify is not enabled, throw a accepted response. - if (!Boolean.parseBoolean(IdentityUtil - .getProperty(IdentityRecoveryConstants.ConnectorConfig.NOTIFY_USER_EXISTENCE))) { - throw new WebApplicationException(Response.accepted().build()); - } - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.NOT_FOUND); - } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_VERIFIED_CHANNELS_FOR_USER. - getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.NOT_FOUND); - } else { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.CONFLICT); - } } catch (IdentityRecoveryException e) { - throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), - Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, - Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); + throw RecoveryUtil.handleIdentityRecoveryException(e, tenantDomain, + IdentityRecoveryConstants.USER_NAME_RECOVERY, Util.getCorrelation()); } } @@ -150,36 +105,9 @@ public Response recoverUsername(RecoveryRequest recoveryRequest) { return Response.status(Response.Status.OK).build(); } return buildUsernameRecoveryResponse(usernameRecoverDTO.getNotificationChannel(), usernameRecoverDTO); - } catch (IdentityRecoveryClientException e) { - if (StringUtils.isEmpty(e.getErrorCode())) { - throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), - Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, - Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, - Response.Status.INTERNAL_SERVER_ERROR); - } - String errorCode = RecoveryUtil.prependOperationScenarioToErrorCode(e.getErrorCode(), - IdentityRecoveryConstants.USER_NAME_RECOVERY); - if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_USERNAME_RECOVERY_NOT_ENABLED.getCode().equals( - e.getErrorCode())) { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.FORBIDDEN); - } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_ACCOUNT_RECOVERY_DATA.getCode().equals( - e.getErrorCode())) { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.NOT_FOUND); - } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals( - e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_EXPIRED_RECOVERY_CODE. - getCode().equals(e.getErrorCode())) { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.NOT_ACCEPTABLE); - } else { - throw RecoveryUtil.handleException(errorCode, Constants.STATUS_CONFLICT_MESSAGE_DEFAULT, - e.getMessage(), Response.Status.CONFLICT); - } } catch (IdentityRecoveryException e) { - throw RecoveryUtil.handleInternalServerError(e, e.getErrorCode(), - Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT, - Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT, Response.Status.INTERNAL_SERVER_ERROR); + throw RecoveryUtil.handleIdentityRecoveryException(e, tenantDomain, + IdentityRecoveryConstants.USER_NAME_RECOVERY, Util.getCorrelation()); } } diff --git a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java index d4e5a3c3..d8c727df 100644 --- a/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java +++ b/components/org.wso2.carbon.identity.api.user.recovery/org.wso2.carbon.identity.rest.api.user.recovery.v2/src/main/java/org/wso2/carbon/identity/rest/api/user/recovery/v2/impl/core/utils/RecoveryUtil.java @@ -27,6 +27,8 @@ import org.wso2.carbon.identity.core.ServiceURLBuilder; import org.wso2.carbon.identity.core.URLBuilderException; import org.wso2.carbon.identity.core.util.IdentityTenantUtil; +import org.wso2.carbon.identity.core.util.IdentityUtil; +import org.wso2.carbon.identity.recovery.IdentityRecoveryClientException; import org.wso2.carbon.identity.recovery.IdentityRecoveryConstants; import org.wso2.carbon.identity.recovery.IdentityRecoveryException; import org.wso2.carbon.identity.recovery.dto.NotificationChannelDTO; @@ -44,6 +46,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; import static org.wso2.carbon.identity.api.user.common.Constants.TENANT_CONTEXT_PATH_COMPONENT; @@ -164,6 +167,99 @@ public static String buildURIForBody(String tenantDomain, String endpoint, Strin return url; } + /** + * Handle errors with specific http codes. + * + * @param e Identity Recovery Exception. + * @param tenantDomain Tenant domain. + * @param scenario Recovery scenario. + * @param correlationId Correlation Id. + * @return WebApplicationException (NOTE: Returns null when the client error is for no user available or for + * multiple users available. + */ + public static WebApplicationException handleIdentityRecoveryException(IdentityRecoveryException e, + String tenantDomain, String scenario, + String correlationId) { + + return handleIdentityRecoveryException(e, tenantDomain, scenario, StringUtils.EMPTY, correlationId); + } + + /** + * Handle errors with specific http codes. + * + * @param e Identity Recovery Exception. + * @param scenario Recovery scenario. + * @param tenantDomain Tenant domain. + * @param code Recovery code. + * @param correlationId Correlation Id. + * @return WebApplicationException (NOTE: Returns null when the client error is for no user available or for + * multiple users available. + */ + public static WebApplicationException handleIdentityRecoveryException(IdentityRecoveryException e, + String tenantDomain, String scenario, + String code, String correlationId) { + + String errorCode = prependOperationScenarioToErrorCode(e.getErrorCode(), scenario); + String errorDescription = e.getMessage(); + String serverErrorDescription = Constants.STATUS_INTERNAL_SERVER_ERROR_DESCRIPTION_DEFAULT; + String errorMessage = Constants.STATUS_INTERNAL_SERVER_ERROR_MESSAGE_DEFAULT; + Response.Status status = Response.Status.INTERNAL_SERVER_ERROR; + + if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_RECOVERY_WITH_NOTIFICATIONS_NOT_ENABLED. + getCode().equals(e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages. + ERROR_CODE_USERNAME_RECOVERY_NOT_ENABLED.getCode().equals(e.getErrorCode()) || + IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_DISABLED_ACCOUNT.getCode().equals(e.getErrorCode()) + || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_LOCKED_ACCOUNT.getCode().equals(e.getErrorCode()) + || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_RECOVERY_NOT_ENABLED.getCode().equals( + e.getErrorCode())) { + errorMessage = Constants.STATUS_FORBIDDEN_MESSAGE_DEFAULT; + status = Response.Status.FORBIDDEN; + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_USER_TENANT_DOMAIN_MISS_MATCH_WITH_CONTEXT. + getCode().equals(e.getErrorCode())) { + errorMessage = Constants.STATUS_CONFLICT_MESSAGE_DEFAULT; + status = Response.Status.CONFLICT; + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_MULTIPLE_MATCHING_USERS.getCode().equals( + e.getErrorCode())) { + // If user notify is not enabled, throw an accepted response. + if (!Boolean.parseBoolean(IdentityUtil + .getProperty(IdentityRecoveryConstants.ConnectorConfig.NOTIFY_USER_EXISTENCE))) { + return new WebApplicationException(Response.accepted().build()); + } + errorMessage = Constants.STATUS_CONFLICT_MESSAGE_DEFAULT; + status = Response.Status.CONFLICT; + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_USER_FOUND.getCode().equals(e. + getErrorCode())) { + // If user notify is not enabled, throw an accepted response. + if (!Boolean.parseBoolean(IdentityUtil + .getProperty(IdentityRecoveryConstants.ConnectorConfig.NOTIFY_USER_EXISTENCE))) { + return new WebApplicationException(Response.accepted().build()); + } + errorMessage = Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT; + status = Response.Status.NOT_FOUND; + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_ACCOUNT_RECOVERY_DATA.getCode().equals( + e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_VERIFIED_CHANNELS_FOR_USER. + getCode().equals(e.getErrorCode())) { + errorMessage = Constants.STATUS_NOT_FOUND_MESSAGE_DEFAULT; + status = Response.Status.NOT_FOUND; + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals( + e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RESEND_CODE.getCode(). + equals(e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_EXPIRED_RECOVERY_CODE. + getCode().equals(e.getErrorCode())) { + errorMessage = Constants.STATUS_METHOD_NOT_ACCEPTED_MESSAGE_DEFAULT; + status = Response.Status.NOT_ACCEPTABLE; + } else if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_HISTORY_VIOLATION.getCode().equals( + e.getErrorCode()) || IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PASSWORD_POLICY_VIOLATION. + getCode().equals(e.getErrorCode())) { + return RecoveryUtil.buildRetryPasswordResetObject(tenantDomain, errorDescription, errorCode, code, + correlationId); + } + + if (e instanceof IdentityRecoveryClientException) { + return buildClientError(errorCode, errorMessage, errorDescription, status); + } + return buildServerError(e, e.getErrorCode(), errorMessage, serverErrorDescription, status); + } + /** * Builds API error to be thrown. * @@ -173,7 +269,7 @@ public static String buildURIForBody(String tenantDomain, String endpoint, Strin * @param status HTTP status. * @return APIError object which contains the error description. */ - public static APIError handleException(String errorCode, String errorMessage, String errorDescription, + private static APIError buildClientError(String errorCode, String errorMessage, String errorDescription, Response.Status status) { ErrorResponse errorResponse = buildErrorResponse(errorCode, errorMessage, errorDescription); @@ -190,62 +286,13 @@ public static APIError handleException(String errorCode, String errorMessage, St * @param status HTTP status. * @return APIError object which contains the error description. */ - public static APIError handleInternalServerError(IdentityRecoveryException e, String errorCode, String errorMessage, - String errorDescription, Response.Status status) { + private static APIError buildServerError(IdentityRecoveryException e, String errorCode, String errorMessage, + String errorDescription, Response.Status status) { ErrorResponse errorResponse = buildServerErrorResponse(e, errorCode, errorMessage, errorDescription); return new APIError(status, errorResponse); } - /** - * Returns a new PreconditionFailedException. - * - * @param tenantDomain Tenant domain. - * @param description Description of the exception. - * @param code Error code. - * @param resetCode Reset code given to the user by confirmation API. - * @param correlationId Correlation Id. - * @return A new PreconditionFailedException with the specified details as a response. - */ - public static PreconditionFailedException buildRetryPasswordResetObject(String tenantDomain, String description, - String code, String resetCode, - String correlationId) { - - // Build next API calls. - ArrayList apiCallsArrayList = new ArrayList<>(); - apiCallsArrayList.add(RecoveryUtil - .buildApiCall(APICalls.RESET_PASSWORD_API.getType(), Constants.RelationStates.NEXT_REL, - buildURIForBody(tenantDomain, APICalls.RESET_PASSWORD_API.getApiUrl(), - Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); - RetryErrorResponse retryErrorResponse = buildRetryErrorResponse( - Constants.STATUS_PRECONDITION_FAILED_MESSAGE_DEFAULT, code, description, resetCode, correlationId, - apiCallsArrayList); - LOG.debug(description); - return new PreconditionFailedException(retryErrorResponse); - } - - /** - * Prepend the operation scenario to the existing exception error code. - * (Eg: USR-20045) - * - * @param exceptionErrorCode Existing error code. - * @param scenario Operation scenario. - * @return New error code with the scenario prepended. - */ - public static String prependOperationScenarioToErrorCode(String exceptionErrorCode, String scenario) { - - if (StringUtils.isNotEmpty(exceptionErrorCode)) { - if (exceptionErrorCode.contains(IdentityRecoveryConstants.EXCEPTION_SCENARIO_SEPARATOR)) { - return exceptionErrorCode; - } - if (StringUtils.isNotEmpty(scenario)) { - exceptionErrorCode = - scenario + IdentityRecoveryConstants.EXCEPTION_SCENARIO_SEPARATOR + exceptionErrorCode; - } - } - return exceptionErrorCode; - } - /** * Builds the API context on whether the tenant qualified url is enabled or not. In tenant qualified mode the * ServiceURLBuilder appends the tenant domain to the URI as a path param automatically. But @@ -333,4 +380,53 @@ private static RetryErrorResponse buildRetryErrorResponse(String message, String retryErrorResponse.setLinks(apiCallsArrayList); return retryErrorResponse; } + + /** + * Returns a new PreconditionFailedException. + * + * @param tenantDomain Tenant domain. + * @param description Description of the exception. + * @param code Error code. + * @param resetCode Reset code given to the user by confirmation API. + * @param correlationId Correlation Id. + * @return A new PreconditionFailedException with the specified details as a response. + */ + private static PreconditionFailedException buildRetryPasswordResetObject(String tenantDomain, String description, + String code, String resetCode, + String correlationId) { + + // Build next API calls. + ArrayList apiCallsArrayList = new ArrayList<>(); + apiCallsArrayList.add(RecoveryUtil + .buildApiCall(APICalls.RESET_PASSWORD_API.getType(), Constants.RelationStates.NEXT_REL, + buildURIForBody(tenantDomain, APICalls.RESET_PASSWORD_API.getApiUrl(), + Constants.ACCOUNT_RECOVERY_ENDPOINT_BASEPATH), null)); + RetryErrorResponse retryErrorResponse = buildRetryErrorResponse( + Constants.STATUS_PRECONDITION_FAILED_MESSAGE_DEFAULT, code, description, resetCode, correlationId, + apiCallsArrayList); + LOG.debug(description); + return new PreconditionFailedException(retryErrorResponse); + } + + /** + * Prepend the operation scenario to the existing exception error code. + * (Eg: USR-20045) + * + * @param exceptionErrorCode Existing error code. + * @param scenario Operation scenario. + * @return New error code with the scenario prepended. + */ + private static String prependOperationScenarioToErrorCode(String exceptionErrorCode, String scenario) { + + if (StringUtils.isNotEmpty(exceptionErrorCode)) { + if (exceptionErrorCode.contains(IdentityRecoveryConstants.EXCEPTION_SCENARIO_SEPARATOR)) { + return exceptionErrorCode; + } + if (StringUtils.isNotEmpty(scenario)) { + exceptionErrorCode = + scenario + IdentityRecoveryConstants.EXCEPTION_SCENARIO_SEPARATOR + exceptionErrorCode; + } + } + return exceptionErrorCode; + } }