Skip to content

Commit f33f7ed

Browse files
theme <file> should not be available when running in restricted mode.
1 parent 91a64b3 commit f33f7ed

File tree

3 files changed

+45
-28
lines changed

3 files changed

+45
-28
lines changed

structurizr-dsl/src/main/java/com/structurizr/dsl/StructurizrDslParser.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,10 +1114,10 @@ void parse(List<String> lines, File dslFile, boolean fragment, boolean includeIn
11141114
new DynamicViewRelationshipParser().parseUrl(getContext(DynamicViewRelationshipContext.class), tokens.withoutContextStartToken());
11151115

11161116
} else if (THEME_TOKEN.equalsIgnoreCase(firstToken) && (inContext(ViewsDslContext.class) || inContext(StylesDslContext.class))) {
1117-
new ThemeParser().parseTheme(getContext(), dslFile, tokens);
1117+
new ThemeParser().parseTheme(getContext(), dslFile, tokens, restricted);
11181118

11191119
} else if (THEMES_TOKEN.equalsIgnoreCase(firstToken) && (inContext(ViewsDslContext.class) || inContext(StylesDslContext.class))) {
1120-
new ThemeParser().parseThemes(getContext(), dslFile, tokens);
1120+
new ThemeParser().parseThemes(getContext(), dslFile, tokens, restricted);
11211121

11221122
} else if (TERMINOLOGY_TOKEN.equalsIgnoreCase(firstToken) && inContext(ViewsDslContext.class)) {
11231123
startContext(new TerminologyDslContext());

structurizr-dsl/src/main/java/com/structurizr/dsl/ThemeParser.java

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ final class ThemeParser extends AbstractParser {
1212

1313
private final static int FIRST_THEME_INDEX = 1;
1414

15-
void parseTheme(DslContext context, File dslFile, Tokens tokens) {
15+
void parseTheme(DslContext context, File dslFile, Tokens tokens, boolean restricted) {
1616
// theme <default|url|file>
1717
if (tokens.hasMoreThan(FIRST_THEME_INDEX)) {
1818
throw new RuntimeException("Too many tokens, expected: theme <url|file>");
@@ -22,21 +22,21 @@ void parseTheme(DslContext context, File dslFile, Tokens tokens) {
2222
throw new RuntimeException("Expected: theme <url|file>");
2323
}
2424

25-
addTheme(context, dslFile, tokens.get(FIRST_THEME_INDEX));
25+
addTheme(context, dslFile, tokens.get(FIRST_THEME_INDEX), restricted);
2626
}
2727

28-
void parseThemes(DslContext context, File dslFile, Tokens tokens) {
28+
void parseThemes(DslContext context, File dslFile, Tokens tokens, boolean restricted) {
2929
// themes <url|file> [url|file] ... [url|file]
3030
if (!tokens.includes(FIRST_THEME_INDEX)) {
3131
throw new RuntimeException("Expected: themes <url|file> [url|file] ... [url|file]");
3232
}
3333

3434
for (int i = FIRST_THEME_INDEX; i < tokens.size(); i++) {
35-
addTheme(context, dslFile, tokens.get(i));
35+
addTheme(context, dslFile, tokens.get(i), restricted);
3636
}
3737
}
3838

39-
private void addTheme(DslContext context, File dslFile, String theme) {
39+
private void addTheme(DslContext context, File dslFile, String theme, boolean restricted) {
4040
if (DEFAULT_THEME_NAME.equalsIgnoreCase(theme)) {
4141
theme = DEFAULT_THEME_URL;
4242
}
@@ -45,20 +45,26 @@ private void addTheme(DslContext context, File dslFile, String theme) {
4545
// this adds the theme to the list of theme URLs in the workspace
4646
context.getWorkspace().getViews().getConfiguration().addTheme(theme);
4747
} else {
48-
// this inlines the file-based theme into the workspace
49-
File file = new File(dslFile.getParentFile(), theme);
50-
if (file.exists()) {
51-
if (file.isFile()) {
52-
try {
53-
ThemeUtils.inlineTheme(context.getWorkspace(), file);
54-
} catch (Exception e) {
55-
throw new RuntimeException("Error loading theme from " + file.getAbsolutePath() + ": " + e.getMessage());
48+
if (!restricted) {
49+
context.setDslPortable(false);
50+
51+
// this inlines the file-based theme into the workspace
52+
File file = new File(dslFile.getParentFile(), theme);
53+
if (file.exists()) {
54+
if (file.isFile()) {
55+
try {
56+
ThemeUtils.inlineTheme(context.getWorkspace(), file);
57+
} catch (Exception e) {
58+
throw new RuntimeException("Error loading theme from " + file.getAbsolutePath() + ": " + e.getMessage());
59+
}
60+
} else {
61+
throw new RuntimeException(file.getAbsolutePath() + " is not a file");
5662
}
5763
} else {
58-
throw new RuntimeException(file.getAbsolutePath() + " is not a file");
64+
throw new RuntimeException(file.getAbsolutePath() + " does not exist");
5965
}
6066
} else {
61-
throw new RuntimeException(file.getAbsolutePath() + " does not exist");
67+
throw new RuntimeException("File-based themes are not supported when the DSL parser is running in restricted mode");
6268
}
6369
}
6470
}

structurizr-dsl/src/test/java/com/structurizr/dsl/ThemeParserTests.java

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class ThemeParserTests extends AbstractTests {
1313
@Test
1414
void test_parseTheme_ThrowsAnException_WhenThereAreTooManyTokens() {
1515
try {
16-
parser.parseTheme(context(), null, tokens("theme", "url", "extra"));
16+
parser.parseTheme(context(), null, tokens("theme", "url", "extra"), false);
1717
fail();
1818
} catch (Exception e) {
1919
assertEquals("Too many tokens, expected: theme <url|file>", e.getMessage());
@@ -23,7 +23,7 @@ void test_parseTheme_ThrowsAnException_WhenThereAreTooManyTokens() {
2323
@Test
2424
void test_parseTheme_ThrowsAnException_WhenNoThemeIsSpecified() {
2525
try {
26-
parser.parseTheme(context(), null, tokens("theme"));
26+
parser.parseTheme(context(), null, tokens("theme"), false);
2727
fail();
2828
} catch (Exception e) {
2929
assertEquals("Expected: theme <url|file>", e.getMessage());
@@ -32,15 +32,15 @@ void test_parseTheme_ThrowsAnException_WhenNoThemeIsSpecified() {
3232

3333
@Test
3434
void test_parseTheme_AddsTheTheme_WhenAThemeIsSpecified() {
35-
parser.parseTheme(context(), null, tokens("theme", "http://example.com/1"));
35+
parser.parseTheme(context(), null, tokens("theme", "http://example.com/1"), false);
3636

3737
assertEquals(1, workspace.getViews().getConfiguration().getThemes().length);
3838
assertEquals("http://example.com/1", workspace.getViews().getConfiguration().getThemes()[0]);
3939
}
4040

4141
@Test
4242
void test_parseTheme_AddsTheTheme_WhenTheDefaultThemeIsSpecified() {
43-
parser.parseTheme(context(), null, tokens("theme", "default"));
43+
parser.parseTheme(context(), null, tokens("theme", "default"), false);
4444

4545
assertEquals(1, workspace.getViews().getConfiguration().getThemes().length);
4646
assertEquals("https://static.structurizr.com/themes/default/theme.json", workspace.getViews().getConfiguration().getThemes()[0]);
@@ -49,7 +49,7 @@ void test_parseTheme_AddsTheTheme_WhenTheDefaultThemeIsSpecified() {
4949
@Test
5050
void test_parseThemes_ThrowsAnException_WhenNoThemesAreSpecified() {
5151
try {
52-
parser.parseThemes(context(), null, tokens("themes"));
52+
parser.parseThemes(context(), null, tokens("themes"), false);
5353
fail();
5454
} catch (Exception e) {
5555
assertEquals("Expected: themes <url|file> [url|file] ... [url|file]", e.getMessage());
@@ -58,15 +58,15 @@ void test_parseThemes_ThrowsAnException_WhenNoThemesAreSpecified() {
5858

5959
@Test
6060
void test_parseThemes_AddsTheTheme_WhenOneThemeIsSpecified() {
61-
parser.parseThemes(context(), null, tokens("themes", "http://example.com/1"));
61+
parser.parseThemes(context(), null, tokens("themes", "http://example.com/1"), false);
6262

6363
assertEquals(1, workspace.getViews().getConfiguration().getThemes().length);
6464
assertEquals("http://example.com/1", workspace.getViews().getConfiguration().getThemes()[0]);
6565
}
6666

6767
@Test
6868
void test_parseThemes_AddsTheThemes_WhenMultipleThemesAreSpecified() {
69-
parser.parseThemes(context(), null, tokens("themes", "http://example.com/1", "http://example.com/2", "http://example.com/3"));
69+
parser.parseThemes(context(), null, tokens("themes", "http://example.com/1", "http://example.com/2", "http://example.com/3"), false);
7070

7171
assertEquals(3, workspace.getViews().getConfiguration().getThemes().length);
7272
assertEquals("http://example.com/1", workspace.getViews().getConfiguration().getThemes()[0]);
@@ -76,7 +76,7 @@ void test_parseThemes_AddsTheThemes_WhenMultipleThemesAreSpecified() {
7676

7777
@Test
7878
void test_parseThemes_AddsTheTheme_WhenTheDefaultThemeIsSpecified() {
79-
parser.parseThemes(context(), null, tokens("themes", "default"));
79+
parser.parseThemes(context(), null, tokens("themes", "default"), false);
8080

8181
assertEquals(1, workspace.getViews().getConfiguration().getThemes().length);
8282
assertEquals("https://static.structurizr.com/themes/default/theme.json", workspace.getViews().getConfiguration().getThemes()[0]);
@@ -86,7 +86,7 @@ void test_parseThemes_AddsTheTheme_WhenTheDefaultThemeIsSpecified() {
8686
void test_parseTheme_ThrowsAnException_WhenTheThemeFileDoesNotExist() {
8787
File dslFile = new File("src/test/resources/themes/workspace.dsl");
8888
try {
89-
parser.parseTheme(context(), dslFile, tokens("theme", "my-theme.json"));
89+
parser.parseTheme(context(), dslFile, tokens("theme", "my-theme.json"), false);
9090
fail();
9191
} catch (Exception e) {
9292
assertTrue(e.getMessage().endsWith("/src/test/resources/themes/my-theme.json does not exist"));
@@ -97,7 +97,7 @@ void test_parseTheme_ThrowsAnException_WhenTheThemeFileDoesNotExist() {
9797
void test_parseTheme_ThrowsAnException_WhenTheThemeFileIsADirectory() {
9898
File dslFile = new File("src/test/resources/workspace.dsl");
9999
try {
100-
parser.parseTheme(context(), dslFile, tokens("theme", "themes"));
100+
parser.parseTheme(context(), dslFile, tokens("theme", "themes"), false);
101101
fail();
102102
} catch (Exception e) {
103103
assertTrue(e.getMessage().endsWith("/src/test/resources/themes is not a file"));
@@ -107,11 +107,22 @@ void test_parseTheme_ThrowsAnException_WhenTheThemeFileIsADirectory() {
107107
@Test
108108
void test_parseTheme_InlinesTheTheme_WhenAThemeFileIsSpecified() {
109109
File dslFile = new File("src/test/resources/themes/workspace.dsl");
110-
parser.parseTheme(context(), dslFile, tokens("theme", "theme.json"));
110+
parser.parseTheme(context(), dslFile, tokens("theme", "theme.json"), false);
111111

112112
assertEquals(0, workspace.getViews().getConfiguration().getThemes().length);
113113
assertEquals("#ff0000", workspace.getViews().getConfiguration().getStyles().getElementStyle("Tag").getBackground());
114114
assertEquals("#00ff00", workspace.getViews().getConfiguration().getStyles().getRelationshipStyle("Tag").getColor());
115115
}
116116

117+
@Test
118+
void test_parseTheme_ThrowsAnException_WhenAThemeFileIsSpecifiedAndTheParserIsRunningInRestrictedMode() {
119+
try {
120+
File dslFile = new File("src/test/resources/themes/workspace.dsl");
121+
parser.parseTheme(context(), dslFile, tokens("theme", "theme.json"), true);
122+
fail();
123+
} catch (Exception e) {
124+
assertEquals("File-based themes are not supported when the DSL parser is running in restricted mode", e.getMessage());
125+
}
126+
}
127+
117128
}

0 commit comments

Comments
 (0)