diff --git a/src/main/java/com/marklogic/mgmt/api/security/RoleObjectNodesSorter.java b/src/main/java/com/marklogic/mgmt/api/security/RoleObjectNodesSorter.java index 194a36ac4..6bbcfc357 100644 --- a/src/main/java/com/marklogic/mgmt/api/security/RoleObjectNodesSorter.java +++ b/src/main/java/com/marklogic/mgmt/api/security/RoleObjectNodesSorter.java @@ -78,7 +78,15 @@ else if (index > -1) { } } - String[] sortedRoleNames = sorter.sort(); + String[] sortedRoleNames; + try { + sortedRoleNames = sorter.sort(); + } catch (IllegalStateException ex) { + throw new IllegalArgumentException("Unable to deploy roles due to circular dependencies " + + "between two or more roles; please remove these circular dependencies in order to deploy" + + " your roles"); + } + roles = new ArrayList<>(); for (String name : sortedRoleNames) { roles.add(map.get(name)); diff --git a/src/test/java/com/marklogic/appdeployer/command/security/DeployRolesWithDependenciesTest.java b/src/test/java/com/marklogic/appdeployer/command/security/DeployRolesWithDependenciesTest.java index 3f84b997c..bac58197a 100644 --- a/src/test/java/com/marklogic/appdeployer/command/security/DeployRolesWithDependenciesTest.java +++ b/src/test/java/com/marklogic/appdeployer/command/security/DeployRolesWithDependenciesTest.java @@ -6,7 +6,7 @@ import java.io.File; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; /** * Each of these tests verifies that the roles in the given config dir can be deployed successfully based on their @@ -73,6 +73,22 @@ public void anotherSortingTest() { } } + @Test + void circularDependencies() { + appConfig.getFirstConfigDir().setBaseDir(new File("src/test/resources/sample-app/roles-with-circular-dependencies")); + initializeAppDeployer(new DeployRolesCommand()); + try { + deploySampleApp(); + fail("Expected an error due to a circular dependency between the two roles"); + } catch (IllegalArgumentException ex) { + assertEquals("Unable to deploy roles due to circular dependencies between two or more roles; " + + "please remove these circular dependencies in order to deploy your roles", + ex.getMessage()); + } finally { + undeploySampleApp(); + } + } + @Test public void test() { appConfig.getFirstConfigDir().setBaseDir(new File("src/test/resources/sample-app/roles-with-dependencies")); diff --git a/src/test/resources/sample-app/roles-with-circular-dependencies/security/roles/role0.json b/src/test/resources/sample-app/roles-with-circular-dependencies/security/roles/role0.json new file mode 100644 index 000000000..f2120b8df --- /dev/null +++ b/src/test/resources/sample-app/roles-with-circular-dependencies/security/roles/role0.json @@ -0,0 +1,6 @@ +{ + "role-name": "sample-app-role0", + "role": [ + "sample-app-role1" + ] +} diff --git a/src/test/resources/sample-app/roles-with-circular-dependencies/security/roles/role1.json b/src/test/resources/sample-app/roles-with-circular-dependencies/security/roles/role1.json new file mode 100644 index 000000000..526f6decd --- /dev/null +++ b/src/test/resources/sample-app/roles-with-circular-dependencies/security/roles/role1.json @@ -0,0 +1,6 @@ +{ + "role-name": "sample-app-role1", + "role": [ + "sample-app-role0" + ] +}