Skip to content

Commit

Permalink
Move deserialize logic to ServerActionManagementService
Browse files Browse the repository at this point in the history
  • Loading branch information
ashanthamara committed Jan 21, 2025
1 parent 1bea095 commit b34a578
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -99,33 +99,9 @@ public Response activateAction(@ApiParam(value = "Name of the Action Type.",requ
@ApiResponse(code = 500, message = "Server Error", response = Error.class),
@ApiResponse(code = 501, message = "Not Implemented", response = Error.class)
})
public Response createAction(@ApiParam(value = "Name of the Action Type.",required=true, allowableValues="preIssueAccessToken, preUpdatePassword, preUpdateProfile, preRegistration") @PathParam("actionType") String actionType, @ApiParam(value = "This represents the information of the action to be created." ,required=true) @Valid String jsonPayload)
throws JsonProcessingException{
public Response createAction(@ApiParam(value = "Name of the Action Type.",required=true, allowableValues="preIssueAccessToken, preUpdatePassword, preUpdateProfile, preRegistration") @PathParam("actionType") String actionType, @ApiParam(value = "This represents the information of the action to be created." ,required=true) @Valid String body) {

ActionModel actionModel = null;
ObjectMapper objectMapper = new ObjectMapper();
switch (actionType) {
case "preIssueAccessToken":
actionModel = objectMapper.readValue(jsonPayload, ActionModel.class);
break;
case "preUpdatePassword":
actionModel = objectMapper.readValue(jsonPayload, PreUpdatePasswordActionModel.class);
// Validate the object
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<PreUpdatePasswordActionModel>> violations =
validator.validate((PreUpdatePasswordActionModel) actionModel);

// Check for violations
if (!violations.isEmpty()) {
throw new ConstraintViolationException(violations);
}
break;
default:
break;
}

return delegate.createAction(actionType, actionModel);
return delegate.createAction(actionType, body);
}

@Valid
Expand Down Expand Up @@ -269,32 +245,8 @@ public Response getActionsByActionType(@ApiParam(value = "Name of the Action Typ
@ApiResponse(code = 500, message = "Server Error", response = Error.class),
@ApiResponse(code = 501, message = "Not Implemented", response = Error.class)
})
public Response updateAction(@ApiParam(value = "Name of the Action Type.",required=true, allowableValues="preIssueAccessToken, preUpdatePassword, preUpdateProfile, preRegistration") @PathParam("actionType") String actionType, @ApiParam(value = "Unique identifier of the action.",required=true) @PathParam("actionId") String actionId, @ApiParam(value = "This represents the action to be updated." ,required=true) @Valid String jsonPayload)
throws JsonProcessingException{

ActionUpdateModel actionUpdateModel = null;
ObjectMapper objectMapper = new ObjectMapper();
switch (actionType) {
case "preIssueAccessToken":
actionUpdateModel = objectMapper.readValue(jsonPayload, ActionUpdateModel.class);
break;
case "preUpdatePassword":
actionUpdateModel = objectMapper.readValue(jsonPayload, PreUpdatePasswordActionUpdateModel.class);
// Validate the object
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<PreUpdatePasswordActionUpdateModel>> violations =
validator.validate((PreUpdatePasswordActionUpdateModel) actionUpdateModel);
public Response updateAction(@ApiParam(value = "Name of the Action Type.",required=true, allowableValues="preIssueAccessToken, preUpdatePassword, preUpdateProfile, preRegistration") @PathParam("actionType") String actionType, @ApiParam(value = "Unique identifier of the action.",required=true) @PathParam("actionId") String actionId, @ApiParam(value = "This represents the action to be updated." ,required=true) @Valid String body) {

// Check for violations
if (!violations.isEmpty()) {
throw new ConstraintViolationException(violations);
}
break;
default:
break;
}

return delegate.updateAction(actionType, actionId, body );
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public interface ActionsApiService {

public Response activateAction(String actionType, String actionId);

public Response createAction(String actionType, ActionModel actionModel);
public Response createAction(String actionType, String body);

public Response deactivateAction(String actionType, String actionId);

Expand All @@ -49,5 +49,5 @@ public interface ActionsApiService {

public Response getActionsByActionType(String actionType);

public Response updateAction(String actionType, String actionId, ActionUpdateModel actionUpdateModel);
public Response updateAction(String actionType, String actionId, String body);
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ public enum ErrorMessage {
ERROR_INVALID_RULE("60013", "Invalid rule.", "%s"),
ERROR_NO_ACTION_BUILDER_FOUND("60014", "Action builder not found.",
"No action builder found for the given action type."),
ERROR_INVALID_PAYLOAD("60015", "Invalid Request body.",
"Provided request body content is not in the expected format."),

// Server errors.
ERROR_NOT_IMPLEMENTED_ACTION_TYPE("650015",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@
import org.wso2.carbon.identity.action.management.model.Action;
import org.wso2.carbon.identity.api.server.action.management.common.ActionManagementServiceHolder;
import org.wso2.carbon.identity.api.server.action.management.v1.ActionBasicResponse;
import org.wso2.carbon.identity.api.server.action.management.v1.builder.ActionBuilder;
import org.wso2.carbon.identity.api.server.action.management.v1.ActionModel;
import org.wso2.carbon.identity.api.server.action.management.v1.ActionResponse;
import org.wso2.carbon.identity.api.server.action.management.v1.ActionType;
import org.wso2.carbon.identity.api.server.action.management.v1.ActionTypesResponseItem;
import org.wso2.carbon.identity.api.server.action.management.v1.ActionUpdateModel;
import org.wso2.carbon.identity.api.server.action.management.v1.builder.ActionBuilder;
import org.wso2.carbon.identity.api.server.action.management.v1.util.ActionBuilderUtil;
import org.wso2.carbon.identity.api.server.action.management.v1.util.ActionDeserializer;
import org.wso2.carbon.identity.api.server.action.management.v1.util.ActionMgtEndpointUtil;

import java.util.ArrayList;
Expand Down Expand Up @@ -61,13 +62,14 @@ public class ServerActionManagementService {
NOT_IMPLEMENTED_ACTION_TYPES.add(Action.ActionTypes.AUTHENTICATION.getPathParam());
}

public ActionResponse createAction(String actionType, ActionModel actionModel) {
public ActionResponse createAction(String actionType, String jsonBody) {

try {
Action.ActionTypes validatedActionType = validateActionType(actionType);
Action action = buildAction(validatedActionType, jsonBody);
String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain();
return buildActionResponse(ActionManagementServiceHolder.getActionManagementService()
.addAction(actionType, buildAction(validatedActionType, actionModel), tenantDomain));
.addAction(actionType, action, tenantDomain));
} catch (ActionMgtException e) {
throw ActionMgtEndpointUtil.handleActionMgtException(e);
}
Expand Down Expand Up @@ -110,14 +112,14 @@ public ActionResponse getActionByActionId(String actionType, String actionId) {
}
}

public ActionResponse updateAction(String actionType, String actionId, ActionUpdateModel actionUpdateModel) {
public ActionResponse updateAction(String actionType, String actionId, String jsonBody) {

try {
Action.ActionTypes validatedActionType = validateActionType(actionType);
Action updatingAction = buildUpdatingAction(validatedActionType, jsonBody);
String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain();
return buildActionResponse(ActionManagementServiceHolder.getActionManagementService()
.updateAction(actionType, actionId,
buildUpdatingAction(validatedActionType, actionUpdateModel), tenantDomain));
.updateAction(actionType, actionId, updatingAction, tenantDomain));
} catch (ActionMgtException e) {
throw ActionMgtEndpointUtil.handleActionMgtException(e);
}
Expand Down Expand Up @@ -203,29 +205,31 @@ private ActionResponse buildActionResponse(Action action) throws ActionMgtExcept
/**
* Build Action from the ActionModel.
*
* @param actionType Action Type.
* @param actionModel Action Model.
* @param actionType Action Type.
* @param jsonBody JSON body.
* @return Action.
* @throws ActionMgtException If an error occurs while building the Action.
*/
private Action buildAction(Action.ActionTypes actionType, ActionModel actionModel)
private Action buildAction(Action.ActionTypes actionType, String jsonBody)
throws ActionMgtException {

ActionModel actionModel = ActionDeserializer.deserializeActionModel(actionType, jsonBody);
ActionBuilder actionBuilder = ActionBuilderUtil.getActionBuilder(actionType);
return actionBuilder.buildAction(actionModel);
}

/**
* Build Action from the ActionUpdateModel.
*
* @param actionType Action Type.
* @param actionUpdateModel Action Update Model.
* @param actionType Action Type.
* @param jsonBody JSON body.
* @return Action.
* @throws ActionMgtException If an error occurs while building the Action.
*/
private Action buildUpdatingAction(Action.ActionTypes actionType, ActionUpdateModel actionUpdateModel)
private Action buildUpdatingAction(Action.ActionTypes actionType, String jsonBody)
throws ActionMgtException {

ActionUpdateModel actionUpdateModel = ActionDeserializer.deserializeActionUpdateModel(actionType, jsonBody);
ActionBuilder actionBuilder = ActionBuilderUtil.getActionBuilder(actionType);
return actionBuilder.buildAction(actionUpdateModel);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ public Response activateAction(String actionType, String actionId) {
}

@Override
public Response createAction(String actionType, ActionModel actionModel) {
public Response createAction(String actionType, String body) {

ActionResponse actionResponse = serverActionManagementService.createAction(actionType, actionModel);
ActionResponse actionResponse = serverActionManagementService.createAction(actionType, body);
URI location = ContextLoader.buildURIForHeader(V1_API_PATH_COMPONENT +
ActionMgtEndpointConstants.ACTION_PATH_COMPONENT + "/" + actionResponse.getId());
return Response.created(location).entity(actionResponse).build();
Expand Down Expand Up @@ -88,9 +88,8 @@ public Response getActionsByActionType(String actionType) {
}

@Override
public Response updateAction(String actionType, String actionId, ActionUpdateModel actionUpdateModel) {
public Response updateAction(String actionType, String actionId, String body) {

return Response.ok().entity(serverActionManagementService.updateAction(actionType, actionId, actionUpdateModel))
.build();
return Response.ok().entity(serverActionManagementService.updateAction(actionType, actionId, body)).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* Copyright (c) 2025, 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.api.server.action.management.v1.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.wso2.carbon.identity.action.management.model.Action;
import org.wso2.carbon.identity.api.server.action.management.v1.ActionModel;
import org.wso2.carbon.identity.api.server.action.management.v1.ActionUpdateModel;
import org.wso2.carbon.identity.api.server.action.management.v1.PreUpdatePasswordActionModel;
import org.wso2.carbon.identity.api.server.action.management.v1.PreUpdatePasswordActionUpdateModel;
import org.wso2.carbon.identity.api.server.action.management.v1.constants.ActionMgtEndpointConstants;

import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.ws.rs.core.Response;

/**
* Utility class for action deserialization.
*/
public class ActionDeserializer {

/**
* Deserialize the action model.
*
* @param actionType Action type.
* @param jsonBody JSON body.
* @return Action model.
*/
public static ActionModel deserializeActionModel(Action.ActionTypes actionType, String jsonBody) {

ActionModel actionModel = null;
try {
ObjectMapper objectMapper = new ObjectMapper();
switch (actionType) {
case PRE_ISSUE_ACCESS_TOKEN:
actionModel = objectMapper.readValue(jsonBody, ActionModel.class);
// Validate the object
validateActionModel(actionModel, ActionModel.class);
break;
case PRE_UPDATE_PASSWORD:
actionModel = objectMapper.readValue(jsonBody, PreUpdatePasswordActionModel.class);
// Validate the object
validateActionModel((PreUpdatePasswordActionModel) actionModel, PreUpdatePasswordActionModel.class);
break;
default:
break;
}
} catch (JsonProcessingException e) {
throw ActionMgtEndpointUtil.handleException(Response.Status.BAD_REQUEST,
ActionMgtEndpointConstants.ErrorMessage.ERROR_INVALID_PAYLOAD);
}

return actionModel;
}

/**
* Deserialize the action update model.
*
* @param actionType Action type.
* @param jsonBody JSON body.
* @return Action update model.
*/
public static ActionUpdateModel deserializeActionUpdateModel(Action.ActionTypes actionType, String jsonBody) {

ActionUpdateModel actionUpdateModel = null;
try {
ObjectMapper objectMapper = new ObjectMapper();
switch (actionType) {
case PRE_ISSUE_ACCESS_TOKEN:
actionUpdateModel = objectMapper.readValue(jsonBody, ActionUpdateModel.class);
// Validate the object
validateActionModel(actionUpdateModel, ActionUpdateModel.class);
break;
case PRE_UPDATE_PASSWORD:
actionUpdateModel = objectMapper.readValue(jsonBody, PreUpdatePasswordActionUpdateModel.class);
// Validate the object
validateActionModel((PreUpdatePasswordActionUpdateModel) actionUpdateModel,
PreUpdatePasswordActionUpdateModel.class);
break;
default:
break;
}
} catch (JsonProcessingException e) {
throw ActionMgtEndpointUtil.handleException(Response.Status.BAD_REQUEST,
ActionMgtEndpointConstants.ErrorMessage.ERROR_INVALID_PAYLOAD);
}

return actionUpdateModel;
}

/**
* Validate the action model.
*
* @param actionModel Action model to be validated.
* @param modelClass Class of the action model.
* @param <T> Type of the action model.
*/
private static <T> void validateActionModel(T actionModel, Class<T> modelClass) {

ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<T>> violations = validator.validate(actionModel);

if (!violations.isEmpty()) {
throw new ConstraintViolationException(violations);
}
}
}

0 comments on commit b34a578

Please sign in to comment.