Skip to content

Commit

Permalink
Add action invocation status INCOMPLETE.
Browse files Browse the repository at this point in the history
  • Loading branch information
Thisara-Welmilla committed Jan 6, 2025
1 parent b242fe4 commit c2b8c08
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,16 @@
import org.wso2.carbon.identity.action.execution.model.ActionExecutionStatus;
import org.wso2.carbon.identity.action.execution.model.ActionInvocationErrorResponse;
import org.wso2.carbon.identity.action.execution.model.ActionInvocationFailureResponse;
import org.wso2.carbon.identity.action.execution.model.ActionInvocationIncompleteResponse;
import org.wso2.carbon.identity.action.execution.model.ActionInvocationSuccessResponse;
import org.wso2.carbon.identity.action.execution.model.ActionType;
import org.wso2.carbon.identity.action.execution.model.Error;
import org.wso2.carbon.identity.action.execution.model.ErrorStatus;
import org.wso2.carbon.identity.action.execution.model.Event;
import org.wso2.carbon.identity.action.execution.model.FailedStatus;
import org.wso2.carbon.identity.action.execution.model.Failure;
import org.wso2.carbon.identity.action.execution.model.Incomplete;
import org.wso2.carbon.identity.action.execution.model.IncompleteStatus;
import org.wso2.carbon.identity.action.execution.model.Success;

import java.util.Map;
Expand All @@ -47,6 +50,15 @@ ActionExecutionStatus<Success> processSuccessResponse(Map<String, Object> eventC
ActionInvocationSuccessResponse successResponse) throws
ActionExecutionResponseProcessorException;

default ActionExecutionStatus<Incomplete> processIncompleteResponse(Map<String, Object> eventContext,
Event actionEvent, ActionInvocationIncompleteResponse incompleteResponse) throws
ActionExecutionResponseProcessorException {

return new IncompleteStatus.Builder()
.incomplete(new Incomplete(incompleteResponse.getOperations()))
.responseContext(eventContext).build();
}

default ActionExecutionStatus<Error> processErrorResponse(Map<String, Object> eventContext,
Event actionEvent,
ActionInvocationErrorResponse errorResponse) throws
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,18 @@ public interface ActionExecutorService {
ActionExecutionStatus execute(ActionType actionType, Map<String, Object> eventContext, String tenantDomain) throws
ActionExecutionException;

/**
* Resolve the actions by given the action id list and execute them.
*
* @param actionType Action Type.
* @param actionIdList Lis of action Ids of the actions that need to be executed.
* @param eventContext The event context of the corresponding flow.
* @param tenantDomain Tenant domain.
* @return {@link ActionExecutionStatus} The status of the action execution and the response context.
* @throws ActionExecutionException If an error occurs while executing the action.
*/
ActionExecutionStatus execute(ActionType actionType, String[] actionIdList,
Map<String, Object> eventContext, String tenantDomain)
throws ActionExecutionException;

}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.wso2.carbon.identity.action.execution.model.ActionInvocationSuccessResponse;
import org.wso2.carbon.identity.action.execution.model.ActionType;
import org.wso2.carbon.identity.action.execution.model.AllowedOperation;
import org.wso2.carbon.identity.action.execution.model.*;
import org.wso2.carbon.identity.action.execution.model.Error;
import org.wso2.carbon.identity.action.execution.model.Failure;
import org.wso2.carbon.identity.action.execution.model.PerformableOperation;
Expand Down Expand Up @@ -106,6 +107,7 @@ public boolean isExecutionEnabled(ActionType actionType) {
* @param tenantDomain Tenant domain.
* @return Action execution status.
*/
@Override
public ActionExecutionStatus<?> execute(ActionType actionType, Map<String, Object> eventContext,
String tenantDomain) throws ActionExecutionException {

Expand All @@ -131,6 +133,7 @@ public ActionExecutionStatus<?> execute(ActionType actionType, Map<String, Objec
* @param tenantDomain Tenant domain.
* @return Action execution status.
*/
@Override
public ActionExecutionStatus<?> execute(ActionType actionType, String[] actionIdList,
Map<String, Object> eventContext, String tenantDomain)
throws ActionExecutionException {
Expand Down Expand Up @@ -310,6 +313,8 @@ private ActionExecutionStatus<?> processActionResponse(Action action,
return processSuccessResponse(action,
(ActionInvocationSuccessResponse) actionInvocationResponse.getResponse(),
eventContext, actionRequest, actionExecutionResponseProcessor);
} else if (actionInvocationResponse.isIncomplete()) {
return new SuccessStatus.Builder().setResponseContext(eventContext).build();
} else if (actionInvocationResponse.isFailure() && actionInvocationResponse.getResponse() != null) {
return processFailureResponse(action, (ActionInvocationFailureResponse) actionInvocationResponse
.getResponse(), eventContext, actionRequest, actionExecutionResponseProcessor);
Expand Down Expand Up @@ -341,6 +346,26 @@ private ActionExecutionStatus<Success> processSuccessResponse(Action action,
actionRequest.getEvent(), successResponseBuilder.build());
}

private ActionExecutionStatus<Incomplete> processIncompleteResponse(
Action action,
ActionInvocationSuccessResponse successResponse,
Map<String, Object> eventContext,
ActionExecutionRequest actionRequest,
ActionExecutionResponseProcessor actionExecutionResponseProcessor)
throws ActionExecutionResponseProcessorException {

//logSuccessResponse(action, successResponse);

List<PerformableOperation> allowedPerformableOperations =
validatePerformableOperations(actionRequest, successResponse, action);
ActionInvocationIncompleteResponse.Builder successResponseBuilder =
new ActionInvocationIncompleteResponse.Builder().actionStatus(
ActionInvocationResponse.Status.INCOMPLETE)
.operations(allowedPerformableOperations);
return actionExecutionResponseProcessor.processIncompleteResponse(eventContext,
actionRequest.getEvent(), successResponseBuilder.build());
}

private ActionExecutionStatus<Error> processErrorResponse(Action action,
ActionInvocationErrorResponse errorResponse,
Map<String, Object> eventContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
* Action Execution Status is the status object that is returned by the Action Executor Service after executing an
* action. It contains the status of the action execution and the response context.
*
* @param <T> Status type (i.e. SUCCESS {@link Success}, FAILED {@link Failure}, ERROR {@link Error})
* @param <T> Status type (i.e. SUCCESS {@link Success}, FAILED {@link Failure}, ERROR {@link Error},
* INCOMPLETE {@link Incomplete})
*/
public abstract class ActionExecutionStatus<T> {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* 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.action.execution.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;

import java.util.List;

/**
* This class is used to represent the incomplete response of an action invocation.
* This response will contain the list of operations that need to be performed.
*/
@JsonDeserialize(builder = ActionInvocationIncompleteResponse.Builder.class)
public class ActionInvocationIncompleteResponse implements ActionInvocationResponse.APIResponse {

private final ActionInvocationResponse.Status actionStatus;

private final List<PerformableOperation> operations;

private ActionInvocationIncompleteResponse(Builder builder) {

this.actionStatus = builder.actionStatus;
this.operations = builder.operations;
}

@Override
public ActionInvocationResponse.Status getActionStatus() {

return actionStatus;
}

public List<PerformableOperation> getOperations() {

return operations;
}

/**
* This class is used to build the {@link ActionInvocationIncompleteResponse}.
*/
@JsonPOJOBuilder(withPrefix = "")
public static class Builder {

private ActionInvocationResponse.Status actionStatus;
private List<PerformableOperation> operations;

@JsonProperty("actionStatus")
public Builder actionStatus(ActionInvocationResponse.Status actionStatus) {

this.actionStatus = actionStatus;
return this;
}

@JsonProperty("operations")
public Builder operations(@JsonProperty("operations") List<PerformableOperation> operations) {

this.operations = operations;
return this;
}

public ActionInvocationIncompleteResponse build() {

if (this.actionStatus == null) {
throw new IllegalArgumentException("actionStatus must not be null.");
}

if (!ActionInvocationResponse.Status.INCOMPLETE.equals(actionStatus)) {
throw new IllegalArgumentException("actionStatus must be INCOMPLETE.");
}

if (this.operations == null) {
throw new IllegalArgumentException("operations must not be null.");
}

return new ActionInvocationIncompleteResponse(this);
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ public boolean isSuccess() {
return Status.SUCCESS.equals(actionStatus);
}

public boolean isIncomplete() {

return Status.INCOMPLETE.equals(actionStatus);
}

public boolean isFailure() {

return Status.FAILED.equals(actionStatus);
Expand All @@ -70,6 +75,7 @@ public String getErrorLog() {
*/
public enum Status {
SUCCESS,
INCOMPLETE,
FAILED,
ERROR
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* 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.action.execution.model;

import java.util.List;

/**
* This interface models the Incomplete status.
* If the downstream extension needs to compose the responses with INCOMPLETE status and communicate it back,
* this class can be used by consumers to implement the model for that incomplete response.
*/
public class Incomplete {

private final List<PerformableOperation> performableOperations;

public Incomplete(List<PerformableOperation> incompleteReasons) {

this.performableOperations = incompleteReasons;
}

public List<PerformableOperation> getPerformableOperations() {

return performableOperations;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2024, 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.action.execution.model;

import java.util.Map;

/**
* This class models the IncompleteStatus.
*/
public class IncompleteStatus extends ActionExecutionStatus<Incomplete> {

private final Incomplete incomplete;

private IncompleteStatus(Builder builder) {

this.status = Status.INCOMPLETE;
this.incomplete = builder.incomplete;
this.responseContext = builder.responseContext;
}

@Override
public Incomplete getResponse() {

return incomplete;
}

/**
* This class is the builder for SuccessStatus.
*/
public static class Builder {

private Incomplete incomplete;
private Map<String, Object> responseContext;

public Builder incomplete(Incomplete incomplete) {

this.incomplete = incomplete;
return this;
}

public Builder responseContext(Map<String, Object> responseContext) {

this.responseContext = responseContext;
return this;
}

public IncompleteStatus build() {

return new IncompleteStatus(this);
}
}
}

0 comments on commit c2b8c08

Please sign in to comment.