Skip to content
3 changes: 3 additions & 0 deletions openapi/openapi-component_catalog-v1.0.0.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1156,6 +1156,9 @@ components:
deletionWorkflowJobId:
type: string
example: '123456'
canBeDeleted:
type: boolean
example: 'true'
parameters:
type: array
items:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.opendevstack.component_provisioner.server.controllers.validators;

import lombok.extern.slf4j.Slf4j;
import org.opendevstack.component_provisioner.client.component_catalog.v1.model.ProjectComponentExtendedInfo;
import org.opendevstack.component_provisioner.server.controllers.exceptions.UserNotAllowedException;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class ProjectComponentDeletePermissionsValidator {

public void validate(ProjectComponentExtendedInfo projectComponentExtendedInfo) {
log.debug("Validating user has permissions to delete. ProjectComponentExtendedInfo: {}", projectComponentExtendedInfo);
if (!Boolean.TRUE.equals(projectComponentExtendedInfo.getCanBeDeleted())) {
throw new UserNotAllowedException("User has no permissions to delete this project component");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.opendevstack.component_provisioner.server.controllers.validators.InputParamsValidator;
import org.opendevstack.component_provisioner.server.controllers.validators.ParameterType;
import org.opendevstack.component_provisioner.server.controllers.validators.WorkflowsValidator;
import org.opendevstack.component_provisioner.server.controllers.validators.ProjectComponentDeletePermissionsValidator;
import org.opendevstack.component_provisioner.server.mappers.EntitiesMapper;
import org.opendevstack.component_provisioner.server.model.CreateIncidentAction;
import org.opendevstack.component_provisioner.server.model.CreateIncidentParameter;
Expand Down Expand Up @@ -65,6 +66,7 @@ public class ProvisionResultsApiFacade {
private final WorkflowsValidator workflowsValidator;
private final DeletionSentinelWorkflowValidator deletionSentinelWorkflowValidator;
private final InputParamsValidator inputParamsValidator;
private final ProjectComponentDeletePermissionsValidator projectComponentDeletePermissionsValidator;

@Value("${component-provisioner.awx.workflows.create-incident-workflow-id}")
private String createIncidentWorkflowId;
Expand All @@ -82,6 +84,8 @@ public AwxResponse requestDeletion(
var accessToken = authenticationProvider.getAccessToken();
var projectComponent = componentCatalogService.getProjectComponentById(accessToken, projectKey, componentId);

projectComponentDeletePermissionsValidator.validate(projectComponent);

String deletionWorkflowId = getDeletionWorkflowId(projectComponent);
String deletionWorkflowName = getDeletionWorkflowName(projectComponent);
String deletionWorkflowTimeoutSeconds = getDeletionWorkflowTimeoutSeconds(projectComponent);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.opendevstack.component_provisioner.server.controllers.validators;

import org.junit.jupiter.api.Test;
import org.opendevstack.component_provisioner.client.component_catalog.v1.model.ProjectComponentExtendedInfo;
import org.opendevstack.component_provisioner.server.controllers.exceptions.UserNotAllowedException;
import org.opendevstack.component_provisioner.server.model.ProjectComponentExtendedInfoMother;

import static org.junit.jupiter.api.Assertions.assertThrows;

public class ProjectComponentDeletePermissionsValidatorTest {

private final ProjectComponentDeletePermissionsValidator validator = new ProjectComponentDeletePermissionsValidator();

@Test
public void givenProjectComponentNotDeletable_whenValidate_thenThrowsUserNotAllowedException() {
// given
ProjectComponentExtendedInfo projectComponentExtendedInfo = ProjectComponentExtendedInfoMother.valid();
projectComponentExtendedInfo.setCanBeDeleted(false);

// when / then
assertThrows(UserNotAllowedException.class, () -> validator.validate(projectComponentExtendedInfo));
}

@Test
public void givenProjectComponentDeletable_whenValidate_thenDoesNotThrow() {
// given
ProjectComponentExtendedInfo projectComponentExtendedInfo = ProjectComponentExtendedInfoMother.valid();

// when / then
validator.validate(projectComponentExtendedInfo);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.opendevstack.component_provisioner.server.controllers.exceptions.SlugNotFoundException;
import org.opendevstack.component_provisioner.server.controllers.validators.DeletionSentinelWorkflowValidator;
import org.opendevstack.component_provisioner.server.controllers.validators.InputParamsValidator;
import org.opendevstack.component_provisioner.server.controllers.validators.ProjectComponentDeletePermissionsValidator;
import org.opendevstack.component_provisioner.server.controllers.validators.WorkflowsValidator;
import org.opendevstack.component_provisioner.server.mappers.EntitiesMapper;
import org.opendevstack.component_provisioner.server.model.*;
Expand Down Expand Up @@ -86,6 +87,9 @@ class ProvisionResultsApiFacadeTest {
@Mock
private InputParamsValidator inputParamsValidator;

@Mock
private ProjectComponentDeletePermissionsValidator projectComponentDeletePermissionsValidator;

@InjectMocks
private ProvisionResultsApiFacade facade;

Expand Down Expand Up @@ -1020,6 +1024,7 @@ private static ProjectComponentExtendedInfo buildProjectComponentWithDeletionCon
.componentId(componentId)
.status(status)
.parameters(parameters)
.canBeDeleted(true)
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public static ProjectComponentExtendedInfo valid() {
.componentId("component-id")
.catalogItemId("aHR0cDovL2JpdGJ1Y2tldC10ZXN0LmNvbQ")
.catalogItemRef("L3JlZmVyZW5jZT9wYXJhbT0xMA")
.canBeDeleted(true)
.status(org.opendevstack.component_provisioner.client.component_catalog.v1.model.ProvisioningStatus.CREATED)
.componentUrl("https://example.com/component")
.parameters(Collections.emptyList())
Expand Down
Loading