From 1bc45461c301b67a8fccad6516516828e978fa98 Mon Sep 17 00:00:00 2001 From: Hubert Van De Walle Date: Tue, 29 Sep 2020 23:42:03 +0200 Subject: [PATCH] Small refactor --- app/src/main/kotlin/Server.kt | 37 ++-- app/src/main/kotlin/SimpleNotes.kt | 167 +----------------- app/src/main/kotlin/modules/ApiModule.kt | 23 +++ app/src/main/kotlin/modules/ConfigModule.kt | 10 ++ app/src/main/kotlin/modules/CoreModules.kt | 31 ++++ app/src/main/kotlin/modules/JsonModule.kt | 24 +++ app/src/main/kotlin/modules/ServerModule.kt | 57 ++++++ .../serialization/LocaleDateTimeSerializer.kt | 22 +++ .../kotlin/serialization/UuidSerializer.kt | 22 +++ .../main/kotlin/utils/StaticFilesResolver.kt | 7 +- deploy-docker-hub.sh | 2 +- domain/src/main/kotlin/DomainModule.kt | 9 +- .../src/main/kotlin/usecases/NoteService.kt | 1 - .../usecases/export/ExportUseCaseImpl.kt | 33 +--- .../src/main/kotlin/PersistanceModule.kt | 5 +- 15 files changed, 226 insertions(+), 224 deletions(-) create mode 100644 app/src/main/kotlin/modules/ApiModule.kt create mode 100644 app/src/main/kotlin/modules/ConfigModule.kt create mode 100644 app/src/main/kotlin/modules/CoreModules.kt create mode 100644 app/src/main/kotlin/modules/JsonModule.kt create mode 100644 app/src/main/kotlin/modules/ServerModule.kt create mode 100644 app/src/main/kotlin/serialization/LocaleDateTimeSerializer.kt create mode 100644 app/src/main/kotlin/serialization/UuidSerializer.kt diff --git a/app/src/main/kotlin/Server.kt b/app/src/main/kotlin/Server.kt index 39f9530..817db49 100644 --- a/app/src/main/kotlin/Server.kt +++ b/app/src/main/kotlin/Server.kt @@ -1,32 +1,23 @@ package be.simplenotes.app -import org.eclipse.jetty.server.Server -import org.eclipse.jetty.server.ServerConnector -import org.http4k.routing.RoutingHttpHandler -import org.http4k.server.ConnectorBuilder -import org.http4k.server.Jetty -import org.http4k.server.ServerConfig -import org.http4k.server.asServer +import org.http4k.server.Http4kServer import org.slf4j.LoggerFactory -import be.simplenotes.shared.config.ServerConfig as SimpleNotesServeConfig +import be.simplenotes.shared.config.ServerConfig as SimpleNotesServerConfig class Server( - private val config: SimpleNotesServeConfig, - private val serverConfig: ServerConfig, - private val router: RoutingHttpHandler, + private val config: SimpleNotesServerConfig, + private val http4kServer: Http4kServer, ) { - fun start() { - router.asServer(serverConfig).start() - LoggerFactory.getLogger(javaClass).info("Listening on http://${config.host}:${config.port}") - } -} + private val logger = LoggerFactory.getLogger(javaClass) -fun serverConfig(config: SimpleNotesServeConfig): ServerConfig { - val builder: ConnectorBuilder = { server: Server -> - ServerConnector(server).apply { - port = config.port - host = config.host - } + fun start(): Server { + http4kServer.start() + logger.info("Listening on http://${config.host}:${config.port}") + return this + } + + fun stop() { + logger.info("Stopping server") + http4kServer.close() } - return Jetty(config.port, builder) } diff --git a/app/src/main/kotlin/SimpleNotes.kt b/app/src/main/kotlin/SimpleNotes.kt index c68bc02..307ba5e 100644 --- a/app/src/main/kotlin/SimpleNotes.kt +++ b/app/src/main/kotlin/SimpleNotes.kt @@ -1,180 +1,25 @@ package be.simplenotes.app -import be.simplenotes.app.api.ApiNoteController -import be.simplenotes.app.api.ApiUserController -import be.simplenotes.app.controllers.BaseController -import be.simplenotes.app.controllers.NoteController -import be.simplenotes.app.controllers.SettingsController -import be.simplenotes.app.controllers.UserController -import be.simplenotes.app.filters.AuthFilter -import be.simplenotes.app.filters.AuthType -import be.simplenotes.app.filters.ErrorFilter -import be.simplenotes.app.filters.JwtSource -import be.simplenotes.app.routes.Router -import be.simplenotes.app.utils.StaticFileResolver -import be.simplenotes.app.utils.StaticFileResolverImpl -import be.simplenotes.app.views.* +import be.simplenotes.app.modules.* import be.simplenotes.domain.domainModule -import be.simplenotes.domain.usecases.NoteService -import be.simplenotes.persistance.DbMigrations import be.simplenotes.persistance.persistanceModule import be.simplenotes.search.searchModule -import be.simplenotes.shared.config.DataSourceConfig -import be.simplenotes.shared.config.JwtConfig -import kotlinx.serialization.KSerializer -import kotlinx.serialization.descriptors.PrimitiveKind -import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor -import kotlinx.serialization.descriptors.SerialDescriptor -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder -import kotlinx.serialization.json.Json -import kotlinx.serialization.modules.SerializersModule -import org.http4k.core.RequestContexts import org.koin.core.context.startKoin -import org.koin.core.qualifier.named -import org.koin.core.qualifier.qualifier -import org.koin.dsl.module -import org.slf4j.LoggerFactory -import java.time.LocalDateTime -import java.util.* -import be.simplenotes.shared.config.ServerConfig as SimpleNotesServeConfig fun main() { - val koin = startKoin { + startKoin { modules( + serverModule, persistanceModule, configModule, - domainModule, - serverModule, - userModule, baseModule, + userModule, noteModule, settingsModule, + domainModule, searchModule, apiModule, + jsonModule ) - }.koin - - val dataSourceConfig = koin.get() - val jwtConfig = koin.get() - val serverConfig = koin.get() - val logger = LoggerFactory.getLogger("SimpleNotes") - logger.info("datasource: $dataSourceConfig") - logger.info("jwt: $jwtConfig") - logger.info("server: $serverConfig") - - val migrations = koin.get() - migrations.migrate() - - val noteService = koin.get() - noteService.dropAllIndexes() - noteService.indexAll() - - koin.get().start() -} - -val serverModule = module { - single { Server(get(), get(), get()) } - single { StaticFileResolverImpl() } - single { - Router( - get(), - get(), - get(), - get(), - get(), - get(), - requiredAuth = get(AuthType.Required.qualifier), - optionalAuth = get(AuthType.Optional.qualifier), - errorFilter = get(named("ErrorFilter")), - apiAuth = get(named("apiAuthFilter")), - get() - )() - } - single { serverConfig(get()) } - single { RequestContexts() } - single(AuthType.Optional.qualifier) { AuthFilter(get(), AuthType.Optional, get())() } - single(AuthType.Required.qualifier) { AuthFilter(get(), AuthType.Required, get())() } - single(named("ErrorFilter")) { ErrorFilter(get())() } - single { ErrorView(get()) } -} - -val userModule = module { - single { UserController(get(), get(), get()) } - single { UserView(get()) } -} - -val baseModule = module { - single { BaseController(get()) } - single { BaseView(get()) } -} - -val noteModule = module { - single { NoteController(get(), get()) } - single { NoteView(get()) } -} - -val settingsModule = module { - single { SettingsController(get(), get()) } - single { SettingView(get()) } -} - -val configModule = module { - single { Config.dataSourceConfig } - single { Config.jwtConfig } - single { Config.serverConfig } -} - -val apiModule = module { - single { ApiUserController(get(), get()) } - single { ApiNoteController(get(), get()) } - single { - Json { - prettyPrint = true - serializersModule = get() - } - } - single { - SerializersModule { - contextual(LocalDateTime::class, LocalDateTimeSerializer) - contextual(UUID::class, UuidSerializer) - } - } - single(named("apiAuthFilter")) { - AuthFilter( - extractor = get(), - authType = AuthType.Required, - ctx = get(), - source = JwtSource.Header, - redirect = false - )() } } - - -internal object LocalDateTimeSerializer : KSerializer { - override val descriptor: SerialDescriptor - get() = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING) - - override fun serialize(encoder: Encoder, value: LocalDateTime) { - encoder.encodeString(value.toString()) - } - - override fun deserialize(decoder: Decoder): LocalDateTime { - TODO("Not implemented, isn't needed") - } -} - -internal object UuidSerializer : KSerializer { - override val descriptor: SerialDescriptor - get() = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING) - - override fun serialize(encoder: Encoder, value: UUID) { - encoder.encodeString(value.toString()) - } - - override fun deserialize(decoder: Decoder): UUID { - TODO() - } -} - diff --git a/app/src/main/kotlin/modules/ApiModule.kt b/app/src/main/kotlin/modules/ApiModule.kt new file mode 100644 index 0000000..031d30d --- /dev/null +++ b/app/src/main/kotlin/modules/ApiModule.kt @@ -0,0 +1,23 @@ +package be.simplenotes.app.modules + +import be.simplenotes.app.api.ApiNoteController +import be.simplenotes.app.api.ApiUserController +import be.simplenotes.app.filters.AuthFilter +import be.simplenotes.app.filters.AuthType +import be.simplenotes.app.filters.JwtSource +import org.koin.core.qualifier.named +import org.koin.dsl.module + +val apiModule = module { + single { ApiUserController(get(), get()) } + single { ApiNoteController(get(), get()) } + single(named("apiAuthFilter")) { + AuthFilter( + extractor = get(), + authType = AuthType.Required, + ctx = get(), + source = JwtSource.Header, + redirect = false + )() + } +} diff --git a/app/src/main/kotlin/modules/ConfigModule.kt b/app/src/main/kotlin/modules/ConfigModule.kt new file mode 100644 index 0000000..65043d5 --- /dev/null +++ b/app/src/main/kotlin/modules/ConfigModule.kt @@ -0,0 +1,10 @@ +package be.simplenotes.app.modules + +import be.simplenotes.app.Config +import org.koin.dsl.module + +val configModule = module { + single { Config.dataSourceConfig } + single { Config.jwtConfig } + single { Config.serverConfig } +} diff --git a/app/src/main/kotlin/modules/CoreModules.kt b/app/src/main/kotlin/modules/CoreModules.kt new file mode 100644 index 0000000..10040b6 --- /dev/null +++ b/app/src/main/kotlin/modules/CoreModules.kt @@ -0,0 +1,31 @@ +package be.simplenotes.app.modules + +import be.simplenotes.app.controllers.BaseController +import be.simplenotes.app.controllers.NoteController +import be.simplenotes.app.controllers.SettingsController +import be.simplenotes.app.controllers.UserController +import be.simplenotes.app.views.BaseView +import be.simplenotes.app.views.NoteView +import be.simplenotes.app.views.SettingView +import be.simplenotes.app.views.UserView +import org.koin.dsl.module + +val userModule = module { + single { UserController(get(), get(), get()) } + single { UserView(get()) } +} + +val baseModule = module { + single { BaseController(get()) } + single { BaseView(get()) } +} + +val noteModule = module { + single { NoteController(get(), get()) } + single { NoteView(get()) } +} + +val settingsModule = module { + single { SettingsController(get(), get()) } + single { SettingView(get()) } +} diff --git a/app/src/main/kotlin/modules/JsonModule.kt b/app/src/main/kotlin/modules/JsonModule.kt new file mode 100644 index 0000000..e349a14 --- /dev/null +++ b/app/src/main/kotlin/modules/JsonModule.kt @@ -0,0 +1,24 @@ +package be.simplenotes.app.modules + +import be.simplenotes.app.serialization.LocalDateTimeSerializer +import be.simplenotes.app.serialization.UuidSerializer +import kotlinx.serialization.json.Json +import kotlinx.serialization.modules.SerializersModule +import org.koin.dsl.module +import java.time.LocalDateTime +import java.util.* + +val jsonModule = module { + single { + Json { + prettyPrint = true + serializersModule = get() + } + } + single { + SerializersModule { + contextual(LocalDateTime::class, LocalDateTimeSerializer()) + contextual(UUID::class, UuidSerializer()) + } + } +} diff --git a/app/src/main/kotlin/modules/ServerModule.kt b/app/src/main/kotlin/modules/ServerModule.kt new file mode 100644 index 0000000..8d8c83b --- /dev/null +++ b/app/src/main/kotlin/modules/ServerModule.kt @@ -0,0 +1,57 @@ +package be.simplenotes.app.modules + +import be.simplenotes.app.Server +import be.simplenotes.app.filters.AuthFilter +import be.simplenotes.app.filters.AuthType +import be.simplenotes.app.filters.ErrorFilter +import be.simplenotes.app.routes.Router +import be.simplenotes.app.utils.StaticFileResolver +import be.simplenotes.app.utils.StaticFileResolverImpl +import be.simplenotes.app.views.ErrorView +import be.simplenotes.shared.config.ServerConfig +import org.eclipse.jetty.server.ServerConnector +import org.http4k.core.RequestContexts +import org.http4k.routing.RoutingHttpHandler +import org.http4k.server.ConnectorBuilder +import org.http4k.server.Jetty +import org.http4k.server.asServer +import org.koin.core.qualifier.named +import org.koin.core.qualifier.qualifier +import org.koin.dsl.module +import org.http4k.server.ServerConfig as Http4kServerConfig + +val serverModule = module { + single(createdAtStart = true) { Server(get(), get()).start() } + single { get().asServer(get()) } + single { + val config = get() + val builder: ConnectorBuilder = { server: org.eclipse.jetty.server.Server -> + ServerConnector(server).apply { + port = config.port + host = config.host + } + } + Jetty(config.port, builder) + } + single { StaticFileResolverImpl(get()) } + single { + Router( + get(), + get(), + get(), + get(), + get(), + get(), + requiredAuth = get(AuthType.Required.qualifier), + optionalAuth = get(AuthType.Optional.qualifier), + errorFilter = get(named("ErrorFilter")), + apiAuth = get(named("apiAuthFilter")), + get() + )() + } + single { RequestContexts() } + single(AuthType.Optional.qualifier) { AuthFilter(get(), AuthType.Optional, get())() } + single(AuthType.Required.qualifier) { AuthFilter(get(), AuthType.Required, get())() } + single(named("ErrorFilter")) { ErrorFilter(get())() } + single { ErrorView(get()) } +} diff --git a/app/src/main/kotlin/serialization/LocaleDateTimeSerializer.kt b/app/src/main/kotlin/serialization/LocaleDateTimeSerializer.kt new file mode 100644 index 0000000..55827af --- /dev/null +++ b/app/src/main/kotlin/serialization/LocaleDateTimeSerializer.kt @@ -0,0 +1,22 @@ +package be.simplenotes.app.serialization + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import java.time.LocalDateTime + +internal class LocalDateTimeSerializer : KSerializer { + override val descriptor: SerialDescriptor + get() = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: LocalDateTime) { + encoder.encodeString(value.toString()) + } + + override fun deserialize(decoder: Decoder): LocalDateTime { + TODO("Not implemented, isn't needed") + } +} diff --git a/app/src/main/kotlin/serialization/UuidSerializer.kt b/app/src/main/kotlin/serialization/UuidSerializer.kt new file mode 100644 index 0000000..a0012e3 --- /dev/null +++ b/app/src/main/kotlin/serialization/UuidSerializer.kt @@ -0,0 +1,22 @@ +package be.simplenotes.app.serialization + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import java.util.* + +internal class UuidSerializer : KSerializer { + override val descriptor: SerialDescriptor + get() = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: UUID) { + encoder.encodeString(value.toString()) + } + + override fun deserialize(decoder: Decoder): UUID { + TODO() + } +} diff --git a/app/src/main/kotlin/utils/StaticFilesResolver.kt b/app/src/main/kotlin/utils/StaticFilesResolver.kt index 12db12d..4e0dee5 100644 --- a/app/src/main/kotlin/utils/StaticFilesResolver.kt +++ b/app/src/main/kotlin/utils/StaticFilesResolver.kt @@ -1,16 +1,17 @@ package be.simplenotes.app.utils -import kotlinx.serialization.json.* +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive interface StaticFileResolver { fun resolve(name: String): String? } -class StaticFileResolverImpl : StaticFileResolver { +class StaticFileResolverImpl(json: Json) : StaticFileResolver { private val mappings: Map init { - val json = Json {} val manifest = javaClass.getResource("/css-manifest.json").readText() val manifestObject = json.parseToJsonElement(manifest).jsonObject val keys = manifestObject.keys diff --git a/deploy-docker-hub.sh b/deploy-docker-hub.sh index 1778647..a08daf0 100755 --- a/deploy-docker-hub.sh +++ b/deploy-docker-hub.sh @@ -5,4 +5,4 @@ rm app/src/main/resources/static/styles* yarn --cwd css run css-purge \ && docker build -t hubv/simplenotes:latest . \ - && docker push hubv/simplenotes:latest + # && docker push hubv/simplenotes:latest diff --git a/domain/src/main/kotlin/DomainModule.kt b/domain/src/main/kotlin/DomainModule.kt index 15af5a2..eedf3aa 100644 --- a/domain/src/main/kotlin/DomainModule.kt +++ b/domain/src/main/kotlin/DomainModule.kt @@ -26,7 +26,12 @@ val domainModule = module { single { BcryptPasswordHash() } single { SimpleJwt(get()) } single { JwtPayloadExtractor(get()) } - single { NoteService(get(), get(), get(), get()) } + single { + NoteService(get(), get(), get(), get()).apply { + dropAllIndexes() + indexAll() + } + } single { MarkdownConverterImpl() } - single { ExportUseCaseImpl(get()) } + single { ExportUseCaseImpl(get(), get()) } } diff --git a/domain/src/main/kotlin/usecases/NoteService.kt b/domain/src/main/kotlin/usecases/NoteService.kt index 830343c..7efe8ef 100644 --- a/domain/src/main/kotlin/usecases/NoteService.kt +++ b/domain/src/main/kotlin/usecases/NoteService.kt @@ -12,7 +12,6 @@ import be.simplenotes.domain.usecases.repositories.NoteRepository import be.simplenotes.domain.usecases.repositories.UserRepository import be.simplenotes.domain.usecases.search.NoteSearcher import be.simplenotes.domain.usecases.search.SearchTerms -import kotlinx.serialization.Serializable import java.util.* class NoteService( diff --git a/domain/src/main/kotlin/usecases/export/ExportUseCaseImpl.kt b/domain/src/main/kotlin/usecases/export/ExportUseCaseImpl.kt index 0e15e1a..05991af 100644 --- a/domain/src/main/kotlin/usecases/export/ExportUseCaseImpl.kt +++ b/domain/src/main/kotlin/usecases/export/ExportUseCaseImpl.kt @@ -2,33 +2,16 @@ package be.simplenotes.domain.usecases.export import be.simplenotes.domain.model.ExportedNote import be.simplenotes.domain.usecases.repositories.NoteRepository -import kotlinx.serialization.KSerializer import kotlinx.serialization.builtins.ListSerializer -import kotlinx.serialization.descriptors.PrimitiveKind -import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor -import kotlinx.serialization.descriptors.SerialDescriptor -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.json.Json -import kotlinx.serialization.modules.SerializersModule import org.apache.commons.compress.archivers.zip.ZipArchiveEntry import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.InputStream -import java.time.LocalDateTime -internal class ExportUseCaseImpl(private val noteRepository: NoteRepository) : ExportUseCase { +internal class ExportUseCaseImpl(private val noteRepository: NoteRepository, private val json: Json) : ExportUseCase { override fun exportAsJson(userId: Int): String { - val module = SerializersModule { - contextual(LocalDateTime::class, LocalDateTimeSerializer) - } - - val json = Json { - prettyPrint = true - serializersModule = module - } - val notes = noteRepository.export(userId) return json.encodeToString(ListSerializer(ExportedNote.serializer()), notes) } @@ -65,17 +48,3 @@ class ZipOutput : AutoCloseable { zipOutputStream.close() } } - - -internal object LocalDateTimeSerializer : KSerializer { - override val descriptor: SerialDescriptor - get() = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING) - - override fun serialize(encoder: Encoder, value: LocalDateTime) { - encoder.encodeString(value.toString()) - } - - override fun deserialize(decoder: Decoder): LocalDateTime { - TODO("Not implemented, isn't needed") - } -} diff --git a/persistance/src/main/kotlin/PersistanceModule.kt b/persistance/src/main/kotlin/PersistanceModule.kt index a0edf85..8ebb455 100644 --- a/persistance/src/main/kotlin/PersistanceModule.kt +++ b/persistance/src/main/kotlin/PersistanceModule.kt @@ -32,5 +32,8 @@ val persistanceModule = module { single { NoteRepositoryImpl(get()) } single { DbMigrationsImpl(get(), get()) } single { hikariDataSource(get()) } - single { Database.connect(get()) } + single { + get().migrate() + Database.connect(get()) + } }