Add ktlint config

This commit is contained in:
Hubert Van De Walle 2020-07-03 00:28:11 +02:00
parent fb471f8100
commit 9212d23933
19 changed files with 145 additions and 125 deletions

17
api/.editorconfig Normal file
View File

@ -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

View File

@ -44,7 +44,6 @@ val mainModule = DI.Module("main") {
) )
} }
bind<SimpleJWT>(tag = "auth") with singleton { simpleJwtFactory(instance<Config>().jwt.auth) } bind<SimpleJWT>(tag = "auth") with singleton { simpleJwtFactory(instance<Config>().jwt.auth) }
bind<SimpleJWT>(tag = "refresh") with singleton { simpleJwtFactory(instance<Config>().jwt.refresh) } bind<SimpleJWT>(tag = "refresh") with singleton { simpleJwtFactory(instance<Config>().jwt.refresh) }

View File

@ -12,7 +12,6 @@ import org.kodein.di.instance
import org.slf4j.Logger import org.slf4j.Logger
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
fun main() { fun main() {
val di = DI { import(mainModule) } val di = DI { import(mainModule) }
val config by di.instance<Config>() val config by di.instance<Config>()
@ -41,7 +40,6 @@ fun serve(di: DI) {
} }
} }
fun Application.module(di: DI) { fun Application.module(di: DI) {
val builders: Set<ApplicationBuilder> by di.instance() val builders: Set<ApplicationBuilder> by di.instance()

View File

@ -8,7 +8,6 @@ import io.ktor.response.*
import io.ktor.utils.io.errors.* import io.ktor.utils.io.errors.*
import java.sql.SQLTransientConnectionException import java.sql.SQLTransientConnectionException
class ErrorHandler : ApplicationBuilder({ class ErrorHandler : ApplicationBuilder({
install(StatusPages) { install(StatusPages) {

View File

@ -40,7 +40,6 @@ fun StatusPages.Configuration.jacksonErrors() {
} }
} }
class InvalidFormatError(val value: Any?, targetType: Class<*>) { class InvalidFormatError(val value: Any?, targetType: Class<*>) {
val msg = "Wrong type" val msg = "Wrong type"
val required = targetType.simpleName val required = targetType.simpleName

View File

@ -8,7 +8,6 @@ import kotlinx.coroutines.launch
import org.flywaydb.core.Flyway import org.flywaydb.core.Flyway
import javax.sql.DataSource import javax.sql.DataSource
class MigrationHook(migration: Migration) : ApplicationBuilder({ class MigrationHook(migration: Migration) : ApplicationBuilder({
environment.monitor.subscribe(ApplicationStarted) { environment.monitor.subscribe(ApplicationStarted) {
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {

View File

@ -29,7 +29,6 @@ class NoteRoutes(noteService: NoteService) : RoutingBuilder({
} }
}) })
private fun Route.createNote(noteService: NoteService) { private fun Route.createNote(noteService: NoteService) {
post { post {
val userId = call.authenticatedUserId() val userId = call.authenticatedUserId()
@ -42,7 +41,7 @@ private fun Route.createNote(noteService: NoteService) {
private fun Route.getAllNotes(noteService: NoteService) { private fun Route.getAllNotes(noteService: NoteService) {
get { get {
val userId = call.authenticatedUserId() 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 after = call.parameters["after"]?.let { UUID.fromString(it) } // FIXME validate
val notes = noteService.findAll(userId, limit, after) val notes = noteService.findAll(userId, limit, after)
call.respond(notes) call.respond(notes)

View File

@ -59,7 +59,6 @@ private fun Route.deleteUser(userService: UserService) {
} }
} }
private fun Route.createUser(userService: UserService) { private fun Route.createUser(userService: UserService) {
post { post {
val user = call.receiveValidated(registerValidator) val user = call.receiveValidated(registerValidator)
@ -74,7 +73,6 @@ private fun Route.createUser(userService: UserService) {
} }
} }
private fun Route.login( private fun Route.login(
userService: UserService, userService: UserService,
passwordHash: PasswordHash, passwordHash: PasswordHash,
@ -99,7 +97,6 @@ private fun Route.login(
} }
} }
private fun Route.refreshToken(userService: UserService, authJWT: SimpleJWT, refreshJWT: SimpleJWT) { private fun Route.refreshToken(userService: UserService, authJWT: SimpleJWT, refreshJWT: SimpleJWT) {
post { post {
val token = call.receive<RefreshToken>().refreshToken val token = call.receive<RefreshToken>().refreshToken

View File

@ -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) } db.sequenceOf(Notes, withReferences = false).any { it.userId eq userId and (it.uuid eq uuid) }
} }
suspend fun create(userId: Int, note: Note): Note = launchIo { suspend fun create(userId: Int, note: Note): Note = launchIo {
val uuid = UUID.randomUUID() val uuid = UUID.randomUUID()
val newNote = note.copy().apply { val newNote = note.copy().apply {
@ -79,7 +78,6 @@ class NoteService(private val db: Database) {
} }
} }
} }
} }
newNote newNote
} }
@ -126,7 +124,6 @@ class NoteService(private val db: Database) {
it.noteUuid to note.uuid it.noteUuid to note.uuid
} }
} }
} }
true true
} }

View File

@ -27,7 +27,6 @@ class UserService(private val db: Database, private val passwordHash: PasswordHa
.find { it.id eq id } .find { it.id eq id }
} }
suspend fun exists(username: String) = launchIo { suspend fun exists(username: String) = launchIo {
db.sequenceOf(Users, withReferences = false) db.sequenceOf(Users, withReferences = false)
.any { it.username eq username } .any { it.username eq username }
@ -65,6 +64,4 @@ class UserService(private val db: Database, private val passwordHash: PasswordHa
else -> error("??") else -> error("??")
} }
} }
} }

View File

@ -35,7 +35,6 @@ class AuthControllerKtTest {
private val passwordHash by kodein.instance<PasswordHash>() private val passwordHash by kodein.instance<PasswordHash>()
init { init {
val user = User { val user = User {
@ -63,7 +62,6 @@ class AuthControllerKtTest {
coEvery { userService.find(3) } returns null coEvery { userService.find(3) } returns null
} }
private val testEngine = TestApplicationEngine().apply { private val testEngine = TestApplicationEngine().apply {
start() start()
application.module(kodein) application.module(kodein)
@ -136,7 +134,6 @@ class AuthControllerKtTest {
} }
res.status() `should be equal to` HttpStatusCode.BadRequest res.status() `should be equal to` HttpStatusCode.BadRequest
} }
} }
@Nested @Nested
@ -195,7 +192,6 @@ class AuthControllerKtTest {
res.status() `should be equal to` HttpStatusCode.Unauthorized res.status() `should be equal to` HttpStatusCode.Unauthorized
res.content `should strictly be equal to json` """{msg: "Unauthorized"}""" res.content `should strictly be equal to json` """{msg: "Unauthorized"}"""
} }
} }
@Nested @Nested
@ -224,6 +220,4 @@ class AuthControllerKtTest {
jsonObject.keyList() `should be equal to` listOf("msg") jsonObject.keyList() `should be equal to` listOf("msg")
} }
} }
} }

View File

@ -38,10 +38,8 @@ class UserControllerKtTest {
coEvery { userService.exists(and(not("modified"), not("existing"))) } returns false coEvery { userService.exists(and(not("modified"), not("existing"))) } returns false
coEvery { userService.exists(1) } returns true coEvery { userService.exists(1) } returns true
coEvery { userService.create("modified", any()) } returns null coEvery { userService.create("modified", any()) } returns null
} }
private val kodein = DI { private val kodein = DI {
import(mainModule, allowOverride = true) import(mainModule, allowOverride = true)
bind<UserService>(overrides = true) with instance(userService) bind<UserService>(overrides = true) with instance(userService)
@ -79,7 +77,6 @@ class UserControllerKtTest {
} }
} }
@Nested @Nested
inner class DeleteUser { inner class DeleteUser {
@ -102,5 +99,4 @@ class UserControllerKtTest {
res2.content `should be equal to json` """{msg:"Not Found"}""" res2.content `should be equal to json` """{msg:"Not Found"}"""
} }
} }
} }

View File

@ -47,15 +47,20 @@ class NoteServiceTest {
val user = runBlocking { userService.create("test", "test")!! } val user = runBlocking { userService.create("test", "test")!! }
val noteService by kodein.instance<NoteService>() val noteService by kodein.instance<NoteService>()
val note = runBlocking { val note = runBlocking {
noteService.create(user.id, Note { noteService.create(
user.id,
Note {
this.title = "a note" this.title = "a note"
this.content = """# Title this.content =
"""
|# Title
| |
|😝😝😝😝 |😝😝😝😝
|another line |another line
""".trimMargin() """.trimMargin()
this.tags = listOf("a", "tag") this.tags = listOf("a", "tag")
}) }
)
} }
println(note) println(note)
@ -78,26 +83,38 @@ class NoteServiceTest {
val noteService by kodein.instance<NoteService>() val noteService by kodein.instance<NoteService>()
runBlocking { runBlocking {
noteService.create(user.id, Note { noteService.create(
user.id,
Note {
title = "test" title = "test"
content = "" content = ""
tags = listOf("same") tags = listOf("same")
}) }
noteService.create(user.id, Note { )
noteService.create(
user.id,
Note {
title = "test2" title = "test2"
content = "" content = ""
tags = listOf("same") tags = listOf("same")
}) }
noteService.create(user.id, Note { )
noteService.create(
user.id,
Note {
title = "test3" title = "test3"
content = "" content = ""
tags = listOf("another") tags = listOf("another")
}) }
noteService.create(user2.id, Note { )
noteService.create(
user2.id,
Note {
title = "test" title = "test"
content = "" content = ""
tags = listOf("user2") tags = listOf("user2")
}) }
)
} }
val user1Tags = runBlocking { noteService.getTags(user.id) } val user1Tags = runBlocking { noteService.getTags(user.id) }
user1Tags `should be equal to` listOf("same", "another") user1Tags `should be equal to` listOf("same", "another")
@ -111,27 +128,30 @@ class NoteServiceTest {
val userService by kodein.instance<UserService>() val userService by kodein.instance<UserService>()
val user = runBlocking { userService.create(Faker().name().username(), "test") }!! val user = runBlocking { userService.create(Faker().name().username(), "test") }!!
val note = runBlocking { val note = runBlocking {
noteService.create(user.id, Note { noteService.create(
user.id,
Note {
this.title = "title" this.title = "title"
this.content = "old content" this.content = "old content"
this.tags = emptyList() this.tags = emptyList()
}) }
)
} }
val get = runBlocking { noteService.find(user.id, note.uuid) } val get = runBlocking { noteService.find(user.id, note.uuid) }
runBlocking { runBlocking {
noteService.updateNote(user.id, Note { noteService.updateNote(
user.id,
Note {
uuid = note.uuid uuid = note.uuid
title = "new title" title = "new title"
}) }
)
} }
val updated = runBlocking { noteService.find(user.id, note.uuid) } val updated = runBlocking { noteService.find(user.id, note.uuid) }
println("updated: $updated") println("updated: $updated")
} }
} }
@Nested @Nested
@ -150,58 +170,70 @@ class NoteServiceTest {
val hasTags = note["tags"] != null && note.tags.isNotEmpty() val hasTags = note["tags"] != null && note.tags.isNotEmpty()
return hasTitle || hasContent || hasTags return hasTitle || hasContent || hasTags
} }
} }
val userValidator: Validator<Note> = ValidatorBuilder<Note>() val userValidator: Validator<Note> = ValidatorBuilder<Note>()
.constraintOnTarget(fieldPresentConstraint, "present") .constraintOnTarget(fieldPresentConstraint, "present")
.build() .build()
userValidator.validate(Note { userValidator.validate(
Note {
title = "this is a title" title = "this is a title"
}).isValid `should be equal to` true }
).isValid `should be equal to` true
userValidator.validate(Note { userValidator.validate(
Note {
content = "this is a title" content = "this is a title"
}).isValid `should be equal to` true }
).isValid `should be equal to` true
userValidator.validate(Note { userValidator.validate(
Note {
tags = emptyList() tags = emptyList()
}).isValid `should be equal to` false }
).isValid `should be equal to` false
userValidator.validate(Note { userValidator.validate(
Note {
tags = listOf("tags") tags = listOf("tags")
}).isValid `should be equal to` true }
).isValid `should be equal to` true
userValidator.validate(Note { userValidator.validate(
Note {
tags = listOf("tags") tags = listOf("tags")
title = "This is a title" title = "This is a title"
}).isValid `should be equal to` true }
).isValid `should be equal to` true
userValidator.validate(Note { userValidator.validate(
Note {
tags = listOf("tags") tags = listOf("tags")
title = "This is a title" title = "This is a title"
content = """ content =
# This is """
|# This is
|
|some markdown content
""".trimMargin()
}
).isValid `should be equal to` true
some markdown content userValidator.validate(
""".trimIndent() Note {
}).isValid `should be equal to` true
userValidator.validate(Note {
tags = listOf("tags") tags = listOf("tags")
title = "This is a title" title = "This is a title"
content = """ content =
# This is """
|# This is
some markdown content |
""".trimIndent() |some markdown content
}).isValid `should be equal to` true """.trimMargin()
}
).isValid `should be equal to` true
userValidator.validate(Note()).isValid `should be equal to` false userValidator.validate(Note()).isValid `should be equal to` false
} }
} }
@Nested @Nested
@ -222,6 +254,4 @@ class NoteServiceTest {
println(note.uuid.mostSignificantBits) println(note.uuid.mostSignificantBits)
} }
} }
} }

View File

@ -12,7 +12,6 @@ import org.kodein.di.instance
import org.kodein.di.singleton import org.kodein.di.singleton
import utils.KMariadbContainer import utils.KMariadbContainer
@TestInstance(TestInstance.Lifecycle.PER_CLASS) @TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation::class) @TestMethodOrder(MethodOrderer.OrderAnnotation::class)
class UserServiceTest { class UserServiceTest {
@ -21,7 +20,7 @@ class UserServiceTest {
private val kodein = DI { private val kodein = DI {
import(mainModule, allowOverride = true) import(mainModule, allowOverride = true)
bind( overrides = true) from singleton { mariadb.datasource() } bind(overrides = true) from singleton { mariadb.datasource() }
} }
private val userService by kodein.instance<UserService>() private val userService by kodein.instance<UserService>()
@ -64,5 +63,4 @@ class UserServiceTest {
userService.find(id) `should be` null userService.find(id) `should be` null
} }
} }
} }

View File

@ -11,21 +11,24 @@ class RegisterValidationTest {
@Test @Test
fun `valid register test`() { fun `valid register test`() {
val violations = registerValidator.validate(User { val violations = registerValidator.validate(
User {
username = "hubert" username = "hubert"
password = "definitelyNotMyPassword" password = "definitelyNotMyPassword"
}) }
)
violations.isValid `should be equal to` true violations.isValid `should be equal to` true
} }
@Test @Test
fun `username too long test`() { fun `username too long test`() {
val violations = registerValidator.validate(User { val violations = registerValidator.validate(
User {
username = "6X9iboWmEOWjVjkO328ReTJ1gGPTTmB/ZGgBLhB6EzAJoWkJht8" username = "6X9iboWmEOWjVjkO328ReTJ1gGPTTmB/ZGgBLhB6EzAJoWkJht8"
password = "definitelyNotMyPassword" password = "definitelyNotMyPassword"
}) }
)
violations.isValid `should be equal to` false violations.isValid `should be equal to` false
violations.firstInvalid `should be equal to` "username" violations.firstInvalid `should be equal to` "username"

View File

@ -3,10 +3,9 @@ package utils
import com.zaxxer.hikari.HikariConfig import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource import com.zaxxer.hikari.HikariDataSource
import org.testcontainers.containers.MariaDBContainer import org.testcontainers.containers.MariaDBContainer
import javax.sql.DataSource
class KMariadbContainer : MariaDBContainer<KMariadbContainer>() { class KMariadbContainer : MariaDBContainer<KMariadbContainer>() {
fun datasource() : HikariDataSource { fun datasource(): HikariDataSource {
val hikariConfig = HikariConfig().apply { val hikariConfig = HikariConfig().apply {
jdbcUrl = this@KMariadbContainer.jdbcUrl jdbcUrl = this@KMariadbContainer.jdbcUrl
username = this@KMariadbContainer.username username = this@KMariadbContainer.username

View File

@ -5,7 +5,6 @@ import io.ktor.http.HttpMethod
import io.ktor.server.testing.* import io.ktor.server.testing.*
import org.json.JSONObject import org.json.JSONObject
fun TestApplicationRequest.json(block: (JSONObject) -> Unit) { fun TestApplicationRequest.json(block: (JSONObject) -> Unit) {
addHeader(HttpHeaders.ContentType, "application/json") addHeader(HttpHeaders.ContentType, "application/json")
setBody(JSONObject().apply(block).toString()) setBody(JSONObject().apply(block).toString())