Skip to content

Commit

Permalink
Add koin (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
dragneelfps authored Jun 17, 2021
1 parent 10c7f41 commit c6cb866
Show file tree
Hide file tree
Showing 15 changed files with 177 additions and 70 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ For more information on how to this works with other frontends/backends, head ov
- [hikari](https://github.com/brettwooldridge/HikariCP) as JDBC connection pool
- [Exposed](https://github.com/JetBrains/Exposed/) as Kotlin SQL Framework
- [Jackson](https://github.com/FasterXML/jackson) for handling JSON
- [Koin](https://insert-koin.io/) for dependency injection

# Getting started

Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ dependencies {
implementation(Deps.exposedJdbc)
implementation(Deps.exposedJavaTime)
implementation(Deps.hikari)
implementation(Deps.koin)

testImplementation(Deps.ktorTests)
}
2 changes: 2 additions & 0 deletions buildSrc/src/main/kotlin/Deps.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const val logbackVersion = "1.2.3"
const val h2Version = "1.4.200"
const val exposedVersion = "0.32.1"
const val hikariVersion = "4.0.3"
const val koinVersion = "3.1.0"

object Deps {
const val kotlinLib = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
Expand All @@ -21,4 +22,5 @@ object Deps {
const val exposedJdbc = "org.jetbrains.exposed:exposed-jdbc:$exposedVersion"
const val exposedJavaTime = "org.jetbrains.exposed:exposed-java-time:$exposedVersion"
const val hikari = "com.zaxxer:HikariCP:$hikariVersion"
const val koin = "io.insert-koin:koin-ktor:$koinVersion"
}
18 changes: 15 additions & 3 deletions src/Application.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
package com.nooblabs

import com.fasterxml.jackson.databind.SerializationFeature
import com.nooblabs.service.DatabaseFactory
import com.nooblabs.service.IDatabaseFactory
import config.api
import config.cors
import config.jwt
import config.statusPages
import io.ktor.application.Application
import io.ktor.application.install
import io.ktor.auth.Authentication
import io.ktor.features.*
import io.ktor.features.CORS
import io.ktor.features.CallLogging
import io.ktor.features.ContentNegotiation
import io.ktor.features.DefaultHeaders
import io.ktor.features.StatusPages
import io.ktor.jackson.jackson
import io.ktor.routing.routing
import org.koin.ktor.ext.Koin
import org.koin.ktor.ext.inject
import org.slf4j.event.Level

fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)
Expand All @@ -37,7 +43,13 @@ fun Application.module() {
}
}

DatabaseFactory.init()
install(Koin) {
modules(serviceKoinModule)
modules(databaseKoinModule)
}

val factory: IDatabaseFactory by inject()
factory.init()

routing {
install(StatusPages) {
Expand Down
10 changes: 7 additions & 3 deletions src/api/ArticleResource.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.nooblabs.api
import com.nooblabs.models.MultipleArticlesResponse
import com.nooblabs.models.NewArticle
import com.nooblabs.models.UpdateArticle
import com.nooblabs.service.ArticleService
import com.nooblabs.service.IArticleService
import com.nooblabs.util.param
import com.nooblabs.util.userId
import io.ktor.application.call
Expand All @@ -13,9 +13,13 @@ import io.ktor.auth.principal
import io.ktor.http.HttpStatusCode
import io.ktor.request.receive
import io.ktor.response.respond
import io.ktor.routing.*
import io.ktor.routing.Route
import io.ktor.routing.delete
import io.ktor.routing.get
import io.ktor.routing.post
import io.ktor.routing.put

fun Route.article(articleService: ArticleService) {
fun Route.article(articleService: IArticleService) {

authenticate {

Expand Down
4 changes: 2 additions & 2 deletions src/api/AuthResource.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.nooblabs.models.LoginUser
import com.nooblabs.models.RegisterUser
import com.nooblabs.models.UpdateUser
import com.nooblabs.models.UserResponse
import com.nooblabs.service.AuthService
import com.nooblabs.service.IAuthService
import com.nooblabs.util.SimpleJWT
import com.nooblabs.util.userId
import io.ktor.application.call
Expand All @@ -16,7 +16,7 @@ import io.ktor.routing.get
import io.ktor.routing.post
import io.ktor.routing.put

fun Route.auth(authService: AuthService, simpleJWT: SimpleJWT) {
fun Route.auth(authService: IAuthService, simpleJWT: SimpleJWT) {

/*
Registration:
Expand Down
4 changes: 2 additions & 2 deletions src/api/CommentResource.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.nooblabs.api

import com.nooblabs.models.PostComment
import com.nooblabs.service.CommentService
import com.nooblabs.service.ICommentService
import com.nooblabs.util.param
import com.nooblabs.util.userId
import io.ktor.application.call
Expand All @@ -16,7 +16,7 @@ import io.ktor.routing.delete
import io.ktor.routing.get
import io.ktor.routing.post

fun Route.comment(commentService: CommentService) {
fun Route.comment(commentService: ICommentService) {

authenticate {

Expand Down
4 changes: 2 additions & 2 deletions src/api/ProfileResource.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.nooblabs.api

import com.nooblabs.service.ProfileService
import com.nooblabs.service.IProfileService
import com.nooblabs.util.param
import com.nooblabs.util.userId
import io.ktor.application.call
Expand All @@ -13,7 +13,7 @@ import io.ktor.routing.delete
import io.ktor.routing.get
import io.ktor.routing.post

fun Route.profile(profileService: ProfileService) {
fun Route.profile(profileService: IProfileService) {

authenticate(optional = true) {

Expand Down
18 changes: 12 additions & 6 deletions src/config/Api.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,25 @@ import com.nooblabs.api.article
import com.nooblabs.api.auth
import com.nooblabs.api.comment
import com.nooblabs.api.profile
import com.nooblabs.service.*
import com.nooblabs.service.IArticleService
import com.nooblabs.service.IAuthService
import com.nooblabs.service.ICommentService
import com.nooblabs.service.IDatabaseFactory
import com.nooblabs.service.IProfileService
import io.ktor.application.call
import io.ktor.response.respond
import io.ktor.routing.Route
import io.ktor.routing.get
import io.ktor.routing.route
import org.koin.ktor.ext.inject

fun Route.api() {

val authService = AuthService()
val profileService = ProfileService()
val articleService = ArticleService()
val commentService = CommentService()
val authService: IAuthService by inject()
val profileService: IProfileService by inject()
val articleService: IArticleService by inject()
val commentService: ICommentService by inject()
val databaseFactory: IDatabaseFactory by inject()

route("/api") {

Expand All @@ -30,7 +36,7 @@ fun Route.api() {
comment(commentService)

get("/drop") {
DatabaseFactory.drop()
databaseFactory.drop()
call.respond("OK")
}
}
Expand Down
24 changes: 24 additions & 0 deletions src/koin.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.nooblabs

import com.nooblabs.service.ArticleService
import com.nooblabs.service.AuthService
import com.nooblabs.service.CommentService
import com.nooblabs.service.DatabaseFactory
import com.nooblabs.service.IArticleService
import com.nooblabs.service.IAuthService
import com.nooblabs.service.ICommentService
import com.nooblabs.service.IDatabaseFactory
import com.nooblabs.service.IProfileService
import com.nooblabs.service.ProfileService
import org.koin.dsl.module

val serviceKoinModule = module {
single<IArticleService> { ArticleService(get()) }
single<IAuthService> { AuthService(get()) }
single<ICommentService> { CommentService(get()) }
single<IProfileService> { ProfileService(get()) }
}

val databaseKoinModule = module {
single<IDatabaseFactory> { DatabaseFactory() }
}
53 changes: 35 additions & 18 deletions src/service/ArticleService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,35 @@ import com.nooblabs.models.TagResponse
import com.nooblabs.models.Tags
import com.nooblabs.models.UpdateArticle
import com.nooblabs.models.User
import com.nooblabs.service.DatabaseFactory.dbQuery
import com.nooblabs.util.ArticleDoesNotExist
import com.nooblabs.util.AuthorizationException
import org.jetbrains.exposed.sql.Op
import org.jetbrains.exposed.sql.SizedCollection
import org.jetbrains.exposed.sql.SortOrder
import java.time.Instant

class ArticleService {
interface IArticleService {
suspend fun createArticle(userId: String, newArticle: NewArticle): ArticleResponse

suspend fun createArticle(userId: String, newArticle: NewArticle): ArticleResponse {
return dbQuery {
suspend fun updateArticle(userId: String, slug: String, updateArticle: UpdateArticle): ArticleResponse

suspend fun getArticle(slug: String): ArticleResponse

suspend fun getArticles(userId: String? = null, filter: Map<String, String?>): List<ArticleResponse.Article>

suspend fun getFeedArticles(userId: String, filter: Map<String, String?>): List<ArticleResponse.Article>

suspend fun changeFavorite(userId: String, slug: String, favorite: Boolean): ArticleResponse

suspend fun deleteArticle(userId: String, slug: String)

suspend fun getAllTags(): TagResponse
}

class ArticleService(private val databaseFactory: IDatabaseFactory) : IArticleService {

override suspend fun createArticle(userId: String, newArticle: NewArticle): ArticleResponse {
return databaseFactory.dbQuery {
val user = getUser(userId)
val article = Article.new {
title = newArticle.article.title
Expand All @@ -35,8 +52,8 @@ class ArticleService {
}
}

suspend fun updateArticle(userId: String, slug: String, updateArticle: UpdateArticle): ArticleResponse {
return dbQuery {
override suspend fun updateArticle(userId: String, slug: String, updateArticle: UpdateArticle): ArticleResponse {
return databaseFactory.dbQuery {
val user = getUser(userId)
val article = getArticleBySlug(slug)
if (!isArticleAuthor(article, user)) throw AuthorizationException()
Expand All @@ -49,15 +66,15 @@ class ArticleService {
}
}

suspend fun getArticle(slug: String): ArticleResponse {
return dbQuery {
override suspend fun getArticle(slug: String): ArticleResponse {
return databaseFactory.dbQuery {
val article = getArticleBySlug(slug)
getArticleResponse(article)
}
}

suspend fun getArticles(userId: String? = null, filter: Map<String, String?>): List<ArticleResponse.Article> {
return dbQuery {
override suspend fun getArticles(userId: String?, filter: Map<String, String?>): List<ArticleResponse.Article> {
return databaseFactory.dbQuery {
val user = if (userId != null) getUser(userId) else null
getAllArticles(
currentUser = user,
Expand All @@ -70,8 +87,8 @@ class ArticleService {
}
}

suspend fun getFeedArticles(userId: String, filter: Map<String, String?>): List<ArticleResponse.Article> {
return dbQuery {
override suspend fun getFeedArticles(userId: String, filter: Map<String, String?>): List<ArticleResponse.Article> {
return databaseFactory.dbQuery {
val user = getUser(userId)
getAllArticles(
currentUser = user,
Expand All @@ -82,8 +99,8 @@ class ArticleService {
}
}

suspend fun changeFavorite(userId: String, slug: String, favorite: Boolean): ArticleResponse {
return dbQuery {
override suspend fun changeFavorite(userId: String, slug: String, favorite: Boolean): ArticleResponse {
return databaseFactory.dbQuery {
val user = getUser(userId)
val article = getArticleBySlug(slug)
if (favorite) {
Expand All @@ -95,17 +112,17 @@ class ArticleService {
}
}

suspend fun deleteArticle(userId: String, slug: String) {
dbQuery {
override suspend fun deleteArticle(userId: String, slug: String) {
databaseFactory.dbQuery {
val user = getUser(userId)
val article = getArticleBySlug(slug)
if (!isArticleAuthor(article, user)) throw AuthorizationException()
article.delete()
}
}

suspend fun getAllTags(): TagResponse {
return dbQuery {
override suspend fun getAllTags(): TagResponse {
return databaseFactory.dbQuery {
val tags = Tag.all().map { it.tag }
TagResponse(tags)
}
Expand Down
Loading

0 comments on commit c6cb866

Please sign in to comment.