diff --git a/backend/build.gradle.kts b/backend/build.gradle.kts index 64d7d810..17c87c40 100644 --- a/backend/build.gradle.kts +++ b/backend/build.gradle.kts @@ -4,7 +4,9 @@ plugins { } dependencies { - implementation(projects.core) + implementation(projects.core.coreData) + implementation(projects.core.coreUsers) + implementation(projects.core.coreDomain) implementation(projects.fake) implementation(projects.mongo) implementation(projects.remoteServer) diff --git a/build.gradle.kts b/build.gradle.kts index 937978b0..661d2b69 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -62,3 +62,10 @@ fun calculateVersion(): String { else "${details.lastTag}-post.${details.commitDistance}+${details.gitHash}" } + +// Workaround for https://github.com/Kotlin/dokka/issues/2954 +tasks.named("dokkaHtmlMultiModule") { + dependsOn( + ":core:dokkaHtmlMultiModule", + ) +} diff --git a/core/core-data/README.md b/core/core-data/README.md new file mode 100644 index 00000000..4d79b8da --- /dev/null +++ b/core/core-data/README.md @@ -0,0 +1,3 @@ +# Module core-data + +Data structures and other helpers for the other core modules. diff --git a/core/core-data/build.gradle.kts b/core/core-data/build.gradle.kts new file mode 100644 index 00000000..024c11c1 --- /dev/null +++ b/core/core-data/build.gradle.kts @@ -0,0 +1,51 @@ +import java.net.URL + +plugins { + kotlin("multiplatform") +} + +kotlin { + jvm { + jvmToolchain(17) + testRuns.named("test") { + executionTask.configure { + useJUnitPlatform() + } + } + } + js(IR) { + browser { + testTask { + useMocha { + timeout = "1 minute" + } + } + } + } + + sourceSets { + val commonMain by getting { + dependencies { + // Nothing here + } + } + + val commonTest by getting { + dependencies { + implementation(projects.testStructure) + } + } + } +} + +tasks.withType().configureEach { + dokkaSourceSets.configureEach { + includes.from("${project.projectDir}/README.md") + + sourceLink { + localDirectory.set(file("src")) + remoteUrl.set(URL("https://gitlab.com/opensavvy/formulaide/-/blob/main/core/core-data/src")) + remoteLineSuffix.set("#L") + } + } +} diff --git a/core/core-data/src/commonMain/kotlin/Marker.kt b/core/core-data/src/commonMain/kotlin/Marker.kt new file mode 100644 index 00000000..fc80ed69 --- /dev/null +++ b/core/core-data/src/commonMain/kotlin/Marker.kt @@ -0,0 +1,3 @@ +package opensavvy.formulaide.core + +// This is a marker for the package declaration diff --git a/core/src/commonMain/kotlin/data/Email.kt b/core/core-data/src/commonMain/kotlin/data/Email.kt similarity index 100% rename from core/src/commonMain/kotlin/data/Email.kt rename to core/core-data/src/commonMain/kotlin/data/Email.kt diff --git a/core/src/commonMain/kotlin/data/Failures.kt b/core/core-data/src/commonMain/kotlin/data/Failures.kt similarity index 100% rename from core/src/commonMain/kotlin/data/Failures.kt rename to core/core-data/src/commonMain/kotlin/data/Failures.kt diff --git a/core/src/commonMain/kotlin/data/Password.kt b/core/core-data/src/commonMain/kotlin/data/Password.kt similarity index 100% rename from core/src/commonMain/kotlin/data/Password.kt rename to core/core-data/src/commonMain/kotlin/data/Password.kt diff --git a/core/src/commonMain/kotlin/data/Token.kt b/core/core-data/src/commonMain/kotlin/data/Token.kt similarity index 100% rename from core/src/commonMain/kotlin/data/Token.kt rename to core/core-data/src/commonMain/kotlin/data/Token.kt diff --git a/core/src/commonMain/kotlin/utils/Identifier.kt b/core/core-data/src/commonMain/kotlin/utils/Identifier.kt similarity index 100% rename from core/src/commonMain/kotlin/utils/Identifier.kt rename to core/core-data/src/commonMain/kotlin/utils/Identifier.kt diff --git a/core/core-data/src/commonTest/kotlin/Marker.kt b/core/core-data/src/commonTest/kotlin/Marker.kt new file mode 100644 index 00000000..fc80ed69 --- /dev/null +++ b/core/core-data/src/commonTest/kotlin/Marker.kt @@ -0,0 +1,3 @@ +package opensavvy.formulaide.core + +// This is a marker for the package declaration diff --git a/core/src/commonTest/kotlin/data/EmailTest.kt b/core/core-data/src/commonTest/kotlin/data/EmailTest.kt similarity index 100% rename from core/src/commonTest/kotlin/data/EmailTest.kt rename to core/core-data/src/commonTest/kotlin/data/EmailTest.kt diff --git a/core/README.md b/core/core-domain/README.md similarity index 65% rename from core/README.md rename to core/core-domain/README.md index c84f52d4..f834c7f7 100644 --- a/core/README.md +++ b/core/core-domain/README.md @@ -1,20 +1,6 @@ -# Module core +# Module core-domain -Core APIs for the Formulaide project. - -Formulaide administrators can create web forms entirely online, and declare how the data submitted by users is shared between departments of the company to ensure each request is checked by the correct people. - -## Users and departments - -There are two types of [users][opensavvy.formulaide.core.User] of Formulaide: the end users, called [guests][opensavvy.formulaide.core.User.Role.Guest], and [employees][opensavvy.formulaide.core.User.Role.Employee]. - -Guests can submit data to the available forms. They are always anonymous and unauthenticated, and therefore cannot access any data (even their own). - -Employees can also submit data to forms, as well as accessing internal forms. -Employees are part of [departments][opensavvy.formulaide.core.Department], which represent the different sections of the company or association using Formulaide. -End user submissions are protected to only be visible by employees belonging to specific departments. - -The [administrator][opensavvy.formulaide.core.User.Role.Administrator] is a specific role given to employees who are allowed to manage Formulaide itself. They can create and edit forms, browse through all user data, and delete data permanently to comply with GDPR requests. +Core functionality of the Formulaide project. ## Form structure @@ -41,7 +27,3 @@ The companion service is an interface that describes the contract all Formulaide Because each object is immutable, the companion reference is used to access their values over time. This avoids data nesting in other data structures, and makes it easier for a client to only request information they do not already possess. For more information about this design pattern, see the [Pedestal](https://gitlab.com/opensavvy/pedestal) project. - -# Package opensavvy.formulaide.core.data - -Additional data structures created for convenience and type safety. diff --git a/core/core-domain/build.gradle.kts b/core/core-domain/build.gradle.kts new file mode 100644 index 00000000..60c4367f --- /dev/null +++ b/core/core-domain/build.gradle.kts @@ -0,0 +1,57 @@ +import java.net.URL + +plugins { + kotlin("multiplatform") +} + +kotlin { + jvm { + jvmToolchain(17) + testRuns.named("test") { + executionTask.configure { + useJUnitPlatform() + } + } + } + js(IR) { + browser { + testTask { + useMocha { + timeout = "1 minute" + } + } + } + } + + sourceSets { + val commonMain by getting { + dependencies { + api("opensavvy.pedestal:backbone:_") + api("opensavvy.pedestal:state-arrow:_") + api(KotlinX.datetime) + + api(projects.core.coreData) + api(projects.core.coreUsers) + } + } + + val commonTest by getting { + dependencies { + implementation(projects.test) + implementation(projects.fake) + } + } + } +} + +tasks.withType().configureEach { + dokkaSourceSets.configureEach { + includes.from("${project.projectDir}/README.md") + + sourceLink { + localDirectory.set(file("src")) + remoteUrl.set(URL("https://gitlab.com/opensavvy/formulaide/-/blob/main/core/core-domain/src")) + remoteLineSuffix.set("#L") + } + } +} diff --git a/core/src/commonMain/kotlin/Field.kt b/core/core-domain/src/commonMain/kotlin/Field.kt similarity index 100% rename from core/src/commonMain/kotlin/Field.kt rename to core/core-domain/src/commonMain/kotlin/Field.kt diff --git a/core/src/commonMain/kotlin/File.kt b/core/core-domain/src/commonMain/kotlin/File.kt similarity index 100% rename from core/src/commonMain/kotlin/File.kt rename to core/core-domain/src/commonMain/kotlin/File.kt diff --git a/core/src/commonMain/kotlin/Form.kt b/core/core-domain/src/commonMain/kotlin/Form.kt similarity index 100% rename from core/src/commonMain/kotlin/Form.kt rename to core/core-domain/src/commonMain/kotlin/Form.kt diff --git a/core/src/commonMain/kotlin/Input.kt b/core/core-domain/src/commonMain/kotlin/Input.kt similarity index 100% rename from core/src/commonMain/kotlin/Input.kt rename to core/core-domain/src/commonMain/kotlin/Input.kt diff --git a/core/src/commonMain/kotlin/Record.kt b/core/core-domain/src/commonMain/kotlin/Record.kt similarity index 100% rename from core/src/commonMain/kotlin/Record.kt rename to core/core-domain/src/commonMain/kotlin/Record.kt diff --git a/core/src/commonMain/kotlin/Submission.kt b/core/core-domain/src/commonMain/kotlin/Submission.kt similarity index 100% rename from core/src/commonMain/kotlin/Submission.kt rename to core/core-domain/src/commonMain/kotlin/Submission.kt diff --git a/core/src/commonMain/kotlin/Template.kt b/core/core-domain/src/commonMain/kotlin/Template.kt similarity index 100% rename from core/src/commonMain/kotlin/Template.kt rename to core/core-domain/src/commonMain/kotlin/Template.kt diff --git a/core/src/commonTest/kotlin/FieldTest.kt b/core/core-domain/src/commonTest/kotlin/FieldTest.kt similarity index 100% rename from core/src/commonTest/kotlin/FieldTest.kt rename to core/core-domain/src/commonTest/kotlin/FieldTest.kt diff --git a/core/src/commonTest/kotlin/ImportedFieldTest.kt b/core/core-domain/src/commonTest/kotlin/ImportedFieldTest.kt similarity index 100% rename from core/src/commonTest/kotlin/ImportedFieldTest.kt rename to core/core-domain/src/commonTest/kotlin/ImportedFieldTest.kt diff --git a/core/src/commonTest/kotlin/InputTest.kt b/core/core-domain/src/commonTest/kotlin/InputTest.kt similarity index 78% rename from core/src/commonTest/kotlin/InputTest.kt rename to core/core-domain/src/commonTest/kotlin/InputTest.kt index 7d409a08..723db614 100644 --- a/core/src/commonTest/kotlin/InputTest.kt +++ b/core/core-domain/src/commonTest/kotlin/InputTest.kt @@ -61,39 +61,39 @@ class InputTest : TestExecutor() { val files = FakeFiles(clock) val bool = Input.Toggle - bool.parse("true", files).shouldSucceedAnd { + Input.Toggle.parse("true", files).shouldSucceedAnd { assertEquals(true, it) } - bool.parse("false", files).shouldSucceedAnd { + Input.Toggle.parse("false", files).shouldSucceedAnd { assertEquals(false, it) } - bool.parse("other", files) shouldFailWithType Input.Failures.Parsing::class - bool.parse("something", files) shouldFailWithType Input.Failures.Parsing::class + Input.Toggle.parse("other", files) shouldFailWithType Input.Failures.Parsing::class + Input.Toggle.parse("something", files) shouldFailWithType Input.Failures.Parsing::class } test("Email") { val files = FakeFiles(clock) val email = Input.Email - email.parse("my-email@gmail.com", files).shouldSucceedAnd { + Input.Email.parse("my-email@gmail.com", files).shouldSucceedAnd { assertEquals(Email("my-email@gmail.com"), it) } - email.parse("something", files) shouldFailWithType Input.Failures.Parsing::class + Input.Email.parse("something", files) shouldFailWithType Input.Failures.Parsing::class } test("Parse phone number") { val files = FakeFiles(clock) val phone = Input.Phone - phone.parse("+332345678", files).shouldSucceedAnd { + Input.Phone.parse("+332345678", files).shouldSucceedAnd { assertEquals("+332345678", it) } - phone.parse("thing", files) shouldFailWithType Input.Failures.Parsing::class - phone.parse("123456789123456789123456789", files) shouldFailWithType Input.Failures.Parsing::class + Input.Phone.parse("thing", files) shouldFailWithType Input.Failures.Parsing::class + Input.Phone.parse("123456789123456789123456789", files) shouldFailWithType Input.Failures.Parsing::class } test("Int range constructor") { diff --git a/core/src/commonTest/kotlin/SubmissionTest.kt b/core/core-domain/src/commonTest/kotlin/SubmissionTest.kt similarity index 100% rename from core/src/commonTest/kotlin/SubmissionTest.kt rename to core/core-domain/src/commonTest/kotlin/SubmissionTest.kt diff --git a/core/core-users/README.md b/core/core-users/README.md new file mode 100644 index 00000000..e8fed621 --- /dev/null +++ b/core/core-users/README.md @@ -0,0 +1,13 @@ +# Module core-users + +Authentication and role management for Formulaide users. + +There are two types of [users][opensavvy.formulaide.core.User] of Formulaide: the end users, called [guests][opensavvy.formulaide.core.User.Role.Guest], and [employees][opensavvy.formulaide.core.User.Role.Employee]. + +Guests can submit data to the available forms. They are always anonymous and unauthenticated, and therefore cannot access any data (even their own). + +Employees can also submit data to forms, as well as accessing internal forms. +Employees are part of [departments][opensavvy.formulaide.core.Department], which represent the different sections of the company or association using Formulaide. +End user submissions are protected to only be visible by employees belonging to specific departments. + +The [administrator][opensavvy.formulaide.core.User.Role.Administrator] is a specific role given to employees who are allowed to manage Formulaide itself. They can create and edit forms, browse through all user data, and delete data permanently to comply with GDPR requests. diff --git a/core/build.gradle.kts b/core/core-users/build.gradle.kts similarity index 91% rename from core/build.gradle.kts rename to core/core-users/build.gradle.kts index 67dff344..8f47912f 100644 --- a/core/build.gradle.kts +++ b/core/core-users/build.gradle.kts @@ -1,5 +1,3 @@ -@file:Suppress("UNUSED_VARIABLE") - import java.net.URL plugins { @@ -30,7 +28,8 @@ kotlin { dependencies { api("opensavvy.pedestal:backbone:_") api("opensavvy.pedestal:state-arrow:_") - api(KotlinX.datetime) + + api(projects.core.coreData) } } @@ -49,7 +48,7 @@ tasks.withType().configureEach { sourceLink { localDirectory.set(file("src")) - remoteUrl.set(URL("https://gitlab.com/opensavvy/formulaide/-/blob/main/core/src")) + remoteUrl.set(URL("https://gitlab.com/opensavvy/formulaide/-/blob/main/core/core-users/src")) remoteLineSuffix.set("#L") } } diff --git a/core/src/commonMain/kotlin/Auth.kt b/core/core-users/src/commonMain/kotlin/Auth.kt similarity index 100% rename from core/src/commonMain/kotlin/Auth.kt rename to core/core-users/src/commonMain/kotlin/Auth.kt diff --git a/core/src/commonMain/kotlin/Department.kt b/core/core-users/src/commonMain/kotlin/Department.kt similarity index 100% rename from core/src/commonMain/kotlin/Department.kt rename to core/core-users/src/commonMain/kotlin/Department.kt diff --git a/core/src/commonMain/kotlin/User.kt b/core/core-users/src/commonMain/kotlin/User.kt similarity index 100% rename from core/src/commonMain/kotlin/User.kt rename to core/core-users/src/commonMain/kotlin/User.kt diff --git a/core/src/commonTest/kotlin/UserTest.kt b/core/core-users/src/commonTest/kotlin/UserTest.kt similarity index 100% rename from core/src/commonTest/kotlin/UserTest.kt rename to core/core-users/src/commonTest/kotlin/UserTest.kt diff --git a/fake/build.gradle.kts b/fake/build.gradle.kts index cef73a7a..8b87b3c9 100644 --- a/fake/build.gradle.kts +++ b/fake/build.gradle.kts @@ -26,7 +26,9 @@ kotlin { sourceSets { val commonMain by getting { dependencies { - api(projects.core) + api(projects.core.coreData) + api(projects.core.coreUsers) + api(projects.core.coreDomain) implementation("opensavvy.pedestal:logger:_") } diff --git a/mongo/build.gradle.kts b/mongo/build.gradle.kts index ad304fc9..757bb15a 100644 --- a/mongo/build.gradle.kts +++ b/mongo/build.gradle.kts @@ -6,7 +6,9 @@ plugins { } dependencies { - api(projects.core) + api(projects.core.coreData) + api(projects.core.coreUsers) + api(projects.core.coreDomain) api(KotlinX.coroutines.core) implementation("org.litote.kmongo:kmongo-coroutine-serialization:_") diff --git a/remote-common/build.gradle.kts b/remote-common/build.gradle.kts index ef590335..a8ddccc7 100644 --- a/remote-common/build.gradle.kts +++ b/remote-common/build.gradle.kts @@ -29,7 +29,9 @@ kotlin { sourceSets { val commonMain by getting { dependencies { - api(projects.core) + api(projects.core.coreData) + api(projects.core.coreUsers) + api(projects.core.coreDomain) api("opensavvy.pedestal:spine:_") api(KotlinX.serialization.core) diff --git a/remote-common/src/commonMain/kotlin/dto/FieldDto.kt b/remote-common/src/commonMain/kotlin/dto/FieldDto.kt index ea5a5712..0fd4d340 100644 --- a/remote-common/src/commonMain/kotlin/dto/FieldDto.kt +++ b/remote-common/src/commonMain/kotlin/dto/FieldDto.kt @@ -3,7 +3,6 @@ package opensavvy.formulaide.remote.dto import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import opensavvy.formulaide.core.Field -import opensavvy.formulaide.core.Input import opensavvy.formulaide.core.Template import opensavvy.formulaide.remote.api import opensavvy.formulaide.remote.dto.InputDto.Companion.toCore diff --git a/settings.gradle.kts b/settings.gradle.kts index 67d16340..db9ee480 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -15,7 +15,10 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") include( "backend", - "core", + + "core:core-data", + "core:core-users", + "core:core-domain", "remote-common", "remote-client", diff --git a/test/build.gradle.kts b/test/build.gradle.kts index 291e7ace..1a297656 100644 --- a/test/build.gradle.kts +++ b/test/build.gradle.kts @@ -31,7 +31,9 @@ kotlin { val commonMain by getting { dependencies { - api(projects.core) + api(projects.core.coreData) + api(projects.core.coreUsers) + api(projects.core.coreDomain) api(projects.testStructure) } } diff --git a/versions.properties b/versions.properties index b0d7f9bd..8a4a0220 100644 --- a/versions.properties +++ b/versions.properties @@ -9,7 +9,7 @@ plugin.com.palantir.git-version=2.0.0 -plugin.org.jetbrains.dokka=1.8.10 +plugin.org.jetbrains.dokka=1.8.20 plugin.org.jetbrains.kotlinx.kover=0.6.1 @@ -19,7 +19,7 @@ version.ch.qos.logback..logback-classic=1.4.6 version.kotest=5.6.1 -version.kotlin=1.8.21 +version.kotlin=1.8.22 version.kotlinx.coroutines=1.7.0