From 1e5598cb91b0d724997923f65fd6348b3da53788 Mon Sep 17 00:00:00 2001 From: Fabrice Lecomte Date: Sat, 23 Jan 2021 21:18:42 +0100 Subject: [PATCH] Move constitution to component --- src/main/kotlin/application/Application.kt | 4 +- src/main/kotlin/application/Converters.kt | 7 +- src/main/kotlin/application/KoinModule.kt | 4 +- .../component/article/ArticleViewManager.kt | 2 +- .../component/article/routes/GetOneArticle.kt | 5 +- .../constitution}/Constitution.kt | 11 +- .../ConstitutionAccessControl.kt | 4 +- .../constitution/ConstitutionRepository.kt} | 10 +- .../constitution/routes/CreateConstitution.kt | 82 +++++++++++++ .../constitution/routes/FindConstitutions.kt | 35 ++++++ .../constitution/routes/GetConstitution.kt | 25 ++++ .../component/constitution/routes/install.kt | 18 +++ .../component/follow/FollowRepository.kt | 4 +- .../routes/constitution/FollowConstitution.kt | 2 +- .../constitution/GetFollowConstitution.kt | 2 +- .../constitution/UnfollowConstitution.kt | 2 +- .../kotlin/component/views/ViewManager.kt | 2 +- .../views}/dto/ViewAggregation.kt | 4 +- .../{ => component/views}/dto/Viewable.kt | 4 +- .../views}/entity/ViewAggregation.kt | 2 +- .../component/vote/VoteRepositoryAbs.kt | 2 +- .../component/vote/routes/VoteConstitution.kt | 2 +- src/main/kotlin/entity/Extra.kt | 1 + .../CommentConstitutionRepository.kt | 2 +- src/main/kotlin/routes/CommentConstitution.kt | 2 +- src/main/kotlin/routes/Constitution.kt | 110 ------------------ src/test/kotlin/steps/ConstitutionSteps.kt | 9 +- src/test/kotlin/steps/FollowSteps.kt | 2 +- 28 files changed, 207 insertions(+), 152 deletions(-) rename src/main/kotlin/{entity => component/constitution}/Constitution.kt (86%) rename src/main/kotlin/{security/voter => component/constitution}/ConstitutionAccessControl.kt (92%) rename src/main/kotlin/{repository/Constitution.kt => component/constitution/ConstitutionRepository.kt} (78%) create mode 100644 src/main/kotlin/component/constitution/routes/CreateConstitution.kt create mode 100644 src/main/kotlin/component/constitution/routes/FindConstitutions.kt create mode 100644 src/main/kotlin/component/constitution/routes/GetConstitution.kt create mode 100644 src/main/kotlin/component/constitution/routes/install.kt rename src/main/kotlin/{ => component/views}/dto/ViewAggregation.kt (59%) rename src/main/kotlin/{ => component/views}/dto/Viewable.kt (54%) rename src/main/kotlin/{ => component/views}/entity/ViewAggregation.kt (86%) delete mode 100644 src/main/kotlin/routes/Constitution.kt diff --git a/src/main/kotlin/application/Application.kt b/src/main/kotlin/application/Application.kt index 47411be..f64a675 100644 --- a/src/main/kotlin/application/Application.kt +++ b/src/main/kotlin/application/Application.kt @@ -16,6 +16,7 @@ import fr.dcproject.component.auth.user import fr.dcproject.component.citizen.routes.installCitizenRoutes import fr.dcproject.component.comment.article.routes.installCommentArticleRoutes import fr.dcproject.component.comment.generic.routes.installCommentRoutes +import fr.dcproject.component.constitution.routes.installConstitutionRoutes import fr.dcproject.component.follow.routes.article.installFollowArticleRoutes import fr.dcproject.component.follow.routes.constitution.installFollowConstitutionRoutes import fr.dcproject.component.opinion.routes.installOpinionRoutes @@ -25,7 +26,6 @@ import fr.dcproject.component.workgroup.routes.installWorkgroupRoutes import fr.dcproject.event.EventNotification import fr.dcproject.event.EventSubscriber import fr.dcproject.routes.commentConstitution -import fr.dcproject.routes.constitution import fr.dcproject.routes.definition import fr.dcproject.routes.notificationArticle import fr.dcproject.security.AccessDeniedException @@ -140,10 +140,10 @@ fun Application.module(env: Env = PROD) { installWorkgroupRoutes() installOpinionRoutes() installVoteRoutes() + installConstitutionRoutes() authenticate(optional = true) { /* TODO */ - constitution(get(), get()) commentConstitution(get(), get()) definition() } diff --git a/src/main/kotlin/application/Converters.kt b/src/main/kotlin/application/Converters.kt index b74404b..507634f 100644 --- a/src/main/kotlin/application/Converters.kt +++ b/src/main/kotlin/application/Converters.kt @@ -8,13 +8,14 @@ import fr.dcproject.component.citizen.CitizenBasic import fr.dcproject.component.citizen.CitizenRef import fr.dcproject.component.citizen.CitizenRepository import fr.dcproject.component.comment.generic.CommentRef +import fr.dcproject.component.constitution.Constitution +import fr.dcproject.component.constitution.ConstitutionRef +import fr.dcproject.component.constitution.ConstitutionRepository import fr.dcproject.component.opinion.OpinionChoiceRepository import fr.dcproject.component.opinion.entity.OpinionChoice import fr.dcproject.component.workgroup.Workgroup import fr.dcproject.component.workgroup.WorkgroupRef import fr.dcproject.component.workgroup.WorkgroupRepository -import fr.dcproject.entity.Constitution -import fr.dcproject.entity.ConstitutionRef import io.ktor.features.DataConversion import io.ktor.features.NotFoundException import io.ktor.util.KtorExperimentalAPI @@ -80,7 +81,7 @@ val converters: ConverterDeclaration = { decode { values, _ -> val id = values.singleOrNull()?.let { UUID.fromString(it) } ?: throw InternalError("Cannot convert $values to UUID") - get().findById(id) ?: throw NotFoundException("Constitution $values not found") + get().findById(id) ?: throw NotFoundException("Constitution $values not found") } } diff --git a/src/main/kotlin/application/KoinModule.kt b/src/main/kotlin/application/KoinModule.kt index 4787c26..9a509a9 100644 --- a/src/main/kotlin/application/KoinModule.kt +++ b/src/main/kotlin/application/KoinModule.kt @@ -18,6 +18,8 @@ import fr.dcproject.component.citizen.CitizenAccessControl import fr.dcproject.component.citizen.CitizenRepository import fr.dcproject.component.comment.article.CommentArticleRepository 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 @@ -33,7 +35,6 @@ import fr.dcproject.event.publisher.Publisher import fr.dcproject.messages.Mailer import fr.dcproject.messages.NotificationEmailSender import fr.dcproject.repository.CommentConstitutionRepository -import fr.dcproject.security.voter.ConstitutionAccessControl import fr.postgresjson.connexion.Connection import fr.postgresjson.connexion.Requester import fr.postgresjson.migration.Migrations @@ -50,7 +51,6 @@ import fr.dcproject.component.comment.generic.CommentRepository as CommentGeneri import fr.dcproject.component.follow.FollowArticleRepository as FollowArticleRepository import fr.dcproject.component.follow.FollowConstitutionRepository as FollowConstitutionRepository import fr.dcproject.component.opinion.OpinionRepositoryArticle as OpinionArticleRepository -import fr.dcproject.repository.Constitution as ConstitutionRepository @KtorExperimentalAPI val KoinModule = module { diff --git a/src/main/kotlin/component/article/ArticleViewManager.kt b/src/main/kotlin/component/article/ArticleViewManager.kt index 660cab6..9a2e952 100644 --- a/src/main/kotlin/component/article/ArticleViewManager.kt +++ b/src/main/kotlin/component/article/ArticleViewManager.kt @@ -2,8 +2,8 @@ package fr.dcproject.component.article import fr.dcproject.component.citizen.CitizenI import fr.dcproject.component.views.ViewManager +import fr.dcproject.component.views.entity.ViewAggregation import fr.dcproject.entity.VersionableRef -import fr.dcproject.entity.ViewAggregation import fr.dcproject.utils.contentToString import fr.dcproject.utils.getJsonField import fr.dcproject.utils.toIso diff --git a/src/main/kotlin/component/article/routes/GetOneArticle.kt b/src/main/kotlin/component/article/routes/GetOneArticle.kt index e127511..bc4860f 100644 --- a/src/main/kotlin/component/article/routes/GetOneArticle.kt +++ b/src/main/kotlin/component/article/routes/GetOneArticle.kt @@ -7,10 +7,11 @@ import fr.dcproject.component.article.ArticleViewManager import fr.dcproject.component.article.routes.GetOneArticle.ArticleRequest.Output import fr.dcproject.component.auth.citizenOrNull import fr.dcproject.component.opinion.dto.Opinionable +import fr.dcproject.component.views.dto.Viewable +import fr.dcproject.component.views.entity.ViewAggregation import fr.dcproject.component.vote.dto.Votable import fr.dcproject.dto.CreatedAt import fr.dcproject.dto.Versionable -import fr.dcproject.dto.Viewable import fr.dcproject.security.assert import io.ktor.application.call import io.ktor.features.NotFoundException @@ -34,7 +35,7 @@ object GetOneArticle { class Output( article: ArticleForView, - views: fr.dcproject.entity.ViewAggregation = fr.dcproject.entity.ViewAggregation() + views: ViewAggregation = ViewAggregation() ) : CreatedAt by CreatedAt.Imp(article), Opinionable by Opinionable.Imp(article), Votable by Votable.Imp(article), diff --git a/src/main/kotlin/entity/Constitution.kt b/src/main/kotlin/component/constitution/Constitution.kt similarity index 86% rename from src/main/kotlin/entity/Constitution.kt rename to src/main/kotlin/component/constitution/Constitution.kt index a3862aa..59f3b86 100644 --- a/src/main/kotlin/entity/Constitution.kt +++ b/src/main/kotlin/component/constitution/Constitution.kt @@ -1,9 +1,12 @@ -package fr.dcproject.entity +package fr.dcproject.component.constitution import fr.dcproject.component.article.ArticleForListing import fr.dcproject.component.article.ArticleI import fr.dcproject.component.citizen.CitizenSimple import fr.dcproject.component.citizen.CitizenWithUserI +import fr.dcproject.component.constitution.ConstitutionSimple.TitleSimple +import fr.dcproject.entity.TargetI +import fr.dcproject.entity.TargetRef import fr.postgresjson.entity.EntityCreatedAt import fr.postgresjson.entity.EntityCreatedAtImp import fr.postgresjson.entity.EntityCreatedBy @@ -23,7 +26,7 @@ class Constitution( draft: Boolean = false, lastVersion: Boolean = false, override val createdBy: CitizenSimple -) : ConstitutionSimple>( +) : ConstitutionSimple>( id, title = title, anonymous = anonymous, @@ -38,10 +41,10 @@ class Constitution( name: String, rank: Int? = null, override val articles: MutableList = mutableListOf() - ) : ConstitutionSimple.TitleSimple(id, name, rank) + ) : TitleSimple(id, name, rank) } -open class ConstitutionSimple>( +open class ConstitutionSimple>( id: UUID = UUID.randomUUID(), val title: String, val anonymous: Boolean = true, diff --git a/src/main/kotlin/security/voter/ConstitutionAccessControl.kt b/src/main/kotlin/component/constitution/ConstitutionAccessControl.kt similarity index 92% rename from src/main/kotlin/security/voter/ConstitutionAccessControl.kt rename to src/main/kotlin/component/constitution/ConstitutionAccessControl.kt index 057d84d..d64d826 100644 --- a/src/main/kotlin/security/voter/ConstitutionAccessControl.kt +++ b/src/main/kotlin/component/constitution/ConstitutionAccessControl.kt @@ -1,8 +1,6 @@ -package fr.dcproject.security.voter +package fr.dcproject.component.constitution import fr.dcproject.component.citizen.CitizenI -import fr.dcproject.entity.ConstitutionS -import fr.dcproject.entity.ConstitutionSimple import fr.dcproject.security.AccessControl import fr.dcproject.security.AccessResponse diff --git a/src/main/kotlin/repository/Constitution.kt b/src/main/kotlin/component/constitution/ConstitutionRepository.kt similarity index 78% rename from src/main/kotlin/repository/Constitution.kt rename to src/main/kotlin/component/constitution/ConstitutionRepository.kt index 3736bf6..df2db85 100644 --- a/src/main/kotlin/repository/Constitution.kt +++ b/src/main/kotlin/component/constitution/ConstitutionRepository.kt @@ -1,17 +1,17 @@ -package fr.dcproject.repository +package fr.dcproject.component.constitution import fr.dcproject.component.article.ArticleRef import fr.dcproject.component.citizen.CitizenWithUserI -import fr.dcproject.entity.ConstitutionSimple +import fr.dcproject.component.constitution.ConstitutionSimple.TitleSimple import fr.postgresjson.connexion.Paginated import fr.postgresjson.connexion.Requester import fr.postgresjson.repository.RepositoryI import fr.postgresjson.repository.RepositoryI.Direction import net.pearx.kasechange.toSnakeCase import java.util.UUID -import fr.dcproject.entity.Constitution as ConstitutionEntity +import fr.dcproject.component.constitution.Constitution as ConstitutionEntity -class Constitution(override var requester: Requester) : RepositoryI { +class ConstitutionRepository(override var requester: Requester) : RepositoryI { fun findById(id: UUID): ConstitutionEntity? { val function = requester.getFunction("find_constitution_by_id") return function.selectOne("id" to id) @@ -35,7 +35,7 @@ class Constitution(override var requester: Requester) : RepositoryI { ) } - fun upsert(constitution: ConstitutionSimple>): ConstitutionEntity? { + fun upsert(constitution: ConstitutionSimple>): ConstitutionEntity? { return requester .getFunction("upsert_constitution") .selectOne("resource" to constitution) diff --git a/src/main/kotlin/component/constitution/routes/CreateConstitution.kt b/src/main/kotlin/component/constitution/routes/CreateConstitution.kt new file mode 100644 index 0000000..0af8436 --- /dev/null +++ b/src/main/kotlin/component/constitution/routes/CreateConstitution.kt @@ -0,0 +1,82 @@ +package fr.dcproject.component.constitution.routes + +import fr.dcproject.component.article.ArticleRef +import fr.dcproject.component.auth.citizen +import fr.dcproject.component.auth.citizenOrNull +import fr.dcproject.component.citizen.Citizen +import fr.dcproject.component.citizen.CitizenWithUserI +import fr.dcproject.component.constitution.ConstitutionAccessControl +import fr.dcproject.component.constitution.ConstitutionRepository +import fr.dcproject.component.constitution.ConstitutionSimple +import fr.dcproject.component.constitution.ConstitutionSimple.TitleSimple +import fr.dcproject.component.constitution.routes.CreateConstitution.PostConstitutionRequest.Input +import fr.dcproject.component.constitution.routes.CreateConstitution.PostConstitutionRequest.Input.Title +import fr.dcproject.security.assert +import fr.postgresjson.entity.UuidEntity +import io.ktor.application.call +import io.ktor.locations.KtorExperimentalLocationsAPI +import io.ktor.locations.Location +import io.ktor.locations.post +import io.ktor.request.receive +import io.ktor.response.respond +import io.ktor.routing.Route +import java.util.UUID + +@KtorExperimentalLocationsAPI +object CreateConstitution { + @Location("/constitutions") + class PostConstitutionRequest { + class Input( + var title: String, + var anonymous: Boolean = true, + var titles: MutableList = mutableListOf(), + var draft: Boolean = false, + var lastVersion: Boolean = false, + var versionId: UUID = UUID.randomUUID() + ) { + init { + titles.forEachIndexed { index, title -> + title.rank = index + } + } + + class Title( + id: UUID = UUID.randomUUID(), + var name: String, + var rank: Int? = null, + var articles: MutableList<ArticleRef> = mutableListOf() + ) : UuidEntity(id) + } + } + + private fun getNewConstitution(input: Input, citizen: Citizen) = input.run { + ConstitutionSimple<CitizenWithUserI, TitleSimple<ArticleRef>>( + id = UUID.randomUUID(), + title = title, + titles = titles.create(), + createdBy = citizen, + versionId = versionId + ) + } + + private fun List<Title>.create(): MutableList<TitleSimple<ArticleRef>> = + map { it.create() }.toMutableList() + + private fun Title.create(): TitleSimple<ArticleRef> = + TitleSimple( + id, + name, + rank, + articles + ) + + fun Route.createConstitution(repo: ConstitutionRepository, ac: ConstitutionAccessControl) { + post<PostConstitutionRequest> { + getNewConstitution(call.receive(), citizen).let { + ac.assert { canCreate(it, citizenOrNull) } + repo.upsert(it) + call.respond(it) + } + } + } +} diff --git a/src/main/kotlin/component/constitution/routes/FindConstitutions.kt b/src/main/kotlin/component/constitution/routes/FindConstitutions.kt new file mode 100644 index 0000000..6f954a4 --- /dev/null +++ b/src/main/kotlin/component/constitution/routes/FindConstitutions.kt @@ -0,0 +1,35 @@ +package fr.dcproject.component.constitution.routes + +import fr.dcproject.component.auth.citizenOrNull +import fr.dcproject.component.constitution.ConstitutionAccessControl +import fr.dcproject.component.constitution.ConstitutionRepository +import fr.dcproject.routes.PaginatedRequest +import fr.dcproject.routes.PaginatedRequestI +import fr.dcproject.security.assert +import fr.postgresjson.repository.RepositoryI +import io.ktor.application.call +import io.ktor.locations.KtorExperimentalLocationsAPI +import io.ktor.locations.Location +import io.ktor.locations.get +import io.ktor.response.respond +import io.ktor.routing.Route + +@KtorExperimentalLocationsAPI +object FindConstitutions { + @Location("/constitutions") + class FindConstitutionsRequest( + page: Int = 1, + limit: Int = 50, + val sort: String? = null, + val direction: RepositoryI.Direction? = null, + val search: String? = null + ) : PaginatedRequestI by PaginatedRequest(page, limit) + + fun Route.findConstitutions(repo: ConstitutionRepository, ac: ConstitutionAccessControl) { + get<FindConstitutionsRequest> { + val constitutions = repo.find(it.page, it.limit, it.sort, it.direction, it.search) + ac.assert { canView(constitutions.result, citizenOrNull) } + call.respond(constitutions) + } + } +} diff --git a/src/main/kotlin/component/constitution/routes/GetConstitution.kt b/src/main/kotlin/component/constitution/routes/GetConstitution.kt new file mode 100644 index 0000000..d6a6814 --- /dev/null +++ b/src/main/kotlin/component/constitution/routes/GetConstitution.kt @@ -0,0 +1,25 @@ +package fr.dcproject.component.constitution.routes + +import fr.dcproject.component.auth.citizenOrNull +import fr.dcproject.component.constitution.ConstitutionAccessControl +import fr.dcproject.security.assert +import io.ktor.application.call +import io.ktor.locations.KtorExperimentalLocationsAPI +import io.ktor.locations.Location +import io.ktor.locations.get +import io.ktor.response.respond +import io.ktor.routing.Route +import fr.dcproject.component.constitution.Constitution as ConstitutionEntity + +@KtorExperimentalLocationsAPI +object GetConstitution { + @Location("/constitutions/{constitution}") + class GetConstitutionRequest(val constitution: ConstitutionEntity) + + fun Route.getConstitution(ac: ConstitutionAccessControl) { + get<GetConstitutionRequest> { + ac.assert { canView(it.constitution, citizenOrNull) } + call.respond(it.constitution) + } + } +} diff --git a/src/main/kotlin/component/constitution/routes/install.kt b/src/main/kotlin/component/constitution/routes/install.kt new file mode 100644 index 0000000..3ea2394 --- /dev/null +++ b/src/main/kotlin/component/constitution/routes/install.kt @@ -0,0 +1,18 @@ +package fr.dcproject.component.constitution.routes + +import fr.dcproject.component.constitution.routes.CreateConstitution.createConstitution +import fr.dcproject.component.constitution.routes.FindConstitutions.findConstitutions +import fr.dcproject.component.constitution.routes.GetConstitution.getConstitution +import io.ktor.auth.authenticate +import io.ktor.locations.KtorExperimentalLocationsAPI +import io.ktor.routing.Routing +import org.koin.ktor.ext.get + +@KtorExperimentalLocationsAPI +fun Routing.installConstitutionRoutes() { + authenticate(optional = true) { + getConstitution(get()) + findConstitutions(get(), get()) + createConstitution(get(), get()) + } +} diff --git a/src/main/kotlin/component/follow/FollowRepository.kt b/src/main/kotlin/component/follow/FollowRepository.kt index a26e69d..b9a3b9f 100644 --- a/src/main/kotlin/component/follow/FollowRepository.kt +++ b/src/main/kotlin/component/follow/FollowRepository.kt @@ -4,7 +4,7 @@ import fr.dcproject.component.article.ArticleForView import fr.dcproject.component.article.ArticleRef import fr.dcproject.component.citizen.CitizenI import fr.dcproject.component.citizen.CitizenRef -import fr.dcproject.entity.ConstitutionRef +import fr.dcproject.component.constitution.ConstitutionRef import fr.dcproject.entity.TargetRef import fr.postgresjson.connexion.Paginated import fr.postgresjson.connexion.Requester @@ -13,8 +13,8 @@ import fr.postgresjson.repository.RepositoryI import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import java.util.UUID +import fr.dcproject.component.constitution.Constitution as ConstitutionEntity import fr.dcproject.component.follow.Follow as FollowEntity -import fr.dcproject.entity.Constitution as ConstitutionEntity sealed class FollowRepository<IN : TargetRef, OUT : TargetRef>(override var requester: Requester) : RepositoryI { open fun findByCitizen( diff --git a/src/main/kotlin/component/follow/routes/constitution/FollowConstitution.kt b/src/main/kotlin/component/follow/routes/constitution/FollowConstitution.kt index 7ea62a7..981e640 100644 --- a/src/main/kotlin/component/follow/routes/constitution/FollowConstitution.kt +++ b/src/main/kotlin/component/follow/routes/constitution/FollowConstitution.kt @@ -2,10 +2,10 @@ package fr.dcproject.component.follow.routes.constitution import fr.dcproject.component.auth.citizen import fr.dcproject.component.auth.citizenOrNull +import fr.dcproject.component.constitution.ConstitutionRef import fr.dcproject.component.follow.FollowAccessControl import fr.dcproject.component.follow.FollowConstitutionRepository import fr.dcproject.component.follow.FollowForUpdate -import fr.dcproject.entity.ConstitutionRef import fr.dcproject.security.assert import io.ktor.application.call import io.ktor.http.HttpStatusCode diff --git a/src/main/kotlin/component/follow/routes/constitution/GetFollowConstitution.kt b/src/main/kotlin/component/follow/routes/constitution/GetFollowConstitution.kt index fc121ec..cd3e67d 100644 --- a/src/main/kotlin/component/follow/routes/constitution/GetFollowConstitution.kt +++ b/src/main/kotlin/component/follow/routes/constitution/GetFollowConstitution.kt @@ -2,9 +2,9 @@ package fr.dcproject.component.follow.routes.constitution import fr.dcproject.component.auth.citizen import fr.dcproject.component.auth.citizenOrNull +import fr.dcproject.component.constitution.ConstitutionRef import fr.dcproject.component.follow.FollowAccessControl import fr.dcproject.component.follow.FollowConstitutionRepository -import fr.dcproject.entity.ConstitutionRef import fr.dcproject.security.assert import io.ktor.application.call import io.ktor.http.HttpStatusCode diff --git a/src/main/kotlin/component/follow/routes/constitution/UnfollowConstitution.kt b/src/main/kotlin/component/follow/routes/constitution/UnfollowConstitution.kt index 261fbab..2c0afd9 100644 --- a/src/main/kotlin/component/follow/routes/constitution/UnfollowConstitution.kt +++ b/src/main/kotlin/component/follow/routes/constitution/UnfollowConstitution.kt @@ -2,10 +2,10 @@ package fr.dcproject.component.follow.routes.constitution import fr.dcproject.component.auth.citizen import fr.dcproject.component.auth.citizenOrNull +import fr.dcproject.component.constitution.ConstitutionRef import fr.dcproject.component.follow.FollowAccessControl import fr.dcproject.component.follow.FollowConstitutionRepository import fr.dcproject.component.follow.FollowForUpdate -import fr.dcproject.entity.ConstitutionRef import fr.dcproject.security.assert import io.ktor.application.call import io.ktor.http.HttpStatusCode diff --git a/src/main/kotlin/component/views/ViewManager.kt b/src/main/kotlin/component/views/ViewManager.kt index 6a374dd..7bfd817 100644 --- a/src/main/kotlin/component/views/ViewManager.kt +++ b/src/main/kotlin/component/views/ViewManager.kt @@ -1,7 +1,7 @@ package fr.dcproject.component.views import fr.dcproject.component.citizen.CitizenI -import fr.dcproject.entity.ViewAggregation +import fr.dcproject.component.views.entity.ViewAggregation import org.elasticsearch.client.Response import org.joda.time.DateTime diff --git a/src/main/kotlin/dto/ViewAggregation.kt b/src/main/kotlin/component/views/dto/ViewAggregation.kt similarity index 59% rename from src/main/kotlin/dto/ViewAggregation.kt rename to src/main/kotlin/component/views/dto/ViewAggregation.kt index d9b8233..41b1b93 100644 --- a/src/main/kotlin/dto/ViewAggregation.kt +++ b/src/main/kotlin/component/views/dto/ViewAggregation.kt @@ -1,6 +1,6 @@ -package fr.dcproject.dto +package fr.dcproject.component.views.dto -import fr.dcproject.entity.ViewAggregation +import fr.dcproject.component.views.entity.ViewAggregation class ViewAggregation( val total: Int, diff --git a/src/main/kotlin/dto/Viewable.kt b/src/main/kotlin/component/views/dto/Viewable.kt similarity index 54% rename from src/main/kotlin/dto/Viewable.kt rename to src/main/kotlin/component/views/dto/Viewable.kt index 510b1c0..fb35787 100644 --- a/src/main/kotlin/dto/Viewable.kt +++ b/src/main/kotlin/component/views/dto/Viewable.kt @@ -1,9 +1,9 @@ -package fr.dcproject.dto +package fr.dcproject.component.views.dto interface Viewable { var views: ViewAggregation - class Imp(views: fr.dcproject.entity.ViewAggregation) : Viewable { + class Imp(views: fr.dcproject.component.views.entity.ViewAggregation) : Viewable { override var views: ViewAggregation = ViewAggregation(views.total, views.unique) } } diff --git a/src/main/kotlin/entity/ViewAggregation.kt b/src/main/kotlin/component/views/entity/ViewAggregation.kt similarity index 86% rename from src/main/kotlin/entity/ViewAggregation.kt rename to src/main/kotlin/component/views/entity/ViewAggregation.kt index e3de7c8..36019ab 100644 --- a/src/main/kotlin/entity/ViewAggregation.kt +++ b/src/main/kotlin/component/views/entity/ViewAggregation.kt @@ -1,4 +1,4 @@ -package fr.dcproject.entity +package fr.dcproject.component.views.entity import fr.postgresjson.entity.EntityI import fr.postgresjson.entity.EntityUpdatedAt diff --git a/src/main/kotlin/component/vote/VoteRepositoryAbs.kt b/src/main/kotlin/component/vote/VoteRepositoryAbs.kt index 8423e5e..e63be2b 100644 --- a/src/main/kotlin/component/vote/VoteRepositoryAbs.kt +++ b/src/main/kotlin/component/vote/VoteRepositoryAbs.kt @@ -4,9 +4,9 @@ import com.fasterxml.jackson.core.type.TypeReference import fr.dcproject.component.article.ArticleForView import fr.dcproject.component.citizen.CitizenRef import fr.dcproject.component.comment.generic.CommentForView +import fr.dcproject.component.constitution.Constitution import fr.dcproject.component.vote.entity.VoteAggregation import fr.dcproject.component.vote.entity.VoteForUpdateI -import fr.dcproject.entity.Constitution import fr.dcproject.entity.TargetI import fr.dcproject.entity.TargetRef import fr.postgresjson.connexion.Paginated diff --git a/src/main/kotlin/component/vote/routes/VoteConstitution.kt b/src/main/kotlin/component/vote/routes/VoteConstitution.kt index d29f63a..fbfde95 100644 --- a/src/main/kotlin/component/vote/routes/VoteConstitution.kt +++ b/src/main/kotlin/component/vote/routes/VoteConstitution.kt @@ -15,7 +15,7 @@ import io.ktor.locations.put import io.ktor.request.receive import io.ktor.response.respond import io.ktor.routing.Route -import fr.dcproject.entity.Constitution as ConstitutionEntity +import fr.dcproject.component.constitution.Constitution as ConstitutionEntity @KtorExperimentalLocationsAPI object VoteConstitution { diff --git a/src/main/kotlin/entity/Extra.kt b/src/main/kotlin/entity/Extra.kt index 023831f..90bc50c 100644 --- a/src/main/kotlin/entity/Extra.kt +++ b/src/main/kotlin/entity/Extra.kt @@ -3,6 +3,7 @@ package fr.dcproject.entity import fr.dcproject.component.article.ArticleRef import fr.dcproject.component.citizen.CitizenI import fr.dcproject.component.comment.generic.CommentRef +import fr.dcproject.component.constitution.ConstitutionRef import fr.dcproject.component.opinion.entity.OpinionRef import fr.postgresjson.entity.EntityCreatedAt import fr.postgresjson.entity.EntityCreatedBy diff --git a/src/main/kotlin/repository/CommentConstitutionRepository.kt b/src/main/kotlin/repository/CommentConstitutionRepository.kt index c6fb75a..1f03aa7 100644 --- a/src/main/kotlin/repository/CommentConstitutionRepository.kt +++ b/src/main/kotlin/repository/CommentConstitutionRepository.kt @@ -5,7 +5,7 @@ import fr.dcproject.component.citizen.CitizenRef import fr.dcproject.component.comment.article.CommentArticleRepository import fr.dcproject.component.comment.generic.CommentForView import fr.dcproject.component.comment.generic.CommentRepositoryAbs -import fr.dcproject.entity.ConstitutionRef +import fr.dcproject.component.constitution.ConstitutionRef import fr.dcproject.entity.TargetI import fr.postgresjson.connexion.Paginated import fr.postgresjson.connexion.Requester diff --git a/src/main/kotlin/routes/CommentConstitution.kt b/src/main/kotlin/routes/CommentConstitution.kt index e775417..5a90161 100644 --- a/src/main/kotlin/routes/CommentConstitution.kt +++ b/src/main/kotlin/routes/CommentConstitution.kt @@ -5,7 +5,7 @@ import fr.dcproject.component.auth.citizenOrNull import fr.dcproject.component.citizen.Citizen import fr.dcproject.component.comment.generic.CommentAccessControl import fr.dcproject.component.comment.generic.CommentForUpdate -import fr.dcproject.entity.ConstitutionRef +import fr.dcproject.component.constitution.ConstitutionRef import fr.dcproject.repository.CommentConstitutionRepository import fr.dcproject.security.assert import io.ktor.application.call diff --git a/src/main/kotlin/routes/Constitution.kt b/src/main/kotlin/routes/Constitution.kt deleted file mode 100644 index e0140e4..0000000 --- a/src/main/kotlin/routes/Constitution.kt +++ /dev/null @@ -1,110 +0,0 @@ -package fr.dcproject.routes - -import fr.dcproject.component.article.ArticleRef -import fr.dcproject.component.auth.citizen -import fr.dcproject.component.auth.citizenOrNull -import fr.dcproject.component.citizen.CitizenWithUserI -import fr.dcproject.entity.ConstitutionSimple -import fr.dcproject.entity.ConstitutionSimple.TitleSimple -import fr.dcproject.security.assert -import fr.dcproject.security.voter.ConstitutionAccessControl -import fr.postgresjson.entity.UuidEntity -import fr.postgresjson.repository.RepositoryI -import io.ktor.application.ApplicationCall -import io.ktor.application.call -import io.ktor.locations.KtorExperimentalLocationsAPI -import io.ktor.locations.Location -import io.ktor.locations.get -import io.ktor.locations.post -import io.ktor.request.receive -import io.ktor.response.respond -import io.ktor.routing.Route -import java.util.UUID -import fr.dcproject.entity.Constitution as ConstitutionEntity -import fr.dcproject.repository.Constitution as ConstitutionRepository - -@KtorExperimentalLocationsAPI -object ConstitutionPaths { - @Location("/constitutions") - class ConstitutionsRequest( - page: Int = 1, - limit: Int = 50, - val sort: String? = null, - val direction: RepositoryI.Direction? = null, - val search: String? = null - ) { - val page: Int = if (page < 1) 1 else page - val limit: Int = if (limit > 50) 50 else if (limit < 1) 1 else limit - } - - @Location("/constitutions/{constitution}") - class ConstitutionRequest(val constitution: ConstitutionEntity) - - @Location("/constitutions") - class PostConstitutionRequest { - class Constitution( - var title: String, - var anonymous: Boolean = true, - var titles: MutableList<Title> = mutableListOf(), - var draft: Boolean = false, - var lastVersion: Boolean = false, - var versionId: UUID = UUID.randomUUID() - ) { - init { - titles.forEachIndexed { index, title -> - title.rank = index - } - } - - class Title( - id: UUID = UUID.randomUUID(), - var name: String, - var rank: Int? = null, - var articles: MutableList<ArticleRef> = mutableListOf() - ) : UuidEntity(id) { - fun create(): TitleSimple<ArticleRef> = - TitleSimple( - id, - name, - rank, - articles - ) - } - - fun List<Title>.create(): MutableList<TitleSimple<ArticleRef>> = - map { it.create() }.toMutableList() - } - - suspend fun getNewConstitution(call: ApplicationCall): ConstitutionSimple<CitizenWithUserI, TitleSimple<ArticleRef>> = call.receive<Constitution>().run { - ConstitutionSimple<CitizenWithUserI, TitleSimple<ArticleRef>>( - id = UUID.randomUUID(), - title = title, - titles = titles.create(), - createdBy = call.citizen, - versionId = versionId - ) - } - } -} - -@KtorExperimentalLocationsAPI -fun Route.constitution(repo: ConstitutionRepository, ac: ConstitutionAccessControl) { - get<ConstitutionPaths.ConstitutionsRequest> { - val constitutions = repo.find(it.page, it.limit, it.sort, it.direction, it.search) - ac.assert { canView(constitutions.result, citizenOrNull) } - call.respond(constitutions) - } - - get<ConstitutionPaths.ConstitutionRequest> { - ac.assert { canView(it.constitution, citizenOrNull) } - call.respond(it.constitution) - } - - post<ConstitutionPaths.PostConstitutionRequest> { - it.getNewConstitution(call).let { constitution -> - ac.assert { canCreate(constitution, citizenOrNull) } - repo.upsert(constitution) - call.respond(constitution) - } - } -} diff --git a/src/test/kotlin/steps/ConstitutionSteps.kt b/src/test/kotlin/steps/ConstitutionSteps.kt index 5ffebe8..67c6a74 100644 --- a/src/test/kotlin/steps/ConstitutionSteps.kt +++ b/src/test/kotlin/steps/ConstitutionSteps.kt @@ -6,8 +6,10 @@ import fr.dcproject.component.citizen.CitizenI import fr.dcproject.component.citizen.CitizenRepository import fr.dcproject.component.citizen.CitizenWithUserI import fr.dcproject.component.comment.generic.CommentForUpdate -import fr.dcproject.entity.ConstitutionRef -import fr.dcproject.entity.ConstitutionSimple +import fr.dcproject.component.constitution.ConstitutionRef +import fr.dcproject.component.constitution.ConstitutionRepository +import fr.dcproject.component.constitution.ConstitutionSimple +import fr.dcproject.component.constitution.ConstitutionSimple.TitleSimple import fr.dcproject.repository.CommentConstitutionRepository import fr.dcproject.utils.toUUID import io.cucumber.datatable.DataTable @@ -17,7 +19,6 @@ import org.koin.test.KoinTest import org.koin.test.get import java.util.UUID import fr.dcproject.component.auth.User as UserEntity -import fr.dcproject.repository.Constitution as ConstitutionRepository class ConstitutionSteps : En, KoinTest { init { @@ -71,7 +72,7 @@ class ConstitutionSteps : En, KoinTest { name = "My Title" ) - val constitution = ConstitutionSimple<CitizenWithUserI, ConstitutionSimple.TitleSimple<ArticleRef>>( + val constitution = ConstitutionSimple<CitizenWithUserI, TitleSimple<ArticleRef>>( id = id ?: params?.get("id")?.toUUID() ?: UUID.randomUUID(), title = "hello", titles = mutableListOf(title1), diff --git a/src/test/kotlin/steps/FollowSteps.kt b/src/test/kotlin/steps/FollowSteps.kt index 1e0b38e..9d06c16 100644 --- a/src/test/kotlin/steps/FollowSteps.kt +++ b/src/test/kotlin/steps/FollowSteps.kt @@ -2,8 +2,8 @@ package steps import fr.dcproject.component.article.ArticleRef import fr.dcproject.component.citizen.CitizenRepository +import fr.dcproject.component.constitution.ConstitutionRef import fr.dcproject.component.follow.FollowForUpdate -import fr.dcproject.entity.ConstitutionRef import fr.dcproject.utils.toUUID import io.cucumber.java8.En import org.koin.test.KoinTest