Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve action management service to manage actions with rules. #6269

Merged
merged 6 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@
<groupId>org.wso2.carbon.identity.framework</groupId>
<artifactId>org.wso2.carbon.identity.certificate.management</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity.framework</groupId>
<artifactId>org.wso2.carbon.identity.rule.management</artifactId>
</dependency>
<dependency>
<groupId>org.json.wso2</groupId>
<artifactId>json</artifactId>
Expand Down Expand Up @@ -100,7 +104,8 @@
org.wso2.carbon.identity.action.management.constant.error,
org.wso2.carbon.identity.action.management.exception,
org.wso2.carbon.identity.action.management.model,
org.wso2.carbon.identity.action.management.service; version="${carbon.identity.package.export.version}"
org.wso2.carbon.identity.action.management.service;
version="${carbon.identity.package.export.version}"
</Export-Package>
<Import-Package>
org.apache.commons.lang; version="${commons-lang.wso2.osgi.version.range}",
Expand All @@ -109,16 +114,27 @@
org.osgi.framework; version="${osgi.framework.imp.pkg.version.range}",
org.osgi.service.component; version="${osgi.service.component.imp.pkg.version.range}",
org.json.*; version="${json.wso2.version.range}",
org.wso2.carbon.database.utils.jdbc; version="${org.wso2.carbon.database.utils.version.range}",
org.wso2.carbon.database.utils.jdbc.exceptions; version="${org.wso2.carbon.database.utils.version.range}",
org.wso2.carbon.identity.core.cache; version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.core.util; version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.secret.mgt.core; version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.secret.mgt.core.exception; version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.secret.mgt.core.model; version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.database.utils.jdbc;
version="${org.wso2.carbon.database.utils.version.range}",
org.wso2.carbon.database.utils.jdbc.exceptions;
version="${org.wso2.carbon.database.utils.version.range}",
org.wso2.carbon.identity.core.cache;
version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.core.util;
version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.secret.mgt.core;
version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.secret.mgt.core.exception;
version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.secret.mgt.core.model;
version="${carbon.identity.package.import.version.range}",
ashanthamara marked this conversation as resolved.
Show resolved Hide resolved
org.wso2.carbon.utils; version="${carbon.kernel.package.import.version.range}",
org.wso2.carbon.identity.event.*; version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.central.log.mgt.utils; version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.rule.management.exception; version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.rule.management.model; version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.rule.management.service; version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.central.log.mgt.utils;
version="${carbon.identity.package.import.version.range}",
org.wso2.carbon; version="${carbon.kernel.package.import.version.range}",
org.wso2.carbon.context; version="${carbon.kernel.package.import.version.range}",
org.wso2.carbon.utils.*; version="${carbon.kernel.package.import.version.range}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class ActionMgtConstants {

public static final String URI_PROPERTY = "uri";
public static final String AUTHN_TYPE_PROPERTY = "authnType";
public static final String RULE_PROPERTY = "rule";
public static final String IDN_SECRET_TYPE_ACTION_SECRETS = "ACTION_API_ENDPOINT_AUTH_SECRETS";

public static final String ACTION_NAME_FIELD = "Action name";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@
import org.wso2.carbon.identity.action.management.exception.ActionMgtClientException;
import org.wso2.carbon.identity.action.management.exception.ActionMgtException;
import org.wso2.carbon.identity.action.management.exception.ActionMgtServerException;
import org.wso2.carbon.identity.action.management.internal.ActionMgtServiceComponentHolder;
import org.wso2.carbon.identity.action.management.model.Action;
import org.wso2.carbon.identity.action.management.model.ActionDTO;
import org.wso2.carbon.identity.action.management.model.ActionRule;
import org.wso2.carbon.identity.action.management.model.AuthProperty;
import org.wso2.carbon.identity.action.management.model.Authentication;
import org.wso2.carbon.identity.action.management.model.EndpointConfig;
Expand All @@ -40,6 +42,7 @@
import org.wso2.carbon.identity.action.management.util.ActionSecretProcessor;
import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil;
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.rule.management.exception.RuleManagementException;
import org.wso2.carbon.identity.secret.mgt.core.exception.SecretManagementException;

import java.util.List;
Expand Down Expand Up @@ -72,10 +75,11 @@ public void addAction(ActionDTO actionDTO, Integer tenantId) throws ActionMgtExc
ActionDTOBuilder actionDTOBuilder = new ActionDTOBuilder(actionDTO);
// Encrypt authentication secrets
encryptAddingAuthSecrets(actionDTOBuilder);
// Add action rule
addActionRule(actionDTOBuilder, IdentityTenantUtil.getTenantDomain(tenantId));
ashanthamara marked this conversation as resolved.
Show resolved Hide resolved
// Resolve action properties
ActionDTO resolvedActionDTO = getResolvedActionDTOForAddOperation(actionDTOBuilder.build(),
tenantId);

actionManagementDAO.addAction(resolvedActionDTO, tenantId);
return null;
});
Expand All @@ -94,7 +98,6 @@ public List<ActionDTO> getActionsByActionType(String actionType, Integer tenantI

try {
List<ActionDTO> actionDTOS = actionManagementDAO.getActionsByActionType(actionType, tenantId);

return getResolvedActionDTOsForGetOperation(actionType, actionDTOS, tenantId);
} catch (ActionMgtException | ActionDTOModelResolverException e) {
throw ActionManagementExceptionHandler.handleServerException(
Expand All @@ -106,15 +109,23 @@ public List<ActionDTO> getActionsByActionType(String actionType, Integer tenantI
public ActionDTO getActionByActionId(String actionType, String actionId, Integer tenantId)
throws ActionMgtException {

NamedJdbcTemplate jdbcTemplate = new NamedJdbcTemplate(IdentityDatabaseUtil.getDataSource());
try {
ActionDTO actionDTO = actionManagementDAO.getActionByActionId(actionType, actionId, tenantId);
if (actionDTO == null) {
return null;
}
return jdbcTemplate.withTransaction(template -> {
ActionDTO actionDTO = actionManagementDAO.getActionByActionId(actionType, actionId, tenantId);
if (actionDTO == null) {
return null;
}

// Populate action properties
return getResolvedActionDTOForGetOperation(actionDTO, tenantId);
} catch (ActionMgtException | ActionDTOModelResolverException e) {
ActionDTOBuilder actionDTOBuilder = new ActionDTOBuilder(actionDTO);
// Load action rule
loadActionRule(actionDTOBuilder, IdentityTenantUtil.getTenantDomain(tenantId));
// Populate action properties
return getResolvedActionDTOForGetOperation(actionDTOBuilder.build(), tenantId);
});
} catch (TransactionException e) {
// Since exceptions thrown are wrapped with TransactionException, extracting the actual cause.
handleActionPropertyResolverClientException(e.getCause());
throw ActionManagementExceptionHandler.handleServerException(
ErrorMessage.ERROR_WHILE_RETRIEVING_ACTION_BY_ID, e);
}
Expand All @@ -130,6 +141,9 @@ public void updateAction(ActionDTO updatingActionDTO, ActionDTO existingActionDT
ActionDTOBuilder updatingActionDTOBuilder = new ActionDTOBuilder(updatingActionDTO);
// Encrypt authentication secrets
encryptUpdatingAuthSecrets(updatingActionDTOBuilder, existingActionDTO);
// Update action rule
updateActionRule(updatingActionDTOBuilder, existingActionDTO,
IdentityTenantUtil.getTenantDomain(tenantId));
// Resolve action properties
ActionDTO resolvedUpdatingActionDTO =
getResolvedActionDTOForUpdateOperation(updatingActionDTOBuilder.build(), existingActionDTO,
Expand All @@ -156,9 +170,8 @@ public void deleteAction(ActionDTO deletingActionDTO, Integer tenantId) throws A
try {
jdbcTemplate.withTransaction(template -> {
actionManagementDAO.deleteAction(deletingActionDTO, tenantId);
// Encrypt authentication secrets
deleteAuthenticationSecrets(deletingActionDTO);
// Resolve action properties
deleteActionRule(deletingActionDTO, IdentityTenantUtil.getTenantDomain(tenantId));
deleteProperties(deletingActionDTO, tenantId);

return null;
Expand Down Expand Up @@ -294,6 +307,108 @@ private void addEncryptedAuthSecretsToBuilder(ActionDTOBuilder actionDTOBuilder,
.build());
}

private void addActionRule(ActionDTOBuilder actionDTOBuilder, String tenantDomain) throws ActionMgtException {

if (actionDTOBuilder.getActionRule() == null || actionDTOBuilder.getActionRule().getRule() == null) {
ashanthamara marked this conversation as resolved.
Show resolved Hide resolved
return;
}

try {
ActionMgtServiceComponentHolder.getInstance()
.getRuleManagementService()
.addRule(actionDTOBuilder.getActionRule().getRule(), tenantDomain);
} catch (RuleManagementException e) {
throw new ActionMgtServerException("Error while adding the Rule associated with the Action.", e);
}

}

private void loadActionRule(ActionDTOBuilder actionDTOBuilder, String tenantDomain)
throws ActionMgtServerException {

if (actionDTOBuilder.getActionRule() == null) {
return;
}

try {
ActionRule actionRule = ActionRule.create(ActionMgtServiceComponentHolder.getInstance()
.getRuleManagementService()
.getRuleByRuleId(actionDTOBuilder.getActionRule().getId(), tenantDomain));
actionDTOBuilder.rule(actionRule);
} catch (RuleManagementException e) {
throw new ActionMgtServerException("Error while retrieving the Rule associated with the Action.", e);
}
}

private void updateActionRule(ActionDTOBuilder updatingActionDTOBuilder, ActionDTO existingActionDTO,
String tenantDomain) throws ActionMgtException {

/*
When updating an action, the action rule can be added, removed or updated.
When action rule is added, the Rule object is added to the ActionRule of the ActionDTO.
When action rule is removed, the Rule object is set as null in the ActionRule of the ActionDTO.
This happens as the API accepts the removal of the rule in an action update via an empty rule JSON object.
e.g., rule: {}. If rule is not present in the payload that means rule is not updated.
When action rule is updated, the Rule object is updated in the ActionRule of the ActionDTO.
*/
if (isAddingNewActionRule(updatingActionDTOBuilder, existingActionDTO)) {
addActionRule(updatingActionDTOBuilder, tenantDomain);
} else if (isRemovingExistingActionRule(updatingActionDTOBuilder, existingActionDTO)) {
deleteActionRule(existingActionDTO, tenantDomain);
} else if (isUpdatingExistingActionRule(updatingActionDTOBuilder, existingActionDTO)) {
updateExistingActionRule(updatingActionDTOBuilder, existingActionDTO, tenantDomain);
}
}

private boolean isAddingNewActionRule(ActionDTOBuilder updatingActionDTOBuilder, ActionDTO existingActionDTO)
throws ActionMgtException {

return existingActionDTO.getActionRule() == null && updatingActionDTOBuilder.getActionRule() != null &&
updatingActionDTOBuilder.getActionRule().getRule() != null;
}

private boolean isRemovingExistingActionRule(ActionDTOBuilder updatingActionDTOBuilder,
ActionDTO existingActionDTO) throws ActionMgtException {

return existingActionDTO.getActionRule() != null && updatingActionDTOBuilder.getActionRule() != null &&
updatingActionDTOBuilder.getActionRule().getRule() == null;
}

private boolean isUpdatingExistingActionRule(ActionDTOBuilder updatingActionDTOBuilder,
ActionDTO existingActionDTO) throws ActionMgtException {

return existingActionDTO.getActionRule() != null && updatingActionDTOBuilder.getActionRule() != null &&
updatingActionDTOBuilder.getActionRule().getRule() != null;
}

private void updateExistingActionRule(ActionDTOBuilder updatingActionDTOBuilder, ActionDTO existingActionDTO,
String tenantDomain) throws ActionMgtException {

try {
updatingActionDTOBuilder.getActionRule().getRule().setId(existingActionDTO.getActionRule().getId());
ActionMgtServiceComponentHolder.getInstance()
.getRuleManagementService()
.updateRule(updatingActionDTOBuilder.getActionRule().getRule(), tenantDomain);
} catch (RuleManagementException e) {
throw new ActionMgtServerException("Error while updating the Rule associated with the Action.", e);
}
}

private void deleteActionRule(ActionDTO actionDTO, String tenantDomain) throws ActionMgtServerException {

if (actionDTO.getActionRule() == null) {
ashanthamara marked this conversation as resolved.
Show resolved Hide resolved
return;
}

try {
ActionMgtServiceComponentHolder.getInstance()
.getRuleManagementService()
.deleteRule(actionDTO.getActionRule().getId(), tenantDomain);
} catch (RuleManagementException e) {
throw new ActionMgtServerException("Error while deleting the Rule associated with the Action.", e);
}
}

/**
* Get the ActionDTO with resolved adding properties that needs to be added in the Action Management Service.
*
Expand Down
Loading
Loading