Skip to content

Commit

Permalink
structurizr-dsl: An exception is now thrown when trying to use disall…
Browse files Browse the repository at this point in the history
…owed features in restricted mode (e.g. `!docs`, `!include <file>`, etc).
  • Loading branch information
simonbrowndotje committed Sep 19, 2024
1 parent 24c5cf6 commit a52e8f9
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 6 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
- structurizr-dsl: Adds a `!relationships` keyword that can be used to find a set of relationships via an expression.
- structurizr-dsl: Adds a DSL wrapper around the `structurizr-component` component finder.
- structurizr-dsl: Adds support for local theme files to be specified via `theme` (https://github.com/structurizr/java/issues/331).
- structurizr-dsl: An exception is now thrown when trying to use disallowed features in restricted mode (e.g. `!docs`, `!include <file>`, etc).
- structurizr-export: Adds support for icons to the Ilograph exporter (https://github.com/structurizr/java/issues/332).
- structurizr-export: Adds support for imports to the Ilograph exporter (https://github.com/structurizr/java/issues/332).
- structurizr-export: Fixes https://github.com/structurizr/java/issues/337 (Malformed subgraph name in Mermaid render).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,8 @@ void parse(List<String> lines, File dslFile, boolean fragment, boolean includeIn

parse(paddedLines, includedFile.getFile(), true, true);
}
} else {
throwRestrictedModeException(firstToken + " <file>");
}

// include the !include in the parser DSL as: # !include ...
Expand All @@ -268,6 +270,8 @@ void parse(List<String> lines, File dslFile, boolean fragment, boolean includeIn
// run the plugin immediately, without looking for parameters
endContext();
}
} else {
throwRestrictedModeException(firstToken);
}

} else if (inContext(PluginDslContext.class)) {
Expand All @@ -289,6 +293,8 @@ void parse(List<String> lines, File dslFile, boolean fragment, boolean includeIn
endContext();
}
}
} else {
throwRestrictedModeException(firstToken);
}

} else if (inContext(ExternalScriptDslContext.class)) {
Expand Down Expand Up @@ -437,6 +443,8 @@ void parse(List<String> lines, File dslFile, boolean fragment, boolean includeIn
if (shouldStartContext(tokens)) {
startContext(new ComponentFinderDslContext(this, getContext(ContainerDslContext.class).getContainer()));
}
} else {
throwRestrictedModeException(firstToken);
}

} else if (COMPONENT_FINDER_CLASSES_TOKEN.equalsIgnoreCase(firstToken) && inContext(ComponentFinderDslContext.class)) {
Expand Down Expand Up @@ -933,41 +941,57 @@ void parse(List<String> lines, File dslFile, boolean fragment, boolean includeIn
} else if (DOCS_TOKEN.equalsIgnoreCase(firstToken) && inContext(WorkspaceDslContext.class)) {
if (!restricted) {
new DocsParser().parse(getContext(WorkspaceDslContext.class), dslFile, tokens);
} else {
throwRestrictedModeException(firstToken);
}

} else if (DOCS_TOKEN.equalsIgnoreCase(firstToken) && inContext(SoftwareSystemDslContext.class)) {
if (!restricted) {
new DocsParser().parse(getContext(SoftwareSystemDslContext.class), dslFile, tokens);
} else {
throwRestrictedModeException(firstToken);
}

} else if (DOCS_TOKEN.equalsIgnoreCase(firstToken) && inContext(ContainerDslContext.class)) {
if (!restricted) {
new DocsParser().parse(getContext(ContainerDslContext.class), dslFile, tokens);
} else {
throwRestrictedModeException(firstToken);
}

} else if (DOCS_TOKEN.equalsIgnoreCase(firstToken) && inContext(ComponentDslContext.class)) {
if (!restricted) {
new DocsParser().parse(getContext(ComponentDslContext.class), dslFile, tokens);
} else {
throwRestrictedModeException(firstToken);
}

} else if ((ADRS_TOKEN.equalsIgnoreCase(firstToken) || DECISIONS_TOKEN.equalsIgnoreCase(firstToken)) && inContext(WorkspaceDslContext.class)) {
if (!restricted) {
new DecisionsParser().parse(getContext(WorkspaceDslContext.class), dslFile, tokens);
} else {
throwRestrictedModeException(firstToken);
}

} else if ((ADRS_TOKEN.equalsIgnoreCase(firstToken) || DECISIONS_TOKEN.equalsIgnoreCase(firstToken)) && inContext(SoftwareSystemDslContext.class)) {
if (!restricted) {
new DecisionsParser().parse(getContext(SoftwareSystemDslContext.class), dslFile, tokens);
} else {
throwRestrictedModeException(firstToken);
}

} else if ((ADRS_TOKEN.equalsIgnoreCase(firstToken) || DECISIONS_TOKEN.equalsIgnoreCase(firstToken)) && inContext(ContainerDslContext.class)) {
if (!restricted) {
new DecisionsParser().parse(getContext(ContainerDslContext.class), dslFile, tokens);
} else {
throwRestrictedModeException(firstToken);
}

} else if ((ADRS_TOKEN.equalsIgnoreCase(firstToken) || DECISIONS_TOKEN.equalsIgnoreCase(firstToken)) && inContext(ComponentDslContext.class)) {
if (!restricted) {
new DecisionsParser().parse(getContext(ComponentDslContext.class), dslFile, tokens);
} else {
throwRestrictedModeException(firstToken);
}

} else if (CONSTANT_TOKEN.equalsIgnoreCase(firstToken)) {
Expand Down Expand Up @@ -1068,6 +1092,10 @@ private List<DslLine> preProcessLines(List<String> lines) {
return dslLines;
}

private void throwRestrictedModeException(String firstToken) {
throw new RuntimeException(firstToken + " is not available when the parser is running in restricted mode");
}

private String substituteStrings(String token) {
Matcher m = STRING_SUBSTITUTION_PATTERN.matcher(token);
while (m.find()) {
Expand Down
77 changes: 71 additions & 6 deletions structurizr-dsl/src/test/java/com/structurizr/dsl/DslTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -419,13 +419,18 @@ void test_includeUrl() throws Exception {
}

@Test
void test_include_WhenRunningInRestrictedMode() throws Exception {
StructurizrDslParser parser = new StructurizrDslParser();
parser.setRestricted(true);
void test_includeLocalFile_ThrowsAnException_WhenRunningInRestrictedMode() {
try {
StructurizrDslParser parser = new StructurizrDslParser();
parser.setRestricted(true);

// the model include will be ignored, so no software systems
parser.parse(new File("src/test/resources/dsl/include-file.dsl"));
assertEquals(0, model.getSoftwareSystems().size());
// the model include will be ignored, so no software systems
parser.parse(new File("src/test/resources/dsl/include-file.dsl"));
fail();
} catch (Exception e) {
System.out.println(e.getMessage());
assertTrue(e.getMessage().startsWith("!include <file> is not available when the parser is running in restricted mode"));
}
}

@ParameterizedTest
Expand Down Expand Up @@ -663,6 +668,19 @@ void test_hierarchicalIdentifiersAndDeploymentNodes_WhenSoftwareContainerClashes
parser.parse(new File("src/test/resources/dsl/hierarchical-identifiers-and-deployment-nodes-3.dsl"));
}

@Test
void test_plugin_ThrowsAnException_WhenTheParserIsRunningInRestrictedMode() {
try {
StructurizrDslParser parser = new StructurizrDslParser();
parser.setRestricted(true);
parser.parse(new File("src/test/resources/dsl/plugin-without-parameters.dsl"));
fail();
} catch (Exception e) {
System.out.println(e.getMessage());
assertTrue(e.getMessage().startsWith("!plugin is not available when the parser is running in restricted mode"));
}
}

@Test
void test_pluginWithoutParameters() throws Exception {
StructurizrDslParser parser = new StructurizrDslParser();
Expand All @@ -679,6 +697,18 @@ void test_pluginWithParameters() throws Exception {
assertNotNull(parser.getWorkspace().getModel().getPersonWithName("Java"));
}

@Test
void test_script_ThrowsAnException_WhenTheParserIsInRestrictedMode() {
try {
StructurizrDslParser parser = new StructurizrDslParser();
parser.setRestricted(true);
parser.parse(new File("src/test/resources/dsl/script-external.dsl"));
fail();
} catch (Exception e) {
assertTrue(e.getMessage().startsWith("!script is not available when the parser is running in restricted mode"));
}
}

@Test
void test_script() throws Exception {
StructurizrDslParser parser = new StructurizrDslParser();
Expand Down Expand Up @@ -751,6 +781,18 @@ void test_docs() throws Exception {
assertEquals(1, component.getDocumentation().getSections().size());
}

@Test
void test_docs_ThrowsAnException_WhenTheParserIsInRestrictedMode() {
try {
StructurizrDslParser parser = new StructurizrDslParser();
parser.setRestricted(true);
parser.parse(new File("src/test/resources/dsl/docs/workspace.dsl"));
fail();
} catch (Exception e) {
assertTrue(e.getMessage().startsWith("!docs is not available when the parser is running in restricted mode"));
}
}

@Test
void test_decisions() throws Exception {
StructurizrDslParser parser = new StructurizrDslParser();
Expand All @@ -771,6 +813,18 @@ void test_decisions() throws Exception {
assertEquals(4, component.getDocumentation().getDecisions().size());
}

@Test
void test_decisions_ThrowsAnException_WhenTheParserIsInRestrictedMode() {
try {
StructurizrDslParser parser = new StructurizrDslParser();
parser.setRestricted(true);
parser.parse(new File("src/test/resources/dsl/decisions/workspace.dsl"));
fail();
} catch (Exception e) {
assertTrue(e.getMessage().startsWith("!adrs is not available when the parser is running in restricted mode"));
}
}

@Test
void test_this() throws Exception {
StructurizrDslParser parser = new StructurizrDslParser();
Expand Down Expand Up @@ -1192,6 +1246,17 @@ void springPetClinic() throws Exception {
if (!StringUtils.isNullOrEmpty(springPetClinicHome)) {
System.out.println("Running Spring PetClinic example...");

try {
File workspaceFile = new File("src/test/resources/dsl/spring-petclinic/workspace.dsl");
StructurizrDslParser parser = new StructurizrDslParser();
parser.setRestricted(true);
parser.parse(workspaceFile);
fail();
} catch (Exception e) {
System.out.println(e.getMessage());
assertTrue(e.getMessage().startsWith("!components is not available when the parser is running in restricted mode"));
}

File workspaceFile = new File("src/test/resources/dsl/spring-petclinic/workspace.dsl");
StructurizrDslParser parser = new StructurizrDslParser();
parser.parse(workspaceFile);
Expand Down

0 comments on commit a52e8f9

Please sign in to comment.