diff --git a/api/.editorconfig b/api/.editorconfig new file mode 100644 index 0000000..0af84ce --- /dev/null +++ b/api/.editorconfig @@ -0,0 +1,17 @@ +# editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{kt, kts}] +indent_size = 4 +insert_final_newline = true +max_line_length = 120 +disabled_rules = no-wildcard-imports +kotlin_imports_layout = idea diff --git a/api/src/Dependencies.kt b/api/src/Dependencies.kt index bd1ce81..ddfa91e 100644 --- a/api/src/Dependencies.kt +++ b/api/src/Dependencies.kt @@ -44,7 +44,6 @@ val mainModule = DI.Module("main") { ) } - bind(tag = "auth") with singleton { simpleJwtFactory(instance().jwt.auth) } bind(tag = "refresh") with singleton { simpleJwtFactory(instance().jwt.refresh) } diff --git a/api/src/NotesApplication.kt b/api/src/NotesApplication.kt index 4996848..4d99927 100644 --- a/api/src/NotesApplication.kt +++ b/api/src/NotesApplication.kt @@ -12,7 +12,6 @@ import org.kodein.di.instance import org.slf4j.Logger import java.util.concurrent.TimeUnit - fun main() { val di = DI { import(mainModule) } val config by di.instance() @@ -41,7 +40,6 @@ fun serve(di: DI) { } } - fun Application.module(di: DI) { val builders: Set by di.instance() diff --git a/api/src/auth/UsernamePasswordCredential.kt b/api/src/auth/UsernamePasswordCredential.kt index 1945e7f..297b189 100644 --- a/api/src/auth/UsernamePasswordCredential.kt +++ b/api/src/auth/UsernamePasswordCredential.kt @@ -7,4 +7,4 @@ import io.ktor.auth.* * @property username * @property password */ -data class UsernamePasswordCredential(val username: String, val password: String) : Credential \ No newline at end of file +data class UsernamePasswordCredential(val username: String, val password: String) : Credential diff --git a/api/src/entities/Tag.kt b/api/src/entities/Tag.kt index 0ab35a3..b2bcb29 100644 --- a/api/src/entities/Tag.kt +++ b/api/src/entities/Tag.kt @@ -8,4 +8,4 @@ interface Tag : Entity { val id: Int var name: String var note: Note -} \ No newline at end of file +} diff --git a/api/src/features/ErrorFeature.kt b/api/src/features/ErrorFeature.kt index a174d6a..eb4edcc 100644 --- a/api/src/features/ErrorFeature.kt +++ b/api/src/features/ErrorFeature.kt @@ -8,7 +8,6 @@ import io.ktor.response.* import io.ktor.utils.io.errors.* import java.sql.SQLTransientConnectionException - class ErrorHandler : ApplicationBuilder({ install(StatusPages) { diff --git a/api/src/features/JacksonErrors.kt b/api/src/features/JacksonErrors.kt index 83b2a62..a6a0f9c 100644 --- a/api/src/features/JacksonErrors.kt +++ b/api/src/features/JacksonErrors.kt @@ -40,7 +40,6 @@ fun StatusPages.Configuration.jacksonErrors() { } } - class InvalidFormatError(val value: Any?, targetType: Class<*>) { val msg = "Wrong type" val required = targetType.simpleName diff --git a/api/src/features/Migration.kt b/api/src/features/Migration.kt index 6d335fe..1af3c7e 100644 --- a/api/src/features/Migration.kt +++ b/api/src/features/Migration.kt @@ -8,7 +8,6 @@ import kotlinx.coroutines.launch import org.flywaydb.core.Flyway import javax.sql.DataSource - class MigrationHook(migration: Migration) : ApplicationBuilder({ environment.monitor.subscribe(ApplicationStarted) { CoroutineScope(Dispatchers.IO).launch { diff --git a/api/src/routing/NoteRoutes.kt b/api/src/routing/NoteRoutes.kt index 2cba7ba..f858eca 100644 --- a/api/src/routing/NoteRoutes.kt +++ b/api/src/routing/NoteRoutes.kt @@ -29,7 +29,6 @@ class NoteRoutes(noteService: NoteService) : RoutingBuilder({ } }) - private fun Route.createNote(noteService: NoteService) { post { val userId = call.authenticatedUserId() @@ -42,7 +41,7 @@ private fun Route.createNote(noteService: NoteService) { private fun Route.getAllNotes(noteService: NoteService) { get { val userId = call.authenticatedUserId() - val limit = call.parameters["limit"]?.toInt() ?: 20// FIXME validate + val limit = call.parameters["limit"]?.toInt() ?: 20 // FIXME validate val after = call.parameters["after"]?.let { UUID.fromString(it) } // FIXME validate val notes = noteService.findAll(userId, limit, after) call.respond(notes) diff --git a/api/src/routing/UserRoutes.kt b/api/src/routing/UserRoutes.kt index 15e217a..8bf6bf3 100644 --- a/api/src/routing/UserRoutes.kt +++ b/api/src/routing/UserRoutes.kt @@ -59,7 +59,6 @@ private fun Route.deleteUser(userService: UserService) { } } - private fun Route.createUser(userService: UserService) { post { val user = call.receiveValidated(registerValidator) @@ -74,7 +73,6 @@ private fun Route.createUser(userService: UserService) { } } - private fun Route.login( userService: UserService, passwordHash: PasswordHash, @@ -99,7 +97,6 @@ private fun Route.login( } } - private fun Route.refreshToken(userService: UserService, authJWT: SimpleJWT, refreshJWT: SimpleJWT) { post { val token = call.receive().refreshToken diff --git a/api/src/services/NoteService.kt b/api/src/services/NoteService.kt index 894e816..18bce91 100644 --- a/api/src/services/NoteService.kt +++ b/api/src/services/NoteService.kt @@ -61,7 +61,6 @@ class NoteService(private val db: Database) { db.sequenceOf(Notes, withReferences = false).any { it.userId eq userId and (it.uuid eq uuid) } } - suspend fun create(userId: Int, note: Note): Note = launchIo { val uuid = UUID.randomUUID() val newNote = note.copy().apply { @@ -79,7 +78,6 @@ class NoteService(private val db: Database) { } } } - } newNote } @@ -126,7 +124,6 @@ class NoteService(private val db: Database) { it.noteUuid to note.uuid } } - } true } diff --git a/api/src/services/UserService.kt b/api/src/services/UserService.kt index 3e0137f..973fc13 100644 --- a/api/src/services/UserService.kt +++ b/api/src/services/UserService.kt @@ -27,7 +27,6 @@ class UserService(private val db: Database, private val passwordHash: PasswordHa .find { it.id eq id } } - suspend fun exists(username: String) = launchIo { db.sequenceOf(Users, withReferences = false) .any { it.username eq username } @@ -65,6 +64,4 @@ class UserService(private val db: Database, private val passwordHash: PasswordHa else -> error("??") } } - } - diff --git a/api/test/integration/routing/AuthControllerKtTest.kt b/api/test/integration/routing/AuthControllerKtTest.kt index 0de74f4..768aad2 100644 --- a/api/test/integration/routing/AuthControllerKtTest.kt +++ b/api/test/integration/routing/AuthControllerKtTest.kt @@ -35,7 +35,6 @@ class AuthControllerKtTest { private val passwordHash by kodein.instance() - init { val user = User { @@ -63,7 +62,6 @@ class AuthControllerKtTest { coEvery { userService.find(3) } returns null } - private val testEngine = TestApplicationEngine().apply { start() application.module(kodein) @@ -136,7 +134,6 @@ class AuthControllerKtTest { } res.status() `should be equal to` HttpStatusCode.BadRequest } - } @Nested @@ -195,7 +192,6 @@ class AuthControllerKtTest { res.status() `should be equal to` HttpStatusCode.Unauthorized res.content `should strictly be equal to json` """{msg: "Unauthorized"}""" } - } @Nested @@ -224,6 +220,4 @@ class AuthControllerKtTest { jsonObject.keyList() `should be equal to` listOf("msg") } } - - } diff --git a/api/test/integration/routing/UserControllerKtTest.kt b/api/test/integration/routing/UserControllerKtTest.kt index 797dfc8..a3c8c53 100644 --- a/api/test/integration/routing/UserControllerKtTest.kt +++ b/api/test/integration/routing/UserControllerKtTest.kt @@ -38,10 +38,8 @@ class UserControllerKtTest { coEvery { userService.exists(and(not("modified"), not("existing"))) } returns false coEvery { userService.exists(1) } returns true coEvery { userService.create("modified", any()) } returns null - } - private val kodein = DI { import(mainModule, allowOverride = true) bind(overrides = true) with instance(userService) @@ -79,7 +77,6 @@ class UserControllerKtTest { } } - @Nested inner class DeleteUser { @@ -102,5 +99,4 @@ class UserControllerKtTest { res2.content `should be equal to json` """{msg:"Not Found"}""" } } - } diff --git a/api/test/integration/services/NoteServiceTest.kt b/api/test/integration/services/NoteServiceTest.kt index 583f5c9..94f4bf0 100644 --- a/api/test/integration/services/NoteServiceTest.kt +++ b/api/test/integration/services/NoteServiceTest.kt @@ -47,15 +47,20 @@ class NoteServiceTest { val user = runBlocking { userService.create("test", "test")!! } val noteService by kodein.instance() val note = runBlocking { - noteService.create(user.id, Note { - this.title = "a note" - this.content = """# Title - | - |😝😝😝😝 - |another line - """.trimMargin() - this.tags = listOf("a", "tag") - }) + noteService.create( + user.id, + Note { + this.title = "a note" + this.content = + """ + |# Title + | + |😝😝😝😝 + |another line + """.trimMargin() + this.tags = listOf("a", "tag") + } + ) } println(note) @@ -78,26 +83,38 @@ class NoteServiceTest { val noteService by kodein.instance() runBlocking { - noteService.create(user.id, Note { - title = "test" - content = "" - tags = listOf("same") - }) - noteService.create(user.id, Note { - title = "test2" - content = "" - tags = listOf("same") - }) - noteService.create(user.id, Note { - title = "test3" - content = "" - tags = listOf("another") - }) - noteService.create(user2.id, Note { - title = "test" - content = "" - tags = listOf("user2") - }) + noteService.create( + user.id, + Note { + title = "test" + content = "" + tags = listOf("same") + } + ) + noteService.create( + user.id, + Note { + title = "test2" + content = "" + tags = listOf("same") + } + ) + noteService.create( + user.id, + Note { + title = "test3" + content = "" + tags = listOf("another") + } + ) + noteService.create( + user2.id, + Note { + title = "test" + content = "" + tags = listOf("user2") + } + ) } val user1Tags = runBlocking { noteService.getTags(user.id) } user1Tags `should be equal to` listOf("same", "another") @@ -111,27 +128,30 @@ class NoteServiceTest { val userService by kodein.instance() val user = runBlocking { userService.create(Faker().name().username(), "test") }!! val note = runBlocking { - noteService.create(user.id, Note { - this.title = "title" - this.content = "old content" - this.tags = emptyList() - }) + noteService.create( + user.id, + Note { + this.title = "title" + this.content = "old content" + this.tags = emptyList() + } + ) } val get = runBlocking { noteService.find(user.id, note.uuid) } runBlocking { - noteService.updateNote(user.id, Note { - uuid = note.uuid - title = "new title" - }) + noteService.updateNote( + user.id, + Note { + uuid = note.uuid + title = "new title" + } + ) } val updated = runBlocking { noteService.find(user.id, note.uuid) } println("updated: $updated") - } - - } @Nested @@ -150,58 +170,70 @@ class NoteServiceTest { val hasTags = note["tags"] != null && note.tags.isNotEmpty() return hasTitle || hasContent || hasTags } - } val userValidator: Validator = ValidatorBuilder() .constraintOnTarget(fieldPresentConstraint, "present") .build() - userValidator.validate(Note { - title = "this is a title" - }).isValid `should be equal to` true + userValidator.validate( + Note { + title = "this is a title" + } + ).isValid `should be equal to` true - userValidator.validate(Note { - content = "this is a title" - }).isValid `should be equal to` true + userValidator.validate( + Note { + content = "this is a title" + } + ).isValid `should be equal to` true - userValidator.validate(Note { - tags = emptyList() - }).isValid `should be equal to` false + userValidator.validate( + Note { + tags = emptyList() + } + ).isValid `should be equal to` false - userValidator.validate(Note { - tags = listOf("tags") - }).isValid `should be equal to` true + userValidator.validate( + Note { + tags = listOf("tags") + } + ).isValid `should be equal to` true - userValidator.validate(Note { - tags = listOf("tags") - title = "This is a title" - }).isValid `should be equal to` true + userValidator.validate( + Note { + tags = listOf("tags") + title = "This is a title" + } + ).isValid `should be equal to` true - userValidator.validate(Note { - tags = listOf("tags") - title = "This is a title" - content = """ - # This is - - some markdown content - """.trimIndent() - }).isValid `should be equal to` true + userValidator.validate( + Note { + tags = listOf("tags") + title = "This is a title" + content = + """ + |# This is + | + |some markdown content + """.trimMargin() + } + ).isValid `should be equal to` true - userValidator.validate(Note { - tags = listOf("tags") - title = "This is a title" - content = """ - # This is - - some markdown content - """.trimIndent() - }).isValid `should be equal to` true + userValidator.validate( + Note { + tags = listOf("tags") + title = "This is a title" + content = + """ + |# This is + | + |some markdown content + """.trimMargin() + } + ).isValid `should be equal to` true userValidator.validate(Note()).isValid `should be equal to` false - - } - } @Nested @@ -222,6 +254,4 @@ class NoteServiceTest { println(note.uuid.mostSignificantBits) } } - - } diff --git a/api/test/integration/services/UserServiceTest.kt b/api/test/integration/services/UserServiceTest.kt index 57905ab..d222345 100644 --- a/api/test/integration/services/UserServiceTest.kt +++ b/api/test/integration/services/UserServiceTest.kt @@ -12,7 +12,6 @@ import org.kodein.di.instance import org.kodein.di.singleton import utils.KMariadbContainer - @TestInstance(TestInstance.Lifecycle.PER_CLASS) @TestMethodOrder(MethodOrderer.OrderAnnotation::class) class UserServiceTest { @@ -21,7 +20,7 @@ class UserServiceTest { private val kodein = DI { import(mainModule, allowOverride = true) - bind( overrides = true) from singleton { mariadb.datasource() } + bind(overrides = true) from singleton { mariadb.datasource() } } private val userService by kodein.instance() @@ -64,5 +63,4 @@ class UserServiceTest { userService.find(id) `should be` null } } - } diff --git a/api/test/unit/validation/RegisterValidationTest.kt b/api/test/unit/validation/RegisterValidationTest.kt index 767e246..ac983ba 100644 --- a/api/test/unit/validation/RegisterValidationTest.kt +++ b/api/test/unit/validation/RegisterValidationTest.kt @@ -11,21 +11,24 @@ class RegisterValidationTest { @Test fun `valid register test`() { - val violations = registerValidator.validate(User { - username = "hubert" - password = "definitelyNotMyPassword" - }) + val violations = registerValidator.validate( + User { + username = "hubert" + password = "definitelyNotMyPassword" + } + ) violations.isValid `should be equal to` true } - @Test fun `username too long test`() { - val violations = registerValidator.validate(User { - username = "6X9iboWmEOWjVjkO328ReTJ1gGPTTmB/ZGgBLhB6EzAJoWkJht8" - password = "definitelyNotMyPassword" - }) + val violations = registerValidator.validate( + User { + username = "6X9iboWmEOWjVjkO328ReTJ1gGPTTmB/ZGgBLhB6EzAJoWkJht8" + password = "definitelyNotMyPassword" + } + ) violations.isValid `should be equal to` false violations.firstInvalid `should be equal to` "username" diff --git a/api/test/utils/TestContainers.kt b/api/test/utils/KMariadbContainer.kt similarity index 87% rename from api/test/utils/TestContainers.kt rename to api/test/utils/KMariadbContainer.kt index 5ca87ad..0ff742c 100644 --- a/api/test/utils/TestContainers.kt +++ b/api/test/utils/KMariadbContainer.kt @@ -3,10 +3,9 @@ package utils import com.zaxxer.hikari.HikariConfig import com.zaxxer.hikari.HikariDataSource import org.testcontainers.containers.MariaDBContainer -import javax.sql.DataSource class KMariadbContainer : MariaDBContainer() { - fun datasource() : HikariDataSource { + fun datasource(): HikariDataSource { val hikariConfig = HikariConfig().apply { jdbcUrl = this@KMariadbContainer.jdbcUrl username = this@KMariadbContainer.username diff --git a/api/test/utils/KtorTestingExtensions.kt b/api/test/utils/KtorTestingExtensions.kt index 7cad21a..bf578b7 100644 --- a/api/test/utils/KtorTestingExtensions.kt +++ b/api/test/utils/KtorTestingExtensions.kt @@ -5,7 +5,6 @@ import io.ktor.http.HttpMethod import io.ktor.server.testing.* import org.json.JSONObject - fun TestApplicationRequest.json(block: (JSONObject) -> Unit) { addHeader(HttpHeaders.ContentType, "application/json") setBody(JSONObject().apply(block).toString())