Move Entity.Request to Routes
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="Build and start Docker" type="docker-deploy" factoryName="docker-compose.yml" server-name="Docker">
|
<configuration default="false" name="Build and start all Docker" type="docker-deploy" factoryName="docker-compose.yml" server-name="Docker">
|
||||||
<deployment type="docker-compose.yml">
|
<deployment type="docker-compose.yml">
|
||||||
<settings>
|
<settings>
|
||||||
<option name="envVars">
|
<option name="envVars">
|
||||||
27
.idea/runConfigurations/Run_dependencies.xml
generated
Normal file
27
.idea/runConfigurations/Run_dependencies.xml
generated
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Run dependencies" type="docker-deploy" factoryName="docker-compose.yml" server-name="Docker">
|
||||||
|
<deployment type="docker-compose.yml">
|
||||||
|
<settings>
|
||||||
|
<option name="envVars">
|
||||||
|
<list>
|
||||||
|
<DockerEnvVarImpl>
|
||||||
|
<option name="name" value="SEND_GRID_KEY" />
|
||||||
|
<option name="value" value="$SEND_GRID_KEY$" />
|
||||||
|
</DockerEnvVarImpl>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="commandLineOptions" value="--build" />
|
||||||
|
<option name="services">
|
||||||
|
<list>
|
||||||
|
<option value="db" />
|
||||||
|
<option value="elasticsearch" />
|
||||||
|
<option value="rabbitmq" />
|
||||||
|
<option value="redis" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="sourceFilePath" value="docker-compose.yml" />
|
||||||
|
</settings>
|
||||||
|
</deployment>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
8
.idea/runConfigurations/Start_Db.xml
generated
8
.idea/runConfigurations/Start_Db.xml
generated
@@ -2,6 +2,14 @@
|
|||||||
<configuration default="false" name="Start Db" type="docker-deploy" factoryName="docker-compose.yml" server-name="Docker">
|
<configuration default="false" name="Start Db" type="docker-deploy" factoryName="docker-compose.yml" server-name="Docker">
|
||||||
<deployment type="docker-compose.yml">
|
<deployment type="docker-compose.yml">
|
||||||
<settings>
|
<settings>
|
||||||
|
<option name="envVars">
|
||||||
|
<list>
|
||||||
|
<DockerEnvVarImpl>
|
||||||
|
<option name="name" value="SEND_GRID_KEY" />
|
||||||
|
<option name="value" value="$SEND_GRID_KEY$" />
|
||||||
|
</DockerEnvVarImpl>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
<option name="commandLineOptions" value="--build" />
|
<option name="commandLineOptions" value="--build" />
|
||||||
<option name="services">
|
<option name="services">
|
||||||
<list>
|
<list>
|
||||||
|
|||||||
8
.idea/runConfigurations/Start_OpenAPI.xml
generated
8
.idea/runConfigurations/Start_OpenAPI.xml
generated
@@ -2,6 +2,14 @@
|
|||||||
<configuration default="false" name="Start OpenAPI" type="docker-deploy" factoryName="docker-compose.yml" server-name="Docker">
|
<configuration default="false" name="Start OpenAPI" type="docker-deploy" factoryName="docker-compose.yml" server-name="Docker">
|
||||||
<deployment type="docker-compose.yml">
|
<deployment type="docker-compose.yml">
|
||||||
<settings>
|
<settings>
|
||||||
|
<option name="envVars">
|
||||||
|
<list>
|
||||||
|
<DockerEnvVarImpl>
|
||||||
|
<option name="name" value="SEND_GRID_KEY" />
|
||||||
|
<option name="value" value="$SEND_GRID_KEY$" />
|
||||||
|
</DockerEnvVarImpl>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
<option name="commandLineOptions" value="--build" />
|
<option name="commandLineOptions" value="--build" />
|
||||||
<option name="services">
|
<option name="services">
|
||||||
<list>
|
<list>
|
||||||
|
|||||||
24
.idea/runConfigurations/Start_RabbitMQ.xml
generated
Normal file
24
.idea/runConfigurations/Start_RabbitMQ.xml
generated
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Start RabbitMQ" type="docker-deploy" factoryName="docker-compose.yml" server-name="Docker">
|
||||||
|
<deployment type="docker-compose.yml">
|
||||||
|
<settings>
|
||||||
|
<option name="envVars">
|
||||||
|
<list>
|
||||||
|
<DockerEnvVarImpl>
|
||||||
|
<option name="name" value="SEND_GRID_KEY" />
|
||||||
|
<option name="value" value="$SEND_GRID_KEY$" />
|
||||||
|
</DockerEnvVarImpl>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="commandLineOptions" value="--build" />
|
||||||
|
<option name="services">
|
||||||
|
<list>
|
||||||
|
<option value="rabbitmq" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="sourceFilePath" value="docker-compose.yml" />
|
||||||
|
</settings>
|
||||||
|
</deployment>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="Docker" type="docker-deploy" factoryName="docker-compose.yml" server-name="Docker">
|
<configuration default="false" name="Start Redis" type="docker-deploy" factoryName="docker-compose.yml" server-name="Docker">
|
||||||
<deployment type="docker-compose.yml">
|
<deployment type="docker-compose.yml">
|
||||||
<settings>
|
<settings>
|
||||||
<option name="envVars">
|
<option name="envVars">
|
||||||
@@ -11,6 +11,11 @@
|
|||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
<option name="commandLineOptions" value="--build" />
|
<option name="commandLineOptions" value="--build" />
|
||||||
|
<option name="services">
|
||||||
|
<list>
|
||||||
|
<option value="redis" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
<option name="sourceFilePath" value="docker-compose.yml" />
|
<option name="sourceFilePath" value="docker-compose.yml" />
|
||||||
</settings>
|
</settings>
|
||||||
</deployment>
|
</deployment>
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
package fr.dcproject.entity.request
|
|
||||||
|
|
||||||
import fr.dcproject.entity.ArticleFull
|
|
||||||
import fr.dcproject.entity.Citizen
|
|
||||||
import java.util.*
|
|
||||||
import fr.dcproject.entity.Article as ArticleEntity
|
|
||||||
|
|
||||||
class Article(
|
|
||||||
val id: UUID?,
|
|
||||||
val title: String,
|
|
||||||
val anonymous: Boolean = true,
|
|
||||||
val content: String,
|
|
||||||
val description: String,
|
|
||||||
val tags: List<String> = emptyList(),
|
|
||||||
val draft: Boolean = false,
|
|
||||||
val versionId: UUID?
|
|
||||||
) :
|
|
||||||
Request {
|
|
||||||
|
|
||||||
fun merge(article: ArticleFull) {
|
|
||||||
article.title = this.title
|
|
||||||
article.content = this.content
|
|
||||||
article.description = this.description
|
|
||||||
article.tags = this.tags.distinct()
|
|
||||||
article.anonymous = this.anonymous
|
|
||||||
article.draft = this.draft
|
|
||||||
article.versionId = this.versionId ?: UUID.randomUUID()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun create(createdBy: Citizen): ArticleEntity {
|
|
||||||
return ArticleEntity(
|
|
||||||
id ?: UUID.randomUUID(),
|
|
||||||
title,
|
|
||||||
anonymous,
|
|
||||||
content,
|
|
||||||
description,
|
|
||||||
tags,
|
|
||||||
draft,
|
|
||||||
createdBy = createdBy
|
|
||||||
).apply { this.versionId = this@Article.versionId ?: UUID.randomUUID() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package fr.dcproject.entity.request
|
|
||||||
|
|
||||||
class Comment(
|
|
||||||
val content: String
|
|
||||||
) : Request
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
package fr.dcproject.entity.request
|
|
||||||
|
|
||||||
import fr.dcproject.entity.ArticleRef
|
|
||||||
import fr.dcproject.entity.Citizen
|
|
||||||
import fr.dcproject.entity.CitizenSimple
|
|
||||||
import fr.dcproject.entity.ConstitutionSimple
|
|
||||||
import fr.postgresjson.entity.immutable.UuidEntity
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
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(): ConstitutionSimple.TitleSimple<ArticleRef> {
|
|
||||||
return ConstitutionSimple.TitleSimple(
|
|
||||||
id, name, rank, articles
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun create(createdBy: Citizen): ConstitutionSimple<CitizenSimple, ConstitutionSimple.TitleSimple<ArticleRef>> {
|
|
||||||
return ConstitutionSimple(
|
|
||||||
title = title,
|
|
||||||
titles = titles.create(),
|
|
||||||
createdBy = createdBy,
|
|
||||||
versionId = versionId
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun List<Constitution.Title>.create(): MutableList<ConstitutionSimple.TitleSimple<ArticleRef>> =
|
|
||||||
map { it.create() }.toMutableList()
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package fr.dcproject.entity.request
|
|
||||||
|
|
||||||
import io.ktor.application.ApplicationCall
|
|
||||||
|
|
||||||
interface Request
|
|
||||||
|
|
||||||
interface RequestBuilder<E> {
|
|
||||||
suspend fun getContent(call: ApplicationCall): E
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun <E> ApplicationCall.getContent(builder: RequestBuilder<E>) = builder.getContent(this)
|
|
||||||
@@ -6,9 +6,10 @@ import fr.dcproject.event.ArticleUpdate
|
|||||||
import fr.dcproject.repository.Article.Filter
|
import fr.dcproject.repository.Article.Filter
|
||||||
import fr.dcproject.security.voter.ArticleVoter.Action.CREATE
|
import fr.dcproject.security.voter.ArticleVoter.Action.CREATE
|
||||||
import fr.dcproject.security.voter.ArticleVoter.Action.VIEW
|
import fr.dcproject.security.voter.ArticleVoter.Action.VIEW
|
||||||
import fr.ktorVoter.assertCan
|
|
||||||
import fr.dcproject.views.ArticleViewManager
|
import fr.dcproject.views.ArticleViewManager
|
||||||
|
import fr.ktorVoter.assertCan
|
||||||
import fr.postgresjson.repository.RepositoryI
|
import fr.postgresjson.repository.RepositoryI
|
||||||
|
import io.ktor.application.ApplicationCall
|
||||||
import io.ktor.application.application
|
import io.ktor.application.application
|
||||||
import io.ktor.application.call
|
import io.ktor.application.call
|
||||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||||
@@ -19,8 +20,8 @@ import io.ktor.request.receive
|
|||||||
import io.ktor.response.respond
|
import io.ktor.response.respond
|
||||||
import io.ktor.routing.Route
|
import io.ktor.routing.Route
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import java.util.*
|
||||||
import fr.dcproject.entity.Article as ArticleEntity
|
import fr.dcproject.entity.Article as ArticleEntity
|
||||||
import fr.dcproject.entity.request.Article as ArticleEntityRequest
|
|
||||||
import fr.dcproject.repository.Article as ArticleRepository
|
import fr.dcproject.repository.Article as ArticleRepository
|
||||||
|
|
||||||
@KtorExperimentalLocationsAPI
|
@KtorExperimentalLocationsAPI
|
||||||
@@ -55,7 +56,33 @@ object ArticlesPaths {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Location("/articles")
|
@Location("/articles")
|
||||||
class PostArticleRequest
|
class PostArticleRequest {
|
||||||
|
class Article(
|
||||||
|
val id: UUID?,
|
||||||
|
val title: String,
|
||||||
|
val anonymous: Boolean = true,
|
||||||
|
val content: String,
|
||||||
|
val description: String,
|
||||||
|
val tags: List<String> = emptyList(),
|
||||||
|
val draft: Boolean = false,
|
||||||
|
val versionId: UUID?
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun getNewArticle(call: ApplicationCall): ArticleEntity = call.receive<Article>().run {
|
||||||
|
ArticleEntity(
|
||||||
|
id ?: UUID.randomUUID(),
|
||||||
|
title,
|
||||||
|
anonymous,
|
||||||
|
content,
|
||||||
|
description,
|
||||||
|
tags,
|
||||||
|
draft,
|
||||||
|
createdBy = call.citizen
|
||||||
|
).also {
|
||||||
|
it.versionId = versionId ?: UUID.randomUUID()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@KtorExperimentalLocationsAPI
|
@KtorExperimentalLocationsAPI
|
||||||
@@ -82,20 +109,17 @@ fun Route.article(repo: ArticleRepository, viewManager: ArticleViewManager) {
|
|||||||
get<ArticlesPaths.ArticleVersionsRequest> {
|
get<ArticlesPaths.ArticleVersionsRequest> {
|
||||||
assertCan(VIEW, it.article)
|
assertCan(VIEW, it.article)
|
||||||
|
|
||||||
val versions = repo.findVerionsByVersionsId(it.page, it.limit, it.article.versionId)
|
repo.findVerionsByVersionsId(it.page, it.limit, it.article.versionId).let {
|
||||||
|
call.respond(it)
|
||||||
call.respond(versions)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
post<ArticlesPaths.PostArticleRequest> {
|
post<ArticlesPaths.PostArticleRequest> {
|
||||||
val request = call.receive<ArticleEntityRequest>()
|
it.getNewArticle(call).also { article ->
|
||||||
val article = request.create(citizen)
|
assertCan(CREATE, article)
|
||||||
|
repo.upsert(article)
|
||||||
assertCan(CREATE, article)
|
call.respond(article)
|
||||||
|
application.environment.monitor.raise(ArticleUpdate.event, ArticleUpdate(article))
|
||||||
repo.upsert(article)
|
}
|
||||||
application.environment.monitor.raise(ArticleUpdate.event, ArticleUpdate(article))
|
|
||||||
|
|
||||||
call.respond(article)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import fr.dcproject.repository.CommentArticle.Sort
|
|||||||
import fr.dcproject.security.voter.CommentVoter.Action.CREATE
|
import fr.dcproject.security.voter.CommentVoter.Action.CREATE
|
||||||
import fr.dcproject.security.voter.CommentVoter.Action.VIEW
|
import fr.dcproject.security.voter.CommentVoter.Action.VIEW
|
||||||
import fr.ktorVoter.assertCan
|
import fr.ktorVoter.assertCan
|
||||||
|
import io.ktor.application.ApplicationCall
|
||||||
import io.ktor.application.call
|
import io.ktor.application.call
|
||||||
import io.ktor.http.HttpStatusCode
|
import io.ktor.http.HttpStatusCode
|
||||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||||
@@ -17,7 +18,6 @@ import io.ktor.request.receive
|
|||||||
import io.ktor.response.respond
|
import io.ktor.response.respond
|
||||||
import io.ktor.routing.Route
|
import io.ktor.routing.Route
|
||||||
import fr.dcproject.entity.Comment as CommentEntity
|
import fr.dcproject.entity.Comment as CommentEntity
|
||||||
import fr.dcproject.entity.request.Comment as CommentEntityRequest
|
|
||||||
import fr.dcproject.repository.CommentArticle as CommentArticleRepository
|
import fr.dcproject.repository.CommentArticle as CommentArticleRepository
|
||||||
|
|
||||||
@KtorExperimentalLocationsAPI
|
@KtorExperimentalLocationsAPI
|
||||||
@@ -35,6 +35,23 @@ object CommentArticlePaths {
|
|||||||
val sort: Sort = Sort.fromString(sort) ?: Sort.CREATED_AT
|
val sort: Sort = Sort.fromString(sort) ?: Sort.CREATED_AT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Location("/articles/{article}/comments")
|
||||||
|
class PostArticleCommentRequest(
|
||||||
|
val article: Article
|
||||||
|
) {
|
||||||
|
class Comment(
|
||||||
|
val content: String
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun getComment(call: ApplicationCall) = call.receive<Comment>().run {
|
||||||
|
CommentEntity(
|
||||||
|
target = article,
|
||||||
|
createdBy = call.citizen,
|
||||||
|
content = content
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Location("/citizens/{citizen}/comments/articles")
|
@Location("/citizens/{citizen}/comments/articles")
|
||||||
class CitizenCommentArticleRequest(val citizen: Citizen)
|
class CitizenCommentArticleRequest(val citizen: Citizen)
|
||||||
}
|
}
|
||||||
@@ -49,23 +66,18 @@ fun Route.commentArticle(repo: CommentArticleRepository) {
|
|||||||
call.respond(HttpStatusCode.OK, comment)
|
call.respond(HttpStatusCode.OK, comment)
|
||||||
}
|
}
|
||||||
|
|
||||||
post<CommentArticlePaths.ArticleCommentRequest> {
|
post<CommentArticlePaths.PostArticleCommentRequest> {
|
||||||
val content = call.receive<CommentEntityRequest>().content
|
it.getComment(call).let { comment ->
|
||||||
val comment = CommentEntity(
|
assertCan(CREATE, comment)
|
||||||
target = it.article,
|
repo.comment(comment)
|
||||||
createdBy = citizen,
|
call.respond(HttpStatusCode.Created, comment)
|
||||||
content = content
|
}
|
||||||
)
|
|
||||||
|
|
||||||
assertCan(CREATE, comment)
|
|
||||||
repo.comment(comment)
|
|
||||||
|
|
||||||
call.respond(HttpStatusCode.Created, comment)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get<CommentArticlePaths.CitizenCommentArticleRequest> {
|
get<CommentArticlePaths.CitizenCommentArticleRequest> {
|
||||||
val comments = repo.findByCitizen(it.citizen)
|
repo.findByCitizen(it.citizen).let { comments ->
|
||||||
assertCan(VIEW, comments.result)
|
assertCan(VIEW, comments.result)
|
||||||
call.respond(comments)
|
call.respond(comments)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,15 @@
|
|||||||
package fr.dcproject.routes
|
package fr.dcproject.routes
|
||||||
|
|
||||||
import fr.dcproject.citizen
|
import fr.dcproject.citizen
|
||||||
import fr.dcproject.entity.request.Constitution
|
import fr.dcproject.entity.ArticleRef
|
||||||
|
import fr.dcproject.entity.CitizenSimple
|
||||||
|
import fr.dcproject.entity.ConstitutionSimple
|
||||||
import fr.dcproject.security.voter.ConstitutionVoter.Action.CREATE
|
import fr.dcproject.security.voter.ConstitutionVoter.Action.CREATE
|
||||||
import fr.dcproject.security.voter.ConstitutionVoter.Action.VIEW
|
import fr.dcproject.security.voter.ConstitutionVoter.Action.VIEW
|
||||||
import fr.ktorVoter.assertCan
|
import fr.ktorVoter.assertCan
|
||||||
|
import fr.postgresjson.entity.immutable.UuidEntity
|
||||||
import fr.postgresjson.repository.RepositoryI
|
import fr.postgresjson.repository.RepositoryI
|
||||||
|
import io.ktor.application.ApplicationCall
|
||||||
import io.ktor.application.call
|
import io.ktor.application.call
|
||||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||||
import io.ktor.locations.Location
|
import io.ktor.locations.Location
|
||||||
@@ -14,6 +18,7 @@ import io.ktor.locations.post
|
|||||||
import io.ktor.request.receive
|
import io.ktor.request.receive
|
||||||
import io.ktor.response.respond
|
import io.ktor.response.respond
|
||||||
import io.ktor.routing.Route
|
import io.ktor.routing.Route
|
||||||
|
import java.util.*
|
||||||
import fr.dcproject.entity.Constitution as ConstitutionEntity
|
import fr.dcproject.entity.Constitution as ConstitutionEntity
|
||||||
import fr.dcproject.repository.Constitution as ConstitutionRepository
|
import fr.dcproject.repository.Constitution as ConstitutionRepository
|
||||||
|
|
||||||
@@ -35,7 +40,46 @@ object ConstitutionPaths {
|
|||||||
class ConstitutionRequest(val constitution: ConstitutionEntity)
|
class ConstitutionRequest(val constitution: ConstitutionEntity)
|
||||||
|
|
||||||
@Location("/constitutions")
|
@Location("/constitutions")
|
||||||
class PostConstitutionRequest
|
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(): ConstitutionSimple.TitleSimple<ArticleRef> =
|
||||||
|
ConstitutionSimple.TitleSimple(
|
||||||
|
id, name, rank, articles
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun List<Title>.create(): MutableList<ConstitutionSimple.TitleSimple<ArticleRef>> =
|
||||||
|
map { it.create() }.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getNewConstitution(call: ApplicationCall): ConstitutionSimple<CitizenSimple, ConstitutionSimple.TitleSimple<ArticleRef>> = call.receive<Constitution>().run {
|
||||||
|
ConstitutionSimple(
|
||||||
|
title = title,
|
||||||
|
titles = titles.create(),
|
||||||
|
createdBy = call.citizen,
|
||||||
|
versionId = versionId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@KtorExperimentalLocationsAPI
|
@KtorExperimentalLocationsAPI
|
||||||
@@ -52,11 +96,10 @@ fun Route.constitution(repo: ConstitutionRepository) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
post<ConstitutionPaths.PostConstitutionRequest> {
|
post<ConstitutionPaths.PostConstitutionRequest> {
|
||||||
val constitution = call.receive<Constitution>().create(citizen)
|
it.getNewConstitution(call).let { constitution ->
|
||||||
assertCan(CREATE, constitution)
|
assertCan(CREATE, constitution)
|
||||||
|
repo.upsert(constitution)
|
||||||
repo.upsert(constitution)
|
call.respond(constitution)
|
||||||
|
}
|
||||||
call.respond(constitution)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,13 +3,10 @@ package fr.dcproject.routes
|
|||||||
import fr.dcproject.citizen
|
import fr.dcproject.citizen
|
||||||
import fr.dcproject.entity.CitizenRef
|
import fr.dcproject.entity.CitizenRef
|
||||||
import fr.dcproject.entity.OpinionChoiceRef
|
import fr.dcproject.entity.OpinionChoiceRef
|
||||||
import fr.dcproject.entity.request.RequestBuilder
|
|
||||||
import fr.dcproject.entity.request.getContent
|
|
||||||
import fr.dcproject.security.voter.OpinionVoter.Action.CREATE
|
import fr.dcproject.security.voter.OpinionVoter.Action.CREATE
|
||||||
import fr.dcproject.security.voter.OpinionVoter.Action.VIEW
|
import fr.dcproject.security.voter.OpinionVoter.Action.VIEW
|
||||||
import fr.ktorVoter.assertCan
|
import fr.ktorVoter.assertCan
|
||||||
import fr.dcproject.utils.toUUID
|
import fr.dcproject.utils.toUUID
|
||||||
import io.ktor.application.ApplicationCall
|
|
||||||
import io.ktor.application.call
|
import io.ktor.application.call
|
||||||
import io.ktor.http.HttpStatusCode
|
import io.ktor.http.HttpStatusCode
|
||||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||||
@@ -44,14 +41,10 @@ object OpinionArticlePaths {
|
|||||||
*/
|
*/
|
||||||
@Location("/articles/{article}/opinions")
|
@Location("/articles/{article}/opinions")
|
||||||
@KtorExperimentalAPI
|
@KtorExperimentalAPI
|
||||||
class ArticleOpinion(val article: ArticleEntity) : RequestBuilder<List<OpinionChoiceRef>> {
|
class ArticleOpinion(val article: ArticleEntity) {
|
||||||
|
class Body(ids: List<String>) {
|
||||||
private class Content(ids: List<String>) : KoinComponent {
|
val ids = ids.map { OpinionChoiceRef(it.toUUID()) }
|
||||||
val ids = ids.map { it.toUUID() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getContent(call: ApplicationCall): List<OpinionChoiceRef> =
|
|
||||||
call.receive<Content>().ids.map { OpinionChoiceRef(it) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,12 +73,11 @@ fun Route.opinionArticle(repo: OpinionArticleRepository) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
put<OpinionArticlePaths.ArticleOpinion> {
|
put<OpinionArticlePaths.ArticleOpinion> {
|
||||||
call.getContent(it)
|
call.receive<OpinionArticlePaths.ArticleOpinion.Body>().ids.let { choices ->
|
||||||
.let { choices ->
|
assertCan(CREATE, it.article)
|
||||||
assertCan(CREATE, it.article)
|
repo.updateOpinions(choices, citizen, it.article)
|
||||||
repo.updateOpinions(choices, citizen, it.article)
|
}.let {
|
||||||
}.let {
|
call.respond(HttpStatusCode.Created, it)
|
||||||
call.respond(HttpStatusCode.Created, it)
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ package fr.dcproject.routes
|
|||||||
import fr.dcproject.citizen
|
import fr.dcproject.citizen
|
||||||
import fr.dcproject.entity.CitizenRef
|
import fr.dcproject.entity.CitizenRef
|
||||||
import fr.dcproject.entity.WorkgroupSimple
|
import fr.dcproject.entity.WorkgroupSimple
|
||||||
import fr.dcproject.entity.request.RequestBuilder
|
|
||||||
import fr.dcproject.entity.request.getContent
|
|
||||||
import fr.dcproject.repository.Workgroup.Filter
|
import fr.dcproject.repository.Workgroup.Filter
|
||||||
import fr.dcproject.security.voter.WorkgroupVoter.Action.VIEW
|
import fr.dcproject.security.voter.WorkgroupVoter.Action.VIEW
|
||||||
import fr.dcproject.security.voter.WorkgroupVoter.Action.CREATE
|
import fr.dcproject.security.voter.WorkgroupVoter.Action.CREATE
|
||||||
@@ -27,7 +25,6 @@ import io.ktor.locations.delete
|
|||||||
import io.ktor.request.receive
|
import io.ktor.request.receive
|
||||||
import io.ktor.response.respond
|
import io.ktor.response.respond
|
||||||
import io.ktor.routing.Route
|
import io.ktor.routing.Route
|
||||||
import org.koin.core.KoinComponent
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import fr.dcproject.entity.Workgroup as WorkgroupEntity
|
import fr.dcproject.entity.Workgroup as WorkgroupEntity
|
||||||
import fr.dcproject.repository.Workgroup as WorkgroupRepository
|
import fr.dcproject.repository.Workgroup as WorkgroupRepository
|
||||||
@@ -51,54 +48,44 @@ object WorkgroupsPaths {
|
|||||||
class WorkgroupRequest(val workgroup: WorkgroupEntity)
|
class WorkgroupRequest(val workgroup: WorkgroupEntity)
|
||||||
|
|
||||||
@Location("/workgroups")
|
@Location("/workgroups")
|
||||||
open class PostWorkgroupRequest : RequestBuilder<WorkgroupSimple<CitizenRef>> {
|
open class PostWorkgroupRequest {
|
||||||
class Content(
|
class Body(
|
||||||
val id: UUID?,
|
val id: UUID?,
|
||||||
val name: String,
|
val name: String,
|
||||||
val description: String,
|
val description: String,
|
||||||
val logo: String?,
|
val logo: String?,
|
||||||
val anonymous: Boolean?,
|
val anonymous: Boolean?,
|
||||||
val owner: UUID?
|
val owner: UUID?
|
||||||
) : KoinComponent {
|
)
|
||||||
fun create(creator: CitizenRef): WorkgroupSimple<CitizenRef> {
|
|
||||||
return WorkgroupSimple(
|
|
||||||
id ?: UUID.randomUUID(),
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
logo,
|
|
||||||
anonymous ?: true,
|
|
||||||
owner?.let { CitizenRef(it) } ?: creator,
|
|
||||||
creator
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun getContent(call: ApplicationCall): WorkgroupSimple<CitizenRef> {
|
suspend fun getNewWorkgroup(call: ApplicationCall): WorkgroupSimple<CitizenRef> = call.receive<Body>().run {
|
||||||
return call.receive<Content>().create(call.citizen)
|
WorkgroupSimple(
|
||||||
|
id ?: UUID.randomUUID(),
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
logo,
|
||||||
|
anonymous ?: true,
|
||||||
|
owner?.let { CitizenRef(it) } ?: call.citizen,
|
||||||
|
call.citizen
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Location("/workgroups/{workgroup}")
|
@Location("/workgroups/{workgroup}")
|
||||||
class PutWorkgroupRequest(val workgroup: WorkgroupEntity) : RequestBuilder<WorkgroupEntity> {
|
class PutWorkgroupRequest(val workgroup: WorkgroupEntity) {
|
||||||
class Content(
|
class Body(
|
||||||
val name: String?,
|
val name: String?,
|
||||||
val description: String?,
|
val description: String?,
|
||||||
val logo: String?,
|
val logo: String?,
|
||||||
val anonymous: Boolean?,
|
val anonymous: Boolean?,
|
||||||
val owner: UUID?
|
val owner: UUID?
|
||||||
) : KoinComponent {
|
)
|
||||||
fun update(workgroup: WorkgroupEntity): WorkgroupEntity {
|
|
||||||
name?.let { workgroup.name = it }
|
|
||||||
description?.let { workgroup.description = it }
|
|
||||||
logo?.let { workgroup.logo = it }
|
|
||||||
anonymous?.let { workgroup.anonymous = it }
|
|
||||||
|
|
||||||
return workgroup
|
suspend fun updateWorkgroup(call: ApplicationCall): Unit = call.receive<Body>().run {
|
||||||
}
|
name?.let { workgroup.name = it }
|
||||||
}
|
description?.let { workgroup.description = it }
|
||||||
|
logo?.let { workgroup.logo = it }
|
||||||
override suspend fun getContent(call: ApplicationCall): WorkgroupEntity {
|
anonymous?.let { workgroup.anonymous = it }
|
||||||
return call.receive<Content>().update(workgroup)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,15 +96,15 @@ object WorkgroupsPaths {
|
|||||||
@KtorExperimentalLocationsAPI
|
@KtorExperimentalLocationsAPI
|
||||||
object WorkgroupsMembersPaths {
|
object WorkgroupsMembersPaths {
|
||||||
@Location("/workgroups/{workgroup}/members")
|
@Location("/workgroups/{workgroup}/members")
|
||||||
class WorkgroupsMembersRequest(val workgroup: WorkgroupEntity) : RequestBuilder<List<CitizenRef>> {
|
class WorkgroupsMembersRequest(val workgroup: WorkgroupEntity) {
|
||||||
class Content : MutableList<Content.Item> by mutableListOf() {
|
class Body : MutableList<Body.Item> by mutableListOf() {
|
||||||
class Item(val id: String)
|
class Item(id: String) {
|
||||||
|
val id = id.toUUID()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getContent(call: ApplicationCall): List<CitizenRef> {
|
suspend fun getMembers(call: ApplicationCall): List<CitizenRef> = call.receive<Body>().map {
|
||||||
return call.receive<Content>().map {
|
CitizenRef(it.id)
|
||||||
CitizenRef(it.id.toUUID())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,7 +125,7 @@ fun Route.workgroup(repo: WorkgroupRepository) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
post<WorkgroupsPaths.PostWorkgroupRequest> {
|
post<WorkgroupsPaths.PostWorkgroupRequest> {
|
||||||
call.getContent(it)
|
it.getNewWorkgroup(call)
|
||||||
.let { workgroup ->
|
.let { workgroup ->
|
||||||
assertCan(CREATE, workgroup)
|
assertCan(CREATE, workgroup)
|
||||||
repo.upsert(workgroup)
|
repo.upsert(workgroup)
|
||||||
@@ -148,13 +135,12 @@ fun Route.workgroup(repo: WorkgroupRepository) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
put<WorkgroupsPaths.PutWorkgroupRequest> {
|
put<WorkgroupsPaths.PutWorkgroupRequest> {
|
||||||
call.getContent(it)
|
it.updateWorkgroup(call).let { workgroup ->
|
||||||
.let { workgroup ->
|
assertCan(UPDATE, workgroup)
|
||||||
assertCan(UPDATE, workgroup)
|
repo.upsert(workgroup as WorkgroupSimple<CitizenRef>)
|
||||||
repo.upsert(workgroup as WorkgroupSimple<CitizenRef>)
|
}.let {
|
||||||
}.let {
|
call.respond(HttpStatusCode.OK, it)
|
||||||
call.respond(HttpStatusCode.OK, it)
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete<WorkgroupsPaths.DeleteWorkgroupRequest> {
|
delete<WorkgroupsPaths.DeleteWorkgroupRequest> {
|
||||||
@@ -165,7 +151,7 @@ fun Route.workgroup(repo: WorkgroupRepository) {
|
|||||||
|
|
||||||
/* Add members to workgroup */
|
/* Add members to workgroup */
|
||||||
post<WorkgroupsMembersPaths.WorkgroupsMembersRequest> {
|
post<WorkgroupsMembersPaths.WorkgroupsMembersRequest> {
|
||||||
call.getContent(it)
|
it.getMembers(call)
|
||||||
.let { members ->
|
.let { members ->
|
||||||
assertCan(ADD_MEMBERS, it.workgroup)
|
assertCan(ADD_MEMBERS, it.workgroup)
|
||||||
repo.addMembers(it.workgroup, members)
|
repo.addMembers(it.workgroup, members)
|
||||||
@@ -176,7 +162,7 @@ fun Route.workgroup(repo: WorkgroupRepository) {
|
|||||||
|
|
||||||
/* Delete members of workgroup */
|
/* Delete members of workgroup */
|
||||||
delete<WorkgroupsMembersPaths.WorkgroupsMembersRequest> {
|
delete<WorkgroupsMembersPaths.WorkgroupsMembersRequest> {
|
||||||
call.getContent(it)
|
it.getMembers(call)
|
||||||
.let { members ->
|
.let { members ->
|
||||||
assertCan(REMOVE_MEMBERS, it.workgroup)
|
assertCan(REMOVE_MEMBERS, it.workgroup)
|
||||||
repo.removeMembers(it.workgroup, members)
|
repo.removeMembers(it.workgroup, members)
|
||||||
@@ -187,7 +173,7 @@ fun Route.workgroup(repo: WorkgroupRepository) {
|
|||||||
|
|
||||||
/* Update members of workgroup */
|
/* Update members of workgroup */
|
||||||
put<WorkgroupsMembersPaths.WorkgroupsMembersRequest> {
|
put<WorkgroupsMembersPaths.WorkgroupsMembersRequest> {
|
||||||
call.getContent(it)
|
it.getMembers(call)
|
||||||
.let { members ->
|
.let { members ->
|
||||||
assertCan(UPDATE_MEMBERS, it.workgroup)
|
assertCan(UPDATE_MEMBERS, it.workgroup)
|
||||||
repo.updateMembers(it.workgroup, members)
|
repo.updateMembers(it.workgroup, members)
|
||||||
|
|||||||
Reference in New Issue
Block a user