Implement comment constitution
fix bugs
This commit is contained in:
@@ -12,11 +12,7 @@ import fr.dcproject.entity.Citizen
|
|||||||
import fr.dcproject.entity.Constitution
|
import fr.dcproject.entity.Constitution
|
||||||
import fr.dcproject.entity.User
|
import fr.dcproject.entity.User
|
||||||
import fr.dcproject.routes.*
|
import fr.dcproject.routes.*
|
||||||
import fr.dcproject.security.voter.ArticleVoter
|
import fr.dcproject.security.voter.*
|
||||||
import fr.dcproject.security.voter.AuthorizationVoter
|
|
||||||
import fr.dcproject.security.voter.CitizenVoter
|
|
||||||
import fr.dcproject.security.voter.CommentVoter
|
|
||||||
import fr.postgresjson.migration.Migrations
|
|
||||||
import io.ktor.application.Application
|
import io.ktor.application.Application
|
||||||
import io.ktor.application.ApplicationCall
|
import io.ktor.application.ApplicationCall
|
||||||
import io.ktor.application.call
|
import io.ktor.application.call
|
||||||
@@ -40,7 +36,6 @@ import java.util.*
|
|||||||
import java.util.concurrent.CompletionException
|
import java.util.concurrent.CompletionException
|
||||||
import fr.dcproject.repository.Article as RepositoryArticle
|
import fr.dcproject.repository.Article as RepositoryArticle
|
||||||
import fr.dcproject.repository.Citizen as RepositoryCitizen
|
import fr.dcproject.repository.Citizen as RepositoryCitizen
|
||||||
import fr.dcproject.repository.CommentGeneric as CommentGenericRepository
|
|
||||||
import fr.dcproject.repository.Constitution as RepositoryConstitution
|
import fr.dcproject.repository.Constitution as RepositoryConstitution
|
||||||
import fr.dcproject.repository.User as UserRepository
|
import fr.dcproject.repository.User as UserRepository
|
||||||
|
|
||||||
@@ -92,14 +87,6 @@ fun Application.module() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
convert<CommentEntityGeneric> {
|
|
||||||
decode { values, _ ->
|
|
||||||
val id = values.singleOrNull()?.let { UUID.fromString(it) }
|
|
||||||
?: throw InternalError("Cannot convert $values to UUID")
|
|
||||||
get<CommentGenericRepository>().findById(id) ?: throw InternalError("Comment $values not found")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
convert<Citizen> {
|
convert<Citizen> {
|
||||||
decode { values, _ ->
|
decode { values, _ ->
|
||||||
val id = values.singleOrNull()?.let { UUID.fromString(it) }
|
val id = values.singleOrNull()?.let { UUID.fromString(it) }
|
||||||
@@ -115,6 +102,7 @@ fun Application.module() {
|
|||||||
install(AuthorizationVoter) {
|
install(AuthorizationVoter) {
|
||||||
voters = mutableListOf(
|
voters = mutableListOf(
|
||||||
ArticleVoter(),
|
ArticleVoter(),
|
||||||
|
ConstitutionVoter(),
|
||||||
CitizenVoter(),
|
CitizenVoter(),
|
||||||
CommentVoter()
|
CommentVoter()
|
||||||
)
|
)
|
||||||
@@ -166,6 +154,7 @@ fun Application.module() {
|
|||||||
followConstitution(get())
|
followConstitution(get())
|
||||||
comment(get())
|
comment(get())
|
||||||
commentArticle(get())
|
commentArticle(get())
|
||||||
|
commentConstitution(get())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import org.koin.dsl.module
|
|||||||
import fr.dcproject.repository.Article as ArticleRepository
|
import fr.dcproject.repository.Article as ArticleRepository
|
||||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
import fr.dcproject.repository.Citizen as CitizenRepository
|
||||||
import fr.dcproject.repository.CommentArticle as CommentArticleRepository
|
import fr.dcproject.repository.CommentArticle as CommentArticleRepository
|
||||||
|
import fr.dcproject.repository.CommentConstitution as CommentConstitutionRepository
|
||||||
import fr.dcproject.repository.CommentGeneric as CommentGenericRepository
|
import fr.dcproject.repository.CommentGeneric as CommentGenericRepository
|
||||||
import fr.dcproject.repository.Constitution as ConstitutionRepository
|
import fr.dcproject.repository.Constitution as ConstitutionRepository
|
||||||
import fr.dcproject.repository.FollowArticle as FollowArticleRepository
|
import fr.dcproject.repository.FollowArticle as FollowArticleRepository
|
||||||
@@ -37,8 +38,7 @@ val Module = module {
|
|||||||
single { FollowConstitutionRepository(get()) }
|
single { FollowConstitutionRepository(get()) }
|
||||||
single { CommentGenericRepository(get()) }
|
single { CommentGenericRepository(get()) }
|
||||||
single { CommentArticleRepository(get()) }
|
single { CommentArticleRepository(get()) }
|
||||||
// TODO implment constitution
|
single { CommentConstitutionRepository(get()) }
|
||||||
// single { CommentConstitutionRepository(get()) }
|
|
||||||
|
|
||||||
single { Migrations(connection = get(), directory = config.sqlFiles) }
|
single { Migrations(connection = get(), directory = config.sqlFiles) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ class Constitution(
|
|||||||
id: UUID = UUID.randomUUID(),
|
id: UUID = UUID.randomUUID(),
|
||||||
var title: String?,
|
var title: String?,
|
||||||
var annonymous: Boolean?,
|
var annonymous: Boolean?,
|
||||||
var titles: List<Title>,
|
var titles: List<Title> = listOf(),
|
||||||
createdBy: Citizen?
|
createdBy: Citizen?
|
||||||
): UuidEntity(id),
|
): UuidEntity(id),
|
||||||
EntityVersioning<UUID, Int> by UuidEntityVersioning(),
|
EntityVersioning<UUID, Int> by UuidEntityVersioning(),
|
||||||
|
|||||||
@@ -14,11 +14,7 @@ import fr.dcproject.entity.Constitution as ConstitutionEntity
|
|||||||
abstract class Comment <T: UuidEntity>(override var requester: Requester): RepositoryI<CommentEntity<T>> {
|
abstract class Comment <T: UuidEntity>(override var requester: Requester): RepositoryI<CommentEntity<T>> {
|
||||||
override val entityName = CommentEntity::class as KClass<CommentEntity<T>>
|
override val entityName = CommentEntity::class as KClass<CommentEntity<T>>
|
||||||
|
|
||||||
open fun findById(id: UUID): CommentEntity<ArticleEntity>? {
|
abstract fun findById(id: UUID): CommentEntity<T>?
|
||||||
return requester
|
|
||||||
.getFunction("find_comment_by_id")
|
|
||||||
.selectOne(mapOf("id" to id))
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract fun findByCitizen(
|
abstract fun findByCitizen(
|
||||||
citizen: CitizenEntity,
|
citizen: CitizenEntity,
|
||||||
@@ -81,23 +77,29 @@ abstract class Comment <T: UuidEntity>(override var requester: Requester): Repos
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun edit(comment: CommentEntity<T>) {
|
fun edit(comment: CommentEntity<T>) {
|
||||||
val reference = comment.target::class.simpleName!!.toLowerCase()
|
|
||||||
requester
|
requester
|
||||||
.getFunction("edit_comment")
|
.getFunction("edit_comment")
|
||||||
.sendQuery(
|
.sendQuery(
|
||||||
"reference" to reference,
|
|
||||||
"id" to comment.id,
|
"id" to comment.id,
|
||||||
"content" to comment.content
|
"content" to comment.content
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CommentGeneric (requester: Requester): Comment<UuidEntity>(requester) {
|
class GenericTargetEntity(id: UUID = UUID.randomUUID()): UuidEntity(id)
|
||||||
|
|
||||||
|
class CommentGeneric (requester: Requester): Comment<GenericTargetEntity>(requester) {
|
||||||
|
override fun findById(id: UUID): CommentEntity<GenericTargetEntity>? {
|
||||||
|
return requester
|
||||||
|
.getFunction("find_comment_by_id")
|
||||||
|
.selectOne(mapOf("id" to id))
|
||||||
|
}
|
||||||
|
|
||||||
override fun findByCitizen(
|
override fun findByCitizen(
|
||||||
citizen: CitizenEntity,
|
citizen: CitizenEntity,
|
||||||
page: Int,
|
page: Int,
|
||||||
limit: Int
|
limit: Int
|
||||||
): Paginated<CommentEntity<UuidEntity>> {
|
): Paginated<CommentEntity<GenericTargetEntity>> {
|
||||||
return requester.run {
|
return requester.run {
|
||||||
getFunction("find_comments_by_citizen")
|
getFunction("find_comments_by_citizen")
|
||||||
.select(page, limit,
|
.select(page, limit,
|
||||||
@@ -108,6 +110,12 @@ class CommentGeneric (requester: Requester): Comment<UuidEntity>(requester) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CommentArticle (requester: Requester): Comment<ArticleEntity>(requester) {
|
class CommentArticle (requester: Requester): Comment<ArticleEntity>(requester) {
|
||||||
|
override fun findById(id: UUID): CommentEntity<ArticleEntity>? {
|
||||||
|
return requester
|
||||||
|
.getFunction("find_comment_by_id")
|
||||||
|
.selectOne(mapOf("id" to id))
|
||||||
|
}
|
||||||
|
|
||||||
override fun findByCitizen(
|
override fun findByCitizen(
|
||||||
citizen: CitizenEntity,
|
citizen: CitizenEntity,
|
||||||
page: Int,
|
page: Int,
|
||||||
@@ -125,6 +133,12 @@ class CommentArticle (requester: Requester): Comment<ArticleEntity>(requester) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CommentConstitution (requester: Requester): Comment<ConstitutionEntity>(requester) {
|
class CommentConstitution (requester: Requester): Comment<ConstitutionEntity>(requester) {
|
||||||
|
override fun findById(id: UUID): CommentEntity<ConstitutionEntity>? {
|
||||||
|
return requester
|
||||||
|
.getFunction("find_comment_by_id")
|
||||||
|
.selectOne(mapOf("id" to id))
|
||||||
|
}
|
||||||
|
|
||||||
override fun findByCitizen(
|
override fun findByCitizen(
|
||||||
citizen: CitizenEntity,
|
citizen: CitizenEntity,
|
||||||
page: Int,
|
page: Int,
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ class Constitution(override var requester: Requester) : RepositoryI<Constitution
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun upsert(article: ConstitutionEntity): ConstitutionEntity? {
|
fun upsert(constitution: ConstitutionEntity): ConstitutionEntity? {
|
||||||
return requester
|
return requester
|
||||||
.getFunction("upsert_constitution")
|
.getFunction("upsert_constitution")
|
||||||
.selectOne("resource" to article)
|
.selectOne("resource" to constitution)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package fr.dcproject.routes
|
|||||||
import fr.dcproject.security.voter.CommentVoter.Action.UPDATE
|
import fr.dcproject.security.voter.CommentVoter.Action.UPDATE
|
||||||
import fr.dcproject.security.voter.CommentVoter.Action.VIEW
|
import fr.dcproject.security.voter.CommentVoter.Action.VIEW
|
||||||
import fr.dcproject.security.voter.assertCan
|
import fr.dcproject.security.voter.assertCan
|
||||||
import fr.postgresjson.entity.UuidEntity
|
|
||||||
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
|
||||||
@@ -14,10 +13,8 @@ import io.ktor.request.receiveText
|
|||||||
import io.ktor.response.respond
|
import io.ktor.response.respond
|
||||||
import io.ktor.routing.Route
|
import io.ktor.routing.Route
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import fr.dcproject.entity.Comment as CommentEntity
|
|
||||||
import fr.dcproject.repository.CommentGeneric as CommentRepository
|
import fr.dcproject.repository.CommentGeneric as CommentRepository
|
||||||
|
|
||||||
typealias CommentEntityGeneric = CommentEntity<UuidEntity>
|
|
||||||
@KtorExperimentalLocationsAPI
|
@KtorExperimentalLocationsAPI
|
||||||
object CommentPaths {
|
object CommentPaths {
|
||||||
// TODO: change UUID by entity converter
|
// TODO: change UUID by entity converter
|
||||||
@@ -38,7 +35,7 @@ fun Route.comment(repo: CommentRepository) {
|
|||||||
assertCan(UPDATE,comment)
|
assertCan(UPDATE,comment)
|
||||||
|
|
||||||
comment.content = call.receiveText()
|
comment.content = call.receiveText()
|
||||||
repo.edit(comment as CommentEntity<UuidEntity>)
|
repo.edit(comment)
|
||||||
|
|
||||||
call.respond(HttpStatusCode.OK, comment)
|
call.respond(HttpStatusCode.OK, comment)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import io.ktor.locations.KtorExperimentalLocationsAPI
|
|||||||
import io.ktor.locations.Location
|
import io.ktor.locations.Location
|
||||||
import io.ktor.locations.get
|
import io.ktor.locations.get
|
||||||
import io.ktor.locations.post
|
import io.ktor.locations.post
|
||||||
import io.ktor.request.receive
|
import io.ktor.request.receiveText
|
||||||
import io.ktor.response.respond
|
import io.ktor.response.respond
|
||||||
import io.ktor.routing.Route
|
import io.ktor.routing.Route
|
||||||
import fr.dcproject.entity.Article as ArticleEntity
|
import fr.dcproject.entity.Article as ArticleEntity
|
||||||
@@ -37,7 +37,7 @@ fun Route.commentArticle(repo: CommentArticleRepository) {
|
|||||||
post<CommentArticlePaths.ArticleCommentRequest> {
|
post<CommentArticlePaths.ArticleCommentRequest> {
|
||||||
assertCan(CREATE, it.article)
|
assertCan(CREATE, it.article)
|
||||||
|
|
||||||
val content = call.receive<String>()
|
val content = call.receiveText()
|
||||||
val comment = CommentEntity(
|
val comment = CommentEntity(
|
||||||
target = it.article,
|
target = it.article,
|
||||||
createdBy = citizen,
|
createdBy = citizen,
|
||||||
|
|||||||
55
src/main/kotlin/fr/dcproject/routes/CommentConstitution.kt
Normal file
55
src/main/kotlin/fr/dcproject/routes/CommentConstitution.kt
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package fr.dcproject.routes
|
||||||
|
|
||||||
|
import fr.dcproject.citizen
|
||||||
|
import fr.dcproject.entity.Citizen
|
||||||
|
import fr.dcproject.security.voter.CommentVoter.Action.CREATE
|
||||||
|
import fr.dcproject.security.voter.CommentVoter.Action.VIEW
|
||||||
|
import fr.dcproject.security.voter.assertCan
|
||||||
|
import io.ktor.application.call
|
||||||
|
import io.ktor.http.HttpStatusCode
|
||||||
|
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||||
|
import io.ktor.locations.Location
|
||||||
|
import io.ktor.locations.get
|
||||||
|
import io.ktor.locations.post
|
||||||
|
import io.ktor.request.receiveText
|
||||||
|
import io.ktor.response.respond
|
||||||
|
import io.ktor.routing.Route
|
||||||
|
import fr.dcproject.entity.Comment as CommentEntity
|
||||||
|
import fr.dcproject.entity.Constitution as ConstitutionEntity
|
||||||
|
import fr.dcproject.repository.CommentConstitution as CommentConstitutionRepository
|
||||||
|
|
||||||
|
@KtorExperimentalLocationsAPI
|
||||||
|
object CommentConstitutionPaths {
|
||||||
|
@Location("/constitutions/{constitution}/comments") class ConstitutionCommentRequest(val constitution: ConstitutionEntity)
|
||||||
|
@Location("/citizens/{citizen}/comments/constitutions") class CitizenCommentConstitutionRequest(val citizen: Citizen)
|
||||||
|
}
|
||||||
|
|
||||||
|
@KtorExperimentalLocationsAPI
|
||||||
|
fun Route.commentConstitution(repo: CommentConstitutionRepository) {
|
||||||
|
get<CommentConstitutionPaths.ConstitutionCommentRequest> {
|
||||||
|
assertCan(VIEW, it.constitution)
|
||||||
|
|
||||||
|
val comment = repo.findByTarget(it.constitution)
|
||||||
|
|
||||||
|
call.respond(HttpStatusCode.OK, comment)
|
||||||
|
}
|
||||||
|
|
||||||
|
post<CommentConstitutionPaths.ConstitutionCommentRequest> {
|
||||||
|
assertCan(CREATE, it.constitution)
|
||||||
|
|
||||||
|
val content = call.receiveText()
|
||||||
|
val comment = CommentEntity(
|
||||||
|
target = it.constitution,
|
||||||
|
createdBy = citizen,
|
||||||
|
content = content
|
||||||
|
)
|
||||||
|
repo.comment(comment)
|
||||||
|
|
||||||
|
call.respond(HttpStatusCode.Created, comment)
|
||||||
|
}
|
||||||
|
|
||||||
|
get<CommentConstitutionPaths.CitizenCommentConstitutionRequest> {
|
||||||
|
val comments = repo.findByCitizen(it.citizen)
|
||||||
|
call.respond(comments)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package fr.dcproject.security.voter
|
||||||
|
|
||||||
|
import fr.dcproject.entity.Constitution
|
||||||
|
import fr.dcproject.entity.User
|
||||||
|
import io.ktor.application.ApplicationCall
|
||||||
|
|
||||||
|
class ConstitutionVoter: Voter {
|
||||||
|
enum class Action: ActionI {
|
||||||
|
CREATE,
|
||||||
|
UPDATE,
|
||||||
|
VIEW,
|
||||||
|
DELETE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
||||||
|
return (action is Action || action is CommentVoter.Action) && subject is Constitution?
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
|
||||||
|
val user = call.user
|
||||||
|
if (action == Action.CREATE && user != null) {
|
||||||
|
return Vote.GRANTED
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == Action.VIEW) {
|
||||||
|
return Vote.GRANTED
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == CommentVoter.Action.CREATE) {
|
||||||
|
return Vote.GRANTED
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == CommentVoter.Action.VIEW) {
|
||||||
|
return Vote.GRANTED
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == Action.DELETE && user is User && subject is Constitution && subject.createdBy?.userId == user.id) {
|
||||||
|
return Vote.GRANTED
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == Action.UPDATE && user is User && subject is Constitution && subject.createdBy?.userId == user.id) {
|
||||||
|
return Vote.GRANTED
|
||||||
|
}
|
||||||
|
|
||||||
|
return Vote.ABSTAIN
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,16 +3,28 @@ create or replace function upsert_article(inout resource json)
|
|||||||
$$
|
$$
|
||||||
declare
|
declare
|
||||||
new_id uuid;
|
new_id uuid;
|
||||||
|
_id_exist boolean;
|
||||||
begin
|
begin
|
||||||
insert into article (version_id, created_by_id, title, annonymous, content, description, tags)
|
-- check if version id already exist
|
||||||
|
select count(*) >= 1
|
||||||
|
into _id_exist
|
||||||
|
from article
|
||||||
|
where (resource->>'id')::uuid is not null
|
||||||
|
and id = (resource->>'id')::uuid
|
||||||
|
-- and draft = false
|
||||||
|
;
|
||||||
|
|
||||||
|
insert into article (id, version_id, created_by_id, title, annonymous, content, description, tags)
|
||||||
select
|
select
|
||||||
coalesce(version_id, uuid_generate_v4()),
|
case when _id_exist then uuid_generate_v4()
|
||||||
(resource#>>'{created_by, id}')::uuid,
|
else coalesce(id, uuid_generate_v4()) end,
|
||||||
title,
|
coalesce(version_id, uuid_generate_v4()),
|
||||||
annonymous,
|
(resource#>>'{created_by, id}')::uuid,
|
||||||
content,
|
title,
|
||||||
description,
|
annonymous,
|
||||||
tags
|
content,
|
||||||
|
description,
|
||||||
|
tags
|
||||||
from json_populate_record(null::article, resource)
|
from json_populate_record(null::article, resource)
|
||||||
returning id into new_id;
|
returning id into new_id;
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,13 @@
|
|||||||
create or replace function edit_comment(reference regclass, _id uuid, _content text) returns void
|
create or replace function edit_comment(_id uuid, _content text) returns void
|
||||||
language plpgsql as
|
language plpgsql as
|
||||||
$$
|
$$
|
||||||
begin
|
begin
|
||||||
if reference = 'article'::regclass then
|
update comment c set
|
||||||
update comment_on_article c set
|
|
||||||
"content" = _content
|
"content" = _content
|
||||||
where c.id = _id;
|
where c.id = _id;
|
||||||
elseif reference = 'constitution'::regclass then
|
|
||||||
update comment_on_constitution c set
|
|
||||||
"content" = _content
|
|
||||||
where c.id = _id;
|
|
||||||
end if;
|
|
||||||
end;
|
end;
|
||||||
$$;
|
$$;
|
||||||
|
|
||||||
-- drop function if exists edit_comment(regclass, uuid, text);
|
-- drop function if exists edit_comment(regclass, uuid, text);
|
||||||
|
|
||||||
|
-- select edit_comment('b0422e48-687f-bea7-b45f-b6b301246e97', 'plop4')
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
create or replace function find_comments_article_by_citizen(
|
|
||||||
_created_by_id uuid,
|
|
||||||
"limit" int default 50,
|
|
||||||
"offset" int default 0,
|
|
||||||
out resource json,
|
|
||||||
out total int
|
|
||||||
) language plpgsql as
|
|
||||||
$$
|
|
||||||
begin
|
|
||||||
select json_agg(t), (select count(id) from comment where target_reference = 'article'::regclass)
|
|
||||||
into resource, total
|
|
||||||
from (
|
|
||||||
select
|
|
||||||
com.*,
|
|
||||||
find_article_by_id(com.target_id) as target,
|
|
||||||
find_citizen_by_id(com.created_by_id) as created_by
|
|
||||||
from comment as com
|
|
||||||
where created_by_id = _created_by_id
|
|
||||||
and target_reference = 'article'::regclass
|
|
||||||
order by created_at desc,
|
|
||||||
com.created_at desc
|
|
||||||
limit "limit" offset "offset"
|
|
||||||
) as t;
|
|
||||||
end;
|
|
||||||
$$;
|
|
||||||
|
|
||||||
-- drop function if exists find_comments_article_by_citizen(uuid, int, int);
|
|
||||||
@@ -6,9 +6,23 @@ declare
|
|||||||
_title json;
|
_title json;
|
||||||
_citizen_id uuid = (resource#>>'{created_by, id}')::uuid;
|
_citizen_id uuid = (resource#>>'{created_by, id}')::uuid;
|
||||||
new_id uuid;
|
new_id uuid;
|
||||||
|
_id_exist boolean;
|
||||||
begin
|
begin
|
||||||
insert into constitution (version_id, created_by_id, title, annonymous)
|
-- check if version id already exist
|
||||||
|
select count(*) >= 1
|
||||||
|
into _id_exist
|
||||||
|
from constitution
|
||||||
|
where (resource->>'id')::uuid is not null
|
||||||
|
and id = (resource->>'id')::uuid
|
||||||
|
-- and draft = false
|
||||||
|
;
|
||||||
|
|
||||||
|
raise notice '%', _id_exist;
|
||||||
|
|
||||||
|
insert into constitution (id, version_id, created_by_id, title, annonymous)
|
||||||
select
|
select
|
||||||
|
case when _id_exist then uuid_generate_v4()
|
||||||
|
else coalesce(id, uuid_generate_v4()) end,
|
||||||
version_id,
|
version_id,
|
||||||
_citizen_id,
|
_citizen_id,
|
||||||
title,
|
title,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ begin
|
|||||||
when 'article'::regclass then
|
when 'article'::regclass then
|
||||||
find_article_by_id(_id)
|
find_article_by_id(_id)
|
||||||
when 'constitution'::regclass then
|
when 'constitution'::regclass then
|
||||||
find_article_by_id(_id)
|
find_constitution_by_id(_id)
|
||||||
else
|
else
|
||||||
json_build_object('id', _id)
|
json_build_object('id', _id)
|
||||||
end
|
end
|
||||||
@@ -19,3 +19,5 @@ end;
|
|||||||
$$;
|
$$;
|
||||||
|
|
||||||
-- drop function if exists find_reference_by_id(uuid, regclass, out json);
|
-- drop function if exists find_reference_by_id(uuid, regclass, out json);
|
||||||
|
|
||||||
|
-- select find_reference_by_id('8944221c-3766-f952-7064-9f229c288049'::uuid, 'constitution'::regclass)
|
||||||
62
src/test/kotlin/feature/ConstitutionSteps.kt
Normal file
62
src/test/kotlin/feature/ConstitutionSteps.kt
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package feature
|
||||||
|
|
||||||
|
import fr.dcproject.entity.Citizen
|
||||||
|
import io.cucumber.java8.En
|
||||||
|
import org.joda.time.DateTime
|
||||||
|
import org.koin.test.KoinTest
|
||||||
|
import org.koin.test.get
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.CompletionException
|
||||||
|
import fr.dcproject.entity.Constitution as ConstitutionEntity
|
||||||
|
import fr.dcproject.entity.Constitution.Title as TitleEntity
|
||||||
|
import fr.dcproject.entity.User as UserEntity
|
||||||
|
import fr.dcproject.repository.Citizen as CitizenRepository
|
||||||
|
import fr.dcproject.repository.Constitution as ConstitutionRepository
|
||||||
|
|
||||||
|
class ConstitutionSteps: En, KoinTest {
|
||||||
|
init {
|
||||||
|
Given("I have constitution with id {string}") { id: String ->
|
||||||
|
var citizen = Citizen(
|
||||||
|
name = Citizen.Name("John", "Doe"),
|
||||||
|
birthday = DateTime.now(),
|
||||||
|
user = UserEntity(username = "john-doe", plainPassword = "azerty")
|
||||||
|
)
|
||||||
|
|
||||||
|
try {
|
||||||
|
get<CitizenRepository>().insertWithUser(citizen)
|
||||||
|
} catch (e: CompletionException) {
|
||||||
|
citizen = get<CitizenRepository>().findByUsername("john-doe")!!
|
||||||
|
}
|
||||||
|
|
||||||
|
val title1 = TitleEntity(
|
||||||
|
name = "My Title"
|
||||||
|
)
|
||||||
|
|
||||||
|
val constitution = ConstitutionEntity(
|
||||||
|
id = UUID.fromString(id),
|
||||||
|
title = "hello",
|
||||||
|
titles = listOf(title1),
|
||||||
|
createdBy = citizen,
|
||||||
|
annonymous = false
|
||||||
|
)
|
||||||
|
get<ConstitutionRepository>().upsert(constitution)
|
||||||
|
}
|
||||||
|
|
||||||
|
Given("I have constitution with id {string} created by {string}") { id: String, username: String ->
|
||||||
|
val citizen = get<CitizenRepository>().findByUsername(username)!!
|
||||||
|
|
||||||
|
val title1 = TitleEntity(
|
||||||
|
name = "My Title"
|
||||||
|
)
|
||||||
|
|
||||||
|
val constitution = ConstitutionEntity(
|
||||||
|
id = UUID.fromString(id),
|
||||||
|
title = "hello",
|
||||||
|
titles = listOf(title1),
|
||||||
|
createdBy = citizen,
|
||||||
|
annonymous = false
|
||||||
|
)
|
||||||
|
get<ConstitutionRepository>().upsert(constitution)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
Feature: comment Article and Constitution
|
Feature: comment Article
|
||||||
|
|
||||||
# Article
|
|
||||||
Scenario: The route for comment article must response a 201 and return object
|
Scenario: The route for comment article must response a 201 and return object
|
||||||
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||||
And I have article with id "9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
And I have article with id "9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
||||||
@@ -34,7 +33,3 @@ Feature: comment Article and Constitution
|
|||||||
Then the response status code should be 200
|
Then the response status code should be 200
|
||||||
And the JSON should contain:
|
And the JSON should contain:
|
||||||
| content | Hello boy |
|
| content | Hello boy |
|
||||||
|
|
||||||
|
|
||||||
# Constitution
|
|
||||||
# TODO
|
|
||||||
35
src/test/resources/feature/commentConstitution.feature
Normal file
35
src/test/resources/feature/commentConstitution.feature
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
Feature: comment Constitution
|
||||||
|
|
||||||
|
Scenario: The route for comment constitution must response a 201 and return object
|
||||||
|
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||||
|
And I have constitution with id "9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
||||||
|
When I send a POST request to "/constitutions/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/comments" with body:
|
||||||
|
"""
|
||||||
|
Hello mister
|
||||||
|
"""
|
||||||
|
Then the response status code should be 201
|
||||||
|
|
||||||
|
Scenario: The route for get comments of constitutions for the current citizen must response a 200 and return objects
|
||||||
|
Given I have citizen John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
|
||||||
|
And I have constitution with id "9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
|
||||||
|
When I send a GET request to "/citizens/64b7b379-2298-43ec-b428-ba134930cabd/comments/constitutions"
|
||||||
|
Then the response status code should be 200
|
||||||
|
And the response should contain object:
|
||||||
|
| current_page | 1 |
|
||||||
|
| limit | 50 |
|
||||||
|
|
||||||
|
Scenario: The route for edit comment must response a 200 and return object
|
||||||
|
Given I am authenticated as username 3 with id "92877af7-0a45-fd6a-2ed7-fe81e1236b78"
|
||||||
|
When I send a PUT request to "/comments/b0422e48-687f-bea7-b45f-b6b301246e97" with body:
|
||||||
|
"""
|
||||||
|
Hello boy
|
||||||
|
"""
|
||||||
|
Then the response status code should be 200
|
||||||
|
And the JSON should contain:
|
||||||
|
| content | Hello boy |
|
||||||
|
|
||||||
|
Scenario: The route for get comment must response a 200 and return object
|
||||||
|
When I send a GET request to "/comments/b0422e48-687f-bea7-b45f-b6b301246e97"
|
||||||
|
Then the response status code should be 200
|
||||||
|
And the JSON should contain:
|
||||||
|
| content | Hello boy |
|
||||||
Reference in New Issue
Block a user