Create OpinionChoice
This commit is contained in:
@@ -39,6 +39,7 @@ 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.Constitution as RepositoryConstitution
|
import fr.dcproject.repository.Constitution as RepositoryConstitution
|
||||||
|
import fr.dcproject.repository.OpinionChoice as OpinionChoiceRepository
|
||||||
import fr.dcproject.repository.User as UserRepository
|
import fr.dcproject.repository.User as UserRepository
|
||||||
|
|
||||||
fun main(args: Array<String>): Unit = io.ktor.server.jetty.EngineMain.main(args)
|
fun main(args: Array<String>): Unit = io.ktor.server.jetty.EngineMain.main(args)
|
||||||
@@ -121,6 +122,14 @@ fun Application.module(env: Env = PROD) {
|
|||||||
get<RepositoryCitizen>().findById(id, true) ?: throw NotFoundException("Citizen $values not found")
|
get<RepositoryCitizen>().findById(id, true) ?: throw NotFoundException("Citizen $values not found")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
convert<OpinionChoice> {
|
||||||
|
decode { values, _ ->
|
||||||
|
val id = values.singleOrNull()?.let { UUID.fromString(it) }
|
||||||
|
?: throw InternalError("Cannot convert $values to UUID")
|
||||||
|
get<OpinionChoiceRepository>().findOpinionChoiceById(id) ?: throw NotFoundException("OpinionChoice $values not found")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
install(Locations) {
|
install(Locations) {
|
||||||
@@ -133,7 +142,8 @@ fun Application.module(env: Env = PROD) {
|
|||||||
CitizenVoter(),
|
CitizenVoter(),
|
||||||
CommentVoter(),
|
CommentVoter(),
|
||||||
VoteVoter(),
|
VoteVoter(),
|
||||||
FollowVoter()
|
FollowVoter(),
|
||||||
|
OpinionChoiceVoter()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,6 +196,7 @@ fun Application.module(env: Env = PROD) {
|
|||||||
commentConstitution(get())
|
commentConstitution(get())
|
||||||
voteArticle(get(), get(), get())
|
voteArticle(get(), get(), get())
|
||||||
voteConstitution(get())
|
voteConstitution(get())
|
||||||
|
opinionChoice(get())
|
||||||
definition()
|
definition()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ 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
|
||||||
import fr.dcproject.repository.FollowConstitution as FollowConstitutionRepository
|
import fr.dcproject.repository.FollowConstitution as FollowConstitutionRepository
|
||||||
|
import fr.dcproject.repository.OpinionChoice as OpinionChoiceRepository
|
||||||
import fr.dcproject.repository.User as UserRepository
|
import fr.dcproject.repository.User as UserRepository
|
||||||
import fr.dcproject.repository.VoteArticle as VoteArticleRepository
|
import fr.dcproject.repository.VoteArticle as VoteArticleRepository
|
||||||
import fr.dcproject.repository.VoteComment as VoteCommentRepository
|
import fr.dcproject.repository.VoteComment as VoteCommentRepository
|
||||||
@@ -57,6 +58,7 @@ val Module = module {
|
|||||||
single { VoteArticleRepository(get()) }
|
single { VoteArticleRepository(get()) }
|
||||||
single { VoteConstitutionRepository(get()) }
|
single { VoteConstitutionRepository(get()) }
|
||||||
single { VoteCommentRepository(get()) }
|
single { VoteCommentRepository(get()) }
|
||||||
|
single { OpinionChoiceRepository(get()) }
|
||||||
|
|
||||||
single { Migrations(connection = get(), directory = config.sqlFiles) }
|
single { Migrations(connection = get(), directory = config.sqlFiles) }
|
||||||
|
|
||||||
|
|||||||
16
src/main/kotlin/fr/dcproject/entity/OpinionChoice.kt
Normal file
16
src/main/kotlin/fr/dcproject/entity/OpinionChoice.kt
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package fr.dcproject.entity
|
||||||
|
|
||||||
|
import fr.postgresjson.entity.immutable.EntityCreatedAt
|
||||||
|
import fr.postgresjson.entity.immutable.EntityCreatedAtImp
|
||||||
|
import fr.postgresjson.entity.immutable.UuidEntity
|
||||||
|
import fr.postgresjson.entity.mutable.EntityDeletedAt
|
||||||
|
import fr.postgresjson.entity.mutable.EntityDeletedAtImp
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class OpinionChoice(
|
||||||
|
id: UUID,
|
||||||
|
val name: String,
|
||||||
|
val target: List<String>
|
||||||
|
) : UuidEntity(id),
|
||||||
|
EntityCreatedAt by EntityCreatedAtImp(),
|
||||||
|
EntityDeletedAt by EntityDeletedAtImp()
|
||||||
37
src/main/kotlin/fr/dcproject/routes/OpinionChoice.kt
Normal file
37
src/main/kotlin/fr/dcproject/routes/OpinionChoice.kt
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package fr.dcproject.routes
|
||||||
|
|
||||||
|
import fr.dcproject.entity.OpinionChoice
|
||||||
|
import fr.dcproject.security.voter.OpinionVoter.Action.VIEW
|
||||||
|
import fr.dcproject.security.voter.assertCan
|
||||||
|
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.repository.OpinionChoice as OpinionChoiceRepository
|
||||||
|
|
||||||
|
@KtorExperimentalLocationsAPI
|
||||||
|
object OpinionChoicePaths {
|
||||||
|
@Location("/opinions/{opinionChoice}")
|
||||||
|
class OpinionChoiceRequest(val opinionChoice: OpinionChoice)
|
||||||
|
|
||||||
|
@Location("/opinions")
|
||||||
|
class OpinionChoicesRequest(val targets: List<String>)
|
||||||
|
}
|
||||||
|
|
||||||
|
@KtorExperimentalLocationsAPI
|
||||||
|
fun Route.opinionChoice(repo: OpinionChoiceRepository) {
|
||||||
|
get<OpinionChoicePaths.OpinionChoiceRequest> {
|
||||||
|
assertCan(VIEW, it.opinionChoice)
|
||||||
|
|
||||||
|
call.respond(it.opinionChoice)
|
||||||
|
}
|
||||||
|
|
||||||
|
get<OpinionChoicePaths.OpinionChoicesRequest> {
|
||||||
|
val opinions = repo.findOpinionsChoices(it.targets)
|
||||||
|
assertCan(VIEW, opinions)
|
||||||
|
|
||||||
|
call.respond(opinions)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package fr.dcproject.security.voter
|
||||||
|
|
||||||
|
import fr.dcproject.entity.OpinionChoice
|
||||||
|
import io.ktor.application.ApplicationCall
|
||||||
|
|
||||||
|
class OpinionChoiceVoter : Voter {
|
||||||
|
enum class Action : ActionI {
|
||||||
|
VIEW
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
|
||||||
|
return (action is Action)
|
||||||
|
.and(subject is OpinionChoice? || subject is List<*>)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
|
||||||
|
if (action == Action.VIEW) {
|
||||||
|
if (subject is OpinionChoice) {
|
||||||
|
return Vote.GRANTED
|
||||||
|
}
|
||||||
|
if (subject is List<*>) {
|
||||||
|
subject.forEach {
|
||||||
|
if (it !is OpinionChoice) {
|
||||||
|
return Vote.DENIED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Vote.GRANTED
|
||||||
|
}
|
||||||
|
return Vote.DENIED
|
||||||
|
}
|
||||||
|
|
||||||
|
return Vote.ABSTAIN
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
create or replace function find_opinion_choice_by_id(_id uuid, out resource json)
|
||||||
|
language plpgsql as
|
||||||
|
$$
|
||||||
|
begin
|
||||||
|
select to_json(ol) into resource
|
||||||
|
from opinion_list ol
|
||||||
|
where (ol.deleted_at <= now()
|
||||||
|
or ol.deleted_at is null)
|
||||||
|
and (ol.id = _id);
|
||||||
|
end;
|
||||||
|
$$;
|
||||||
|
|
||||||
|
-- drop function if exists find_opinion_choice_by_id();
|
||||||
|
|
||||||
|
-- select find_opinion_choice_by_id('8c6cb3cc-cac5-93ad-312e-6bd87d9916d9');
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
create or replace function find_opinions(out resource json)
|
create or replace function find_opinion_choices(targets text[] default null, out resource json)
|
||||||
language plpgsql as
|
language plpgsql as
|
||||||
$$
|
$$
|
||||||
begin
|
begin
|
||||||
@@ -7,8 +7,10 @@ begin
|
|||||||
from (
|
from (
|
||||||
select ol.*
|
select ol.*
|
||||||
from opinion_list ol
|
from opinion_list ol
|
||||||
where ol.deleted_at <= now()
|
where (ol.deleted_at <= now()
|
||||||
or ol.deleted_at is null
|
or ol.deleted_at is null)
|
||||||
|
and (ol.target is null or array_length(targets) = 0 or ol.target = any(targets))
|
||||||
|
|
||||||
order by ol.name
|
order by ol.name
|
||||||
) t;
|
) t;
|
||||||
end;
|
end;
|
||||||
|
|||||||
@@ -90,8 +90,12 @@ begin
|
|||||||
'The first opinion must have a name';
|
'The first opinion must have a name';
|
||||||
|
|
||||||
assert(
|
assert(
|
||||||
select find_opinions()#>>'{0, name}' = 'Opinion1'
|
select find_opinion_choices()#>>'{0, name}' = 'Opinion1'
|
||||||
), 'find_opinions mst be return all opinions';
|
), 'find_opinion_choices mst be return all opinions';
|
||||||
|
|
||||||
|
assert(
|
||||||
|
select (find_opinion_choice_by_id(opinion1)->>'name') = 'Opinion1'
|
||||||
|
), 'find_opinion_choice_by_id must return the opinion_choice';
|
||||||
|
|
||||||
-- delete vote and context
|
-- delete vote and context
|
||||||
delete from opinion;
|
delete from opinion;
|
||||||
|
|||||||
Reference in New Issue
Block a user