From aa95de7a6add5f098d7b0155a7fda42c0300ab95 Mon Sep 17 00:00:00 2001 From: Fabrice Lecomte Date: Sat, 23 Jan 2021 23:26:01 +0100 Subject: [PATCH] move some part of KoinModule in components --- src/main/kotlin/application/Application.kt | 29 ++++++- src/main/kotlin/application/KoinModule.kt | 71 ---------------- .../kotlin/component/article/KoinModule.kt | 8 ++ src/main/kotlin/component/auth/KoinModule.kt | 11 +++ .../kotlin/component/citizen/KoinModule.kt | 8 ++ .../kotlin/component/comment/KoinModule.kt | 14 +++ .../component/constitution/KoinModule.kt | 8 ++ .../kotlin/component/follow/KoinModule.kt | 9 ++ .../kotlin/component/opinion/KoinModule.kt | 11 +++ .../kotlin/component/views/ConfigViews.kt | 85 ------------------- src/main/kotlin/component/views/KoinModule.kt | 19 +++++ .../component/views/createEsIndexForViews.kt | 58 +++++++++++++ src/main/kotlin/component/vote/KoinModule.kt | 12 +++ .../kotlin/component/workgroup/KoinModule.kt | 8 ++ src/main/kotlin/utils/waitElastic.kt | 28 ++++++ 15 files changed, 219 insertions(+), 160 deletions(-) create mode 100644 src/main/kotlin/component/article/KoinModule.kt create mode 100644 src/main/kotlin/component/auth/KoinModule.kt create mode 100644 src/main/kotlin/component/citizen/KoinModule.kt create mode 100644 src/main/kotlin/component/comment/KoinModule.kt create mode 100644 src/main/kotlin/component/constitution/KoinModule.kt create mode 100644 src/main/kotlin/component/follow/KoinModule.kt create mode 100644 src/main/kotlin/component/opinion/KoinModule.kt delete mode 100644 src/main/kotlin/component/views/ConfigViews.kt create mode 100644 src/main/kotlin/component/views/KoinModule.kt create mode 100644 src/main/kotlin/component/views/createEsIndexForViews.kt create mode 100644 src/main/kotlin/component/vote/KoinModule.kt create mode 100644 src/main/kotlin/component/workgroup/KoinModule.kt create mode 100644 src/main/kotlin/utils/waitElastic.kt diff --git a/src/main/kotlin/application/Application.kt b/src/main/kotlin/application/Application.kt index dbf822f..f7e3eef 100644 --- a/src/main/kotlin/application/Application.kt +++ b/src/main/kotlin/application/Application.kt @@ -8,22 +8,31 @@ import com.fasterxml.jackson.databind.SerializationFeature import com.fasterxml.jackson.datatype.joda.JodaModule import com.github.jasync.sql.db.postgresql.exceptions.GenericDatabaseException import fr.dcproject.application.Env.PROD +import fr.dcproject.component.article.articleKoinModule import fr.dcproject.component.article.routes.installArticleRoutes import fr.dcproject.component.auth.ForbiddenException +import fr.dcproject.component.auth.authKoinModule import fr.dcproject.component.auth.jwt.jwtInstallation import fr.dcproject.component.auth.routes.installAuthRoutes import fr.dcproject.component.auth.user +import fr.dcproject.component.citizen.citizenKoinModule import fr.dcproject.component.citizen.routes.installCitizenRoutes import fr.dcproject.component.comment.article.routes.installCommentArticleRoutes +import fr.dcproject.component.comment.commentKoinModule import fr.dcproject.component.comment.constitution.routes.installCommentConstitutionRoutes import fr.dcproject.component.comment.generic.routes.installCommentRoutes +import fr.dcproject.component.constitution.constitutionKoinModule import fr.dcproject.component.constitution.routes.installConstitutionRoutes +import fr.dcproject.component.follow.followKoinModule import fr.dcproject.component.follow.routes.article.installFollowArticleRoutes import fr.dcproject.component.follow.routes.constitution.installFollowConstitutionRoutes +import fr.dcproject.component.opinion.opinionKoinModule import fr.dcproject.component.opinion.routes.installOpinionRoutes -import fr.dcproject.component.views.ConfigViews +import fr.dcproject.component.views.viewKoinModule import fr.dcproject.component.vote.routes.installVoteRoutes +import fr.dcproject.component.vote.voteKoinModule import fr.dcproject.component.workgroup.routes.installWorkgroupRoutes +import fr.dcproject.component.workgroup.workgroupKoinModule import fr.dcproject.event.EventNotification import fr.dcproject.event.EventSubscriber import fr.dcproject.routes.definition @@ -78,7 +87,21 @@ enum class Env { PROD, TEST, CUCUMBER } fun Application.module(env: Env = PROD) { install(Koin) { Slf4jLog() - modules(KoinModule) + modules( + listOf( + KoinModule, + articleKoinModule, + authKoinModule, + citizenKoinModule, + commentKoinModule, + constitutionKoinModule, + followKoinModule, + opinionKoinModule, + viewKoinModule, + voteKoinModule, + workgroupKoinModule, + ) + ) } install(CallLogging) { @@ -94,8 +117,6 @@ fun Application.module(env: Env = PROD) { } } - ConfigViews.createEsIndexForViews(get()) - install(WebSockets) { pingPeriod = Duration.ofSeconds(60) // Disabled (null) by default timeout = Duration.ofSeconds(15) diff --git a/src/main/kotlin/application/KoinModule.kt b/src/main/kotlin/application/KoinModule.kt index f31f31c..1fd748e 100644 --- a/src/main/kotlin/application/KoinModule.kt +++ b/src/main/kotlin/application/KoinModule.kt @@ -8,30 +8,6 @@ import com.fasterxml.jackson.databind.module.SimpleModule import com.fasterxml.jackson.datatype.joda.JodaModule import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.rabbitmq.client.ConnectionFactory -import fr.dcproject.component.article.ArticleAccessControl -import fr.dcproject.component.article.ArticleForView -import fr.dcproject.component.article.ArticleRepository -import fr.dcproject.component.article.ArticleViewManager -import fr.dcproject.component.auth.PasswordlessAuth -import fr.dcproject.component.auth.UserRepository -import fr.dcproject.component.citizen.CitizenAccessControl -import fr.dcproject.component.citizen.CitizenRepository -import fr.dcproject.component.comment.article.CommentArticleRepository -import fr.dcproject.component.comment.constitution.CommentConstitutionRepository -import fr.dcproject.component.comment.generic.CommentAccessControl -import fr.dcproject.component.constitution.ConstitutionAccessControl -import fr.dcproject.component.constitution.ConstitutionRepository -import fr.dcproject.component.follow.FollowAccessControl -import fr.dcproject.component.opinion.OpinionAccessControl -import fr.dcproject.component.opinion.OpinionChoiceAccessControl -import fr.dcproject.component.opinion.OpinionChoiceRepository -import fr.dcproject.component.vote.VoteAccessControl -import fr.dcproject.component.vote.VoteArticleRepository -import fr.dcproject.component.vote.VoteCommentRepository -import fr.dcproject.component.vote.VoteConstitutionRepository -import fr.dcproject.component.vote.VoteRepository -import fr.dcproject.component.workgroup.WorkgroupAccessControl -import fr.dcproject.component.workgroup.WorkgroupRepository import fr.dcproject.event.publisher.Publisher import fr.dcproject.messages.Mailer import fr.dcproject.messages.NotificationEmailSender @@ -43,14 +19,8 @@ import io.ktor.client.features.websocket.WebSockets import io.ktor.util.KtorExperimentalAPI import io.lettuce.core.RedisClient import io.lettuce.core.api.async.RedisAsyncCommands -import org.apache.http.HttpHost -import org.elasticsearch.client.RestClient import org.koin.core.qualifier.named import org.koin.dsl.module -import fr.dcproject.component.comment.generic.CommentRepository as CommentGenericRepository -import fr.dcproject.component.follow.FollowArticleRepository as FollowArticleRepository -import fr.dcproject.component.follow.FollowConstitutionRepository as FollowConstitutionRepository -import fr.dcproject.component.opinion.OpinionRepositoryArticle as OpinionArticleRepository @KtorExperimentalAPI val KoinModule = module { @@ -105,50 +75,9 @@ val KoinModule = module { ).createRequester() } - // Repositories - single { UserRepository(get()) } - single { ArticleRepository(get()) } - single { CitizenRepository(get()) } - single { ConstitutionRepository(get()) } - single { FollowArticleRepository(get()) } - single { FollowConstitutionRepository(get()) } - single { CommentGenericRepository(get()) } - single { CommentArticleRepository(get()) } - single { CommentConstitutionRepository(get()) } - single { VoteRepository(get()) } - single { VoteArticleRepository(get()) } - single { VoteConstitutionRepository(get()) } - single { VoteCommentRepository(get()) } - single { OpinionChoiceRepository(get()) } - single { OpinionArticleRepository(get()) } - single { WorkgroupRepository(get()) } - - // AccessControl - single { ArticleAccessControl(get()) } - single { CitizenAccessControl() } - single { CommentAccessControl() } - single { WorkgroupAccessControl() } - single { ConstitutionAccessControl() } - single { VoteAccessControl() } - single { FollowAccessControl() } - single { OpinionAccessControl() } - single { OpinionChoiceAccessControl() } - - // Elasticsearch Client - single { - RestClient.builder( - HttpHost.create(Configuration.elasticsearch) - ).build() - } - - single { ArticleViewManager(get()) } - // Mailer single { Mailer(Configuration.sendGridKey) } - // Used to send a connexion link by email - single { PasswordlessAuth(get(), Configuration.domain, get()) } - single { Publisher(get(), get(), exchangeName = Configuration.exchangeNotificationName) } single { NotificationEmailSender(get(), Configuration.domain, get(), get()) } diff --git a/src/main/kotlin/component/article/KoinModule.kt b/src/main/kotlin/component/article/KoinModule.kt new file mode 100644 index 0000000..2434328 --- /dev/null +++ b/src/main/kotlin/component/article/KoinModule.kt @@ -0,0 +1,8 @@ +package fr.dcproject.component.article + +import org.koin.dsl.module + +val articleKoinModule = module { + single { ArticleRepository(get()) } + single { ArticleAccessControl(get()) } +} diff --git a/src/main/kotlin/component/auth/KoinModule.kt b/src/main/kotlin/component/auth/KoinModule.kt new file mode 100644 index 0000000..cdf3d91 --- /dev/null +++ b/src/main/kotlin/component/auth/KoinModule.kt @@ -0,0 +1,11 @@ +package fr.dcproject.component.auth + +import fr.dcproject.application.Configuration +import fr.dcproject.messages.Mailer +import org.koin.dsl.module + +val authKoinModule = module { + single { UserRepository(get()) } + // Used to send a connexion link by email + single { PasswordlessAuth(get(), Configuration.domain, get()) } +} diff --git a/src/main/kotlin/component/citizen/KoinModule.kt b/src/main/kotlin/component/citizen/KoinModule.kt new file mode 100644 index 0000000..16e7a12 --- /dev/null +++ b/src/main/kotlin/component/citizen/KoinModule.kt @@ -0,0 +1,8 @@ +package fr.dcproject.component.citizen + +import org.koin.dsl.module + +val citizenKoinModule = module { + single { CitizenRepository(get()) } + single { CitizenAccessControl() } +} diff --git a/src/main/kotlin/component/comment/KoinModule.kt b/src/main/kotlin/component/comment/KoinModule.kt new file mode 100644 index 0000000..ef17eb1 --- /dev/null +++ b/src/main/kotlin/component/comment/KoinModule.kt @@ -0,0 +1,14 @@ +package fr.dcproject.component.comment + +import fr.dcproject.component.comment.article.CommentArticleRepository +import fr.dcproject.component.comment.constitution.CommentConstitutionRepository +import fr.dcproject.component.comment.generic.CommentAccessControl +import fr.dcproject.component.comment.generic.CommentRepository +import org.koin.dsl.module + +val commentKoinModule = module { + single { CommentRepository(get()) } + single { CommentArticleRepository(get()) } + single { CommentConstitutionRepository(get()) } + single { CommentAccessControl() } +} diff --git a/src/main/kotlin/component/constitution/KoinModule.kt b/src/main/kotlin/component/constitution/KoinModule.kt new file mode 100644 index 0000000..3fac4bb --- /dev/null +++ b/src/main/kotlin/component/constitution/KoinModule.kt @@ -0,0 +1,8 @@ +package fr.dcproject.component.constitution + +import org.koin.dsl.module + +val constitutionKoinModule = module { + single { ConstitutionRepository(get()) } + single { ConstitutionAccessControl() } +} diff --git a/src/main/kotlin/component/follow/KoinModule.kt b/src/main/kotlin/component/follow/KoinModule.kt new file mode 100644 index 0000000..00416c5 --- /dev/null +++ b/src/main/kotlin/component/follow/KoinModule.kt @@ -0,0 +1,9 @@ +package fr.dcproject.component.follow + +import org.koin.dsl.module + +val followKoinModule = module { + single { FollowArticleRepository(get()) } + single { FollowConstitutionRepository(get()) } + single { FollowAccessControl() } +} diff --git a/src/main/kotlin/component/opinion/KoinModule.kt b/src/main/kotlin/component/opinion/KoinModule.kt new file mode 100644 index 0000000..fcb8091 --- /dev/null +++ b/src/main/kotlin/component/opinion/KoinModule.kt @@ -0,0 +1,11 @@ +package fr.dcproject.component.opinion + +import org.koin.dsl.module + +val opinionKoinModule = module { + single { OpinionChoiceRepository(get()) } + single { OpinionRepositoryArticle(get()) } + + single { OpinionAccessControl() } + single { OpinionChoiceAccessControl() } +} diff --git a/src/main/kotlin/component/views/ConfigViews.kt b/src/main/kotlin/component/views/ConfigViews.kt deleted file mode 100644 index c07292f..0000000 --- a/src/main/kotlin/component/views/ConfigViews.kt +++ /dev/null @@ -1,85 +0,0 @@ -package fr.dcproject.component.views - -import org.elasticsearch.client.Request -import org.elasticsearch.client.RestClient -import org.slf4j.Logger -import org.slf4j.LoggerFactory - -object ConfigViews { - private fun waitElasticsearchIsUp(client: RestClient) { - val logger: Logger = LoggerFactory.getLogger("fr.dcproject.elasticsearch") - val request = Request("GET", "/_cluster/health") - repeat(5 * 60 / 2) { // 5 minutes - runCatching { - client.performRequest(request).statusLine.statusCode - }.onSuccess { - if (it == 200) { - logger.debug("Elasticsearch is Ready! Continue...") - return - } else { - logger.debug("sleep 2s and retry...") - Thread.sleep(2000) - } - }.onFailure { - logger.debug("${it.message}, sleep 2s and retry...") - Thread.sleep(2000) - } - } - error("Elasticsearch is not ready") - } - - fun createEsIndexForViews(client: RestClient) { - waitElasticsearchIsUp(client) - - /* Create index if not exist */ - client.run { - if (performRequest(Request("HEAD", "/views?include_type_name=false")).statusLine.statusCode == 404) { - Request( - "PUT", - "/views?include_type_name=false" - ).apply { - //language=JSON - setJsonEntity( - """ - { - "settings": { - "number_of_shards": 5 - }, - "mappings": { - "properties": { - "logged": { - "type": "boolean" - }, - "type": { - "type": "keyword" - }, - "user_ref": { - "type": "keyword" - }, - "id": { - "type": "keyword" - }, - "version_id": { - "type": "keyword" - }, - "ip": { - "type": "keyword" - }, - "citizen_id": { - "type": "keyword" - }, - "view_at": { - "type": "date" - } - } - } - } - """.trimIndent() - ) - }.let { - performRequest(it) - } - } - } - } -} diff --git a/src/main/kotlin/component/views/KoinModule.kt b/src/main/kotlin/component/views/KoinModule.kt new file mode 100644 index 0000000..10916a3 --- /dev/null +++ b/src/main/kotlin/component/views/KoinModule.kt @@ -0,0 +1,19 @@ +package fr.dcproject.component.views + +import fr.dcproject.application.Configuration +import fr.dcproject.component.article.ArticleForView +import fr.dcproject.component.article.ArticleViewManager +import org.apache.http.HttpHost +import org.elasticsearch.client.RestClient +import org.koin.dsl.module + +val viewKoinModule = module { + // Elasticsearch Client + val esClient = RestClient.builder( + HttpHost.create(Configuration.elasticsearch) + ).build().apply { + createEsIndexForViews() + } + + single { ArticleViewManager(esClient) } +} diff --git a/src/main/kotlin/component/views/createEsIndexForViews.kt b/src/main/kotlin/component/views/createEsIndexForViews.kt new file mode 100644 index 0000000..2c74f94 --- /dev/null +++ b/src/main/kotlin/component/views/createEsIndexForViews.kt @@ -0,0 +1,58 @@ +package fr.dcproject.component.views + +import fr.dcproject.utils.waitElasticsearchIsUp +import org.elasticsearch.client.Request +import org.elasticsearch.client.RestClient + +fun RestClient.createEsIndexForViews() { + waitElasticsearchIsUp() + + /* Create index if not exist */ + if (performRequest(Request("HEAD", "/views?include_type_name=false")).statusLine.statusCode == 404) { + Request( + "PUT", + "/views?include_type_name=false" + ).apply { + //language=JSON + setJsonEntity( + """ + { + "settings": { + "number_of_shards": 5 + }, + "mappings": { + "properties": { + "logged": { + "type": "boolean" + }, + "type": { + "type": "keyword" + }, + "user_ref": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "version_id": { + "type": "keyword" + }, + "ip": { + "type": "keyword" + }, + "citizen_id": { + "type": "keyword" + }, + "view_at": { + "type": "date" + } + } + } + } + """.trimIndent() + ) + }.let { + performRequest(it) + } + } +} diff --git a/src/main/kotlin/component/vote/KoinModule.kt b/src/main/kotlin/component/vote/KoinModule.kt new file mode 100644 index 0000000..94a7050 --- /dev/null +++ b/src/main/kotlin/component/vote/KoinModule.kt @@ -0,0 +1,12 @@ +package fr.dcproject.component.vote + +import org.koin.dsl.module + +val voteKoinModule = module { + single { VoteRepository(get()) } + single { VoteArticleRepository(get()) } + single { VoteConstitutionRepository(get()) } + single { VoteCommentRepository(get()) } + + single { VoteAccessControl() } +} diff --git a/src/main/kotlin/component/workgroup/KoinModule.kt b/src/main/kotlin/component/workgroup/KoinModule.kt new file mode 100644 index 0000000..d905ac9 --- /dev/null +++ b/src/main/kotlin/component/workgroup/KoinModule.kt @@ -0,0 +1,8 @@ +package fr.dcproject.component.workgroup + +import org.koin.dsl.module + +val workgroupKoinModule = module { + single { WorkgroupRepository(get()) } + single { WorkgroupAccessControl() } +} diff --git a/src/main/kotlin/utils/waitElastic.kt b/src/main/kotlin/utils/waitElastic.kt new file mode 100644 index 0000000..d95d6fd --- /dev/null +++ b/src/main/kotlin/utils/waitElastic.kt @@ -0,0 +1,28 @@ +package fr.dcproject.utils + +import org.elasticsearch.client.Request +import org.elasticsearch.client.RestClient +import org.slf4j.Logger +import org.slf4j.LoggerFactory + +fun RestClient.waitElasticsearchIsUp() { + val logger: Logger = LoggerFactory.getLogger("fr.dcproject.elasticsearch") + val request = Request("GET", "/_cluster/health") + repeat(5 * 60 / 2) { // 5 minutes + runCatching { + performRequest(request).statusLine.statusCode + }.onSuccess { + if (it == 200) { + logger.debug("Elasticsearch is Ready! Continue...") + return + } else { + logger.debug("sleep 2s and retry...") + Thread.sleep(2000) + } + }.onFailure { + logger.debug("${it.message}, sleep 2s and retry...") + Thread.sleep(2000) + } + } + error("Elasticsearch is not ready") +}