diff --git a/build.gradle b/build.gradle index 1e221f2..a2bce9a 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ repositories { } dependencies { - api 'com.structurizr:structurizr-client:1.25.1' + api 'com.structurizr:structurizr-client:1.26.1' api 'com.structurizr:structurizr-import:1.5.0' testImplementation 'org.codehaus.groovy:groovy-jsr223:3.0.16' @@ -27,7 +27,7 @@ targetCompatibility = 11 description = 'Structurizr DSL' group = 'com.structurizr' -version = '1.31.1' +version = '1.32.0' test { useJUnitPlatform() diff --git a/docs/changelog.md b/docs/changelog.md index 9048ef7..c342fcc 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,5 +1,10 @@ # Changelog +## 1.32.0 (28th July 2023) + +- Adds the ability to specify the workspace `visibility` (private/public) via the workspace configuration. +- Updates structurizr/java to [v1.26.1](https://github.com/structurizr/java/releases/tag/v1.26.1). + ## 1.31.1 (26th July 2023) - Fixes https://github.com/structurizr/dsl/issues/308 (Hidden (e.g. .DS_Store) file causes exception during !include ). diff --git a/docs/language-reference.md b/docs/language-reference.md index c5f49b4..dc132b7 100644 --- a/docs/language-reference.md +++ b/docs/language-reference.md @@ -1514,9 +1514,18 @@ configuration { Permitted children: +- [visibility](#visibility) - [users](#users) - [properties](#properties) +### visibility + +The `visibility` keyword can be used to set the [visibility of the workspace](https://structurizr.com/help/workspace-sharing). + +``` +visibility +``` + ### users The `users` block can be used to specify the users who should have read-only or read-write access to a workspace. Each username (e.g. e-mail address) and role pair should be specified on their own line. Valid roles are `read` (read-only) and `write` (read-write). diff --git a/src/main/java/com/structurizr/dsl/ConfigurationDslContext.java b/src/main/java/com/structurizr/dsl/ConfigurationDslContext.java index cad575d..f8df431 100644 --- a/src/main/java/com/structurizr/dsl/ConfigurationDslContext.java +++ b/src/main/java/com/structurizr/dsl/ConfigurationDslContext.java @@ -2,9 +2,15 @@ final class ConfigurationDslContext extends DslContext { + private static final int FIRST_PROPERTY_INDEX = 1; + + private static final String PRIVATE = "private"; + private static final String PUBLIC = "public"; + @Override protected String[] getPermittedTokens() { return new String[] { + StructurizrDslTokens.VISIBILITY_TOKEN, StructurizrDslTokens.USERS_TOKEN, StructurizrDslTokens.PROPERTIES_TOKEN }; diff --git a/src/main/java/com/structurizr/dsl/ConfigurationParser.java b/src/main/java/com/structurizr/dsl/ConfigurationParser.java new file mode 100644 index 0000000..702f12d --- /dev/null +++ b/src/main/java/com/structurizr/dsl/ConfigurationParser.java @@ -0,0 +1,34 @@ +package com.structurizr.dsl; + +import com.structurizr.configuration.Visibility; + +final class ConfigurationParser extends AbstractParser { + + private static final String GRAMMAR = "visibility "; + + private static final int FIRST_PROPERTY_INDEX = 1; + + private static final String PRIVATE = "private"; + private static final String PUBLIC = "public"; + + void parseVisibility(DslContext context, Tokens tokens) { + if (tokens.hasMoreThan(FIRST_PROPERTY_INDEX)) { + throw new RuntimeException("Too many tokens, expected: " + GRAMMAR); + } + + if (tokens.includes(FIRST_PROPERTY_INDEX)) { + String visibility = tokens.get(1).toLowerCase(); + + if (visibility.equalsIgnoreCase(PRIVATE)) { + context.getWorkspace().getConfiguration().setVisibility(Visibility.Private); + } else if (visibility.equalsIgnoreCase(PUBLIC)) { + context.getWorkspace().getConfiguration().setVisibility(Visibility.Public); + } else { + throw new RuntimeException("The visibility \"" + visibility + "\" is not valid"); + } + } else { + throw new RuntimeException("Expected: " + GRAMMAR); + } + } + +} \ No newline at end of file diff --git a/src/main/java/com/structurizr/dsl/StructurizrDslParser.java b/src/main/java/com/structurizr/dsl/StructurizrDslParser.java index 58e2e71..dc44711 100644 --- a/src/main/java/com/structurizr/dsl/StructurizrDslParser.java +++ b/src/main/java/com/structurizr/dsl/StructurizrDslParser.java @@ -786,6 +786,9 @@ void parse(List lines, File dslFile) throws StructurizrDslParserExceptio } else if (CONFIGURATION_TOKEN.equalsIgnoreCase(firstToken) && inContext(WorkspaceDslContext.class)) { startContext(new ConfigurationDslContext()); + } else if (VISIBILITY_TOKEN.equalsIgnoreCase(firstToken) && inContext(ConfigurationDslContext.class)) { + new ConfigurationParser().parseVisibility(getContext(), tokens); + } else if (USERS_TOKEN.equalsIgnoreCase(firstToken) && inContext(ConfigurationDslContext.class)) { startContext(new UsersDslContext()); diff --git a/src/main/java/com/structurizr/dsl/StructurizrDslTokens.java b/src/main/java/com/structurizr/dsl/StructurizrDslTokens.java index 833a68e..3d76df6 100644 --- a/src/main/java/com/structurizr/dsl/StructurizrDslTokens.java +++ b/src/main/java/com/structurizr/dsl/StructurizrDslTokens.java @@ -88,6 +88,7 @@ class StructurizrDslTokens { static final String THEME_TOKEN = "theme"; static final String THEMES_TOKEN = "themes"; static final String CONFIGURATION_TOKEN = "configuration"; + static final String VISIBILITY_TOKEN = "visibility"; static final String TERMINOLOGY_TOKEN = "terminology"; static final String TERMINOLOGY_RELATIONSHIP_TOKEN = "relationship"; static final String USERS_TOKEN = "users"; diff --git a/src/test/java/com/structurizr/dsl/ConfigurationParserTests.java b/src/test/java/com/structurizr/dsl/ConfigurationParserTests.java new file mode 100644 index 0000000..4eff20e --- /dev/null +++ b/src/test/java/com/structurizr/dsl/ConfigurationParserTests.java @@ -0,0 +1,49 @@ +package com.structurizr.dsl; + +import com.structurizr.configuration.Visibility; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +class ConfigurationParserTests extends AbstractTests { + + private final ConfigurationParser parser = new ConfigurationParser(); + + @Test + void test_parseVisibility_ThrowsAnException_WhenThereAreTooManyTokens() { + try { + parser.parseVisibility(context(), tokens("visibility", "public", "extra")); + fail(); + } catch (Exception e) { + assertEquals("Too many tokens, expected: visibility ", e.getMessage()); + } + } + + @Test + void test_parseVisibility_ThrowsAnException_WhenTheVisibilityIsMissing() { + try { + parser.parseVisibility(context(), tokens("visibility")); + fail(); + } catch (Exception e) { + assertEquals("Expected: visibility ", e.getMessage()); + } + } + + @Test + void test_parseVisibility_ThrowsAnException_WhenTheVisibilityIsNotValid() { + try { + parser.parseVisibility(context(), tokens("visibility", "shared")); + fail(); + } catch (Exception e) { + assertEquals("The visibility \"shared\" is not valid", e.getMessage()); + } + } + + @Test + void test_parseVisibility_SetsTheVisibility() { + parser.parseVisibility(context(), tokens("visibility", "public")); + assertEquals(Visibility.Public, workspace.getConfiguration().getVisibility()); + } + +} \ No newline at end of file