Skip to content

Commit

Permalink
Add AuthenticatorAdapterService,
Browse files Browse the repository at this point in the history
  • Loading branch information
Thisara-Welmilla committed Jan 20, 2025
1 parent 26eb2d9 commit 03667aa
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* 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.impl;

import org.wso2.carbon.identity.action.execution.model.Context;
import org.wso2.carbon.identity.action.execution.model.ActionType;

import java.util.HashMap;
import java.util.Map;

public class InvocationSuccessResponseContextFactory {

private static final Map<ActionType, Class<? extends Context>> contextClassMap = new HashMap<>();

public static Class<? extends Context> getInvocationSuccessResponseContextClass(ActionType actionType) {

Class<? extends Context> responseClass = contextClassMap.get(actionType);
if (responseClass != null) {
return responseClass;
}
return Context.class;
}

public static void registerInvocationSuccessResponseContextClass(
Class<? extends Context> invocationSuccessResponse) throws NoSuchFieldException, IllegalAccessException {

ActionType type = (ActionType) invocationSuccessResponse.getDeclaredField("ACTION_TYPE").get(null);
contextClassMap.put(type, invocationSuccessResponse);
}

public static void unregisterInvocationSuccessResponse(Class<? extends Context> invocationSuccessResponse) {

contextClassMap.remove(ActionType.AUTHENTICATION);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@
public class ActionInvocationSuccessResponse implements ActionInvocationResponse.APIResponse {

private final ActionInvocationResponse.Status actionStatus;

private final List<PerformableOperation> operations;
private final Context data;

private ActionInvocationSuccessResponse(Builder builder) {

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

@Override
Expand All @@ -52,6 +53,11 @@ public List<PerformableOperation> getOperations() {
return operations;
}

public Context getData() {

return data;
}

/**
* This class is used to build the {@link ActionInvocationSuccessResponse}.
*/
Expand All @@ -60,6 +66,7 @@ public static class Builder {

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

@JsonProperty("actionStatus")
public Builder actionStatus(ActionInvocationResponse.Status actionStatus) {
Expand All @@ -75,6 +82,14 @@ public Builder operations(@JsonProperty("operations") List<PerformableOperation>
return this;
}

@JsonDeserialize(using = Context.ContextDeserializer.class)
@JsonProperty("data")
public Builder context(@JsonProperty("data")Context data) {

this.data = data;
return this;
}

public ActionInvocationSuccessResponse build() {

if (this.actionStatus == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* 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.core.JsonParser;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;

import java.io.IOException;

import static org.wso2.carbon.identity.action.execution.impl.InvocationSuccessResponseContextFactory.getInvocationSuccessResponseContextClass;

public interface Context {

public static final ActionType ACTION_TYPE = null;

public static ActionType getActionType() {
return ACTION_TYPE;
}

public static class DefaultContext implements Context {
}

public static class ContextDeserializer extends StdDeserializer<Context> {

private final ActionType actionType;

public ContextDeserializer(ActionType actionType) {

super(Context.class);
this.actionType = actionType;
}

@Override
public Context deserialize(JsonParser p, com.fasterxml.jackson.databind.DeserializationContext ctxt)
throws IOException {

JsonNode node = p.getCodec().readTree(p);
ObjectMapper mapper = (ObjectMapper) p.getCodec();
return mapper.treeToValue(node, getInvocationSuccessResponseContextClass(actionType));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
Expand All @@ -40,6 +41,8 @@
import org.wso2.carbon.identity.action.execution.model.ActionInvocationFailureResponse;
import org.wso2.carbon.identity.action.execution.model.ActionInvocationResponse;
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.Context;

import java.io.IOException;
import java.net.SocketTimeoutException;
Expand Down Expand Up @@ -75,13 +78,13 @@ public APIClient() {
.build();
}

public ActionInvocationResponse callAPI(String url, AuthMethods.AuthMethod authMethod,
public ActionInvocationResponse callAPI(ActionType actionType, String url, AuthMethods.AuthMethod authMethod,
String payload) {

HttpPost httpPost = new HttpPost(url);
setRequestEntity(httpPost, payload, authMethod);

return executeRequest(httpPost);
return executeRequest(actionType, httpPost);
}

private void setRequestEntity(HttpPost httpPost, String jsonRequest, AuthMethods.AuthMethod authMethod) {
Expand All @@ -95,15 +98,15 @@ private void setRequestEntity(HttpPost httpPost, String jsonRequest, AuthMethods
httpPost.setHeader("Content-type", "application/json");
}

private ActionInvocationResponse executeRequest(HttpPost request) {
private ActionInvocationResponse executeRequest(ActionType actionType, HttpPost request) {

int attempts = 0;
int retryCount = ActionExecutorConfig.getInstance().getHttpRequestRetryCount();
ActionInvocationResponse actionInvocationResponse = null;

while (attempts < retryCount) {
try (CloseableHttpResponse response = httpClient.execute(request)) {
actionInvocationResponse = handleResponse(response);
actionInvocationResponse = handleResponse(actionType, response);
if (!actionInvocationResponse.isError() || !actionInvocationResponse.isRetry()) {
return actionInvocationResponse;
}
Expand All @@ -129,7 +132,7 @@ private ActionInvocationResponse executeRequest(HttpPost request) {
.errorLog("Failed to execute the action request or maximum retry attempts reached.").build();
}

private ActionInvocationResponse handleResponse(HttpResponse response) {
private ActionInvocationResponse handleResponse(ActionType actionType, HttpResponse response) {

int statusCode = response.getStatusLine().getStatusCode();
HttpEntity responseEntity = response.getEntity();
Expand All @@ -138,7 +141,7 @@ private ActionInvocationResponse handleResponse(HttpResponse response) {

switch (statusCode) {
case HttpStatus.SC_OK:
handleSuccessOrFailure(actionInvocationResponseBuilder, responseEntity, statusCode);
handleSuccessOrFailure(actionType, actionInvocationResponseBuilder, responseEntity, statusCode);
break;
case HttpStatus.SC_BAD_REQUEST:
case HttpStatus.SC_UNAUTHORIZED:
Expand All @@ -162,10 +165,11 @@ private ActionInvocationResponse handleResponse(HttpResponse response) {
return actionInvocationResponseBuilder.build();
}

private void handleSuccessOrFailure(ActionInvocationResponse.Builder builder, HttpEntity entity, int statusCode) {
private void handleSuccessOrFailure(ActionType actionType, ActionInvocationResponse.Builder builder,
HttpEntity entity, int statusCode) {

try {
builder.response(handleSuccessOrFailureResponse(entity));
builder.response(handleSuccessOrFailureResponse(actionType, entity));
} catch (ActionInvocationException e) {
builder.errorLog("Unexpected response for status code: " + statusCode + ". " + e.getMessage());
}
Expand Down Expand Up @@ -207,10 +211,11 @@ private void handleServerError(ActionInvocationResponse.Builder builder, HttpEnt
}
}

private ActionInvocationResponse.APIResponse handleSuccessOrFailureResponse(HttpEntity responseEntity)
private ActionInvocationResponse.APIResponse handleSuccessOrFailureResponse(ActionType actionType,
HttpEntity responseEntity)
throws ActionInvocationException {

return deserializeSuccessOrFailureResponse(responseEntity);
return deserializeSuccessOrFailureResponse(actionType, responseEntity);
}

private ActionInvocationResponse.APIResponse handleErrorResponse(HttpEntity responseEntity)
Expand All @@ -236,7 +241,8 @@ private String validateJsonResponse(HttpEntity responseEntity) throws ActionInvo
}
}

private ActionInvocationResponse.APIResponse deserializeSuccessOrFailureResponse(HttpEntity responseEntity)
private ActionInvocationResponse.APIResponse deserializeSuccessOrFailureResponse(ActionType actionType,
HttpEntity responseEntity)
throws ActionInvocationException {

try {
Expand All @@ -248,6 +254,9 @@ private ActionInvocationResponse.APIResponse deserializeSuccessOrFailureResponse
throw new ActionInvocationException("Reading JSON response failed.");
}
if (actionStatus.equals(ActionExecutionStatus.Status.SUCCESS.name())) {
SimpleModule module = new SimpleModule();
module.addDeserializer(Context.class, new Context.ContextDeserializer(actionType));
objectMapper.registerModule(module);
return objectMapper.readValue(jsonResponse, ActionInvocationSuccessResponse.class);
} else {
return objectMapper.readValue(jsonResponse, ActionInvocationFailureResponse.class);
Expand Down

0 comments on commit 03667aa

Please sign in to comment.