Move vote to component
This commit is contained in:
@@ -9,6 +9,8 @@ import fr.dcproject.component.citizen.CitizenRef
|
||||
import fr.dcproject.component.opinion.entity.Opinionable
|
||||
import fr.dcproject.component.opinion.entity.OpinionableImp
|
||||
import fr.dcproject.component.opinion.entity.Opinions
|
||||
import fr.dcproject.component.vote.entity.Votable
|
||||
import fr.dcproject.component.vote.entity.VotableImp
|
||||
import fr.dcproject.component.workgroup.WorkgroupCart
|
||||
import fr.dcproject.component.workgroup.WorkgroupCartI
|
||||
import fr.dcproject.component.workgroup.WorkgroupRef
|
||||
@@ -19,8 +21,6 @@ import fr.dcproject.entity.TargetI
|
||||
import fr.dcproject.entity.TargetRef
|
||||
import fr.dcproject.entity.VersionableRef
|
||||
import fr.dcproject.entity.VersionableRefImp
|
||||
import fr.dcproject.entity.Votable
|
||||
import fr.dcproject.entity.VotableImp
|
||||
import fr.postgresjson.entity.EntityCreatedAt
|
||||
import fr.postgresjson.entity.EntityCreatedAtImp
|
||||
import fr.postgresjson.entity.EntityDeletedAt
|
||||
|
||||
@@ -7,10 +7,10 @@ import fr.dcproject.component.article.ArticleVoter
|
||||
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.vote.dto.Votable
|
||||
import fr.dcproject.dto.CreatedAt
|
||||
import fr.dcproject.dto.Versionable
|
||||
import fr.dcproject.dto.Viewable
|
||||
import fr.dcproject.dto.Votable
|
||||
import fr.dcproject.voter.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.features.NotFoundException
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package fr.dcproject.component.comment.generic
|
||||
|
||||
import fr.dcproject.component.citizen.CitizenRef
|
||||
import fr.dcproject.component.vote.entity.Votable
|
||||
import fr.dcproject.component.vote.entity.VotableImp
|
||||
import fr.dcproject.entity.EntityI
|
||||
import fr.dcproject.entity.ExtraI
|
||||
import fr.dcproject.entity.HasTarget
|
||||
import fr.dcproject.entity.TargetI
|
||||
import fr.dcproject.entity.TargetRef
|
||||
import fr.dcproject.entity.Votable
|
||||
import fr.dcproject.entity.VotableImp
|
||||
import fr.postgresjson.entity.EntityCreatedAt
|
||||
import fr.postgresjson.entity.EntityCreatedAtImp
|
||||
import fr.postgresjson.entity.EntityCreatedBy
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package fr.dcproject.repository
|
||||
package fr.dcproject.component.opinion
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference
|
||||
import fr.dcproject.component.article.ArticleRef
|
||||
|
||||
@@ -15,7 +15,7 @@ import io.ktor.routing.Route
|
||||
import org.koin.core.KoinComponent
|
||||
import java.util.UUID
|
||||
import fr.dcproject.component.citizen.Citizen as CitizenEntity
|
||||
import fr.dcproject.repository.OpinionRepositoryArticle as OpinionArticleRepository
|
||||
import fr.dcproject.component.opinion.OpinionRepositoryArticle as OpinionArticleRepository
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
object GetCitizenOpinions {
|
||||
|
||||
@@ -13,7 +13,7 @@ import io.ktor.locations.Location
|
||||
import io.ktor.locations.get
|
||||
import io.ktor.response.respond
|
||||
import io.ktor.routing.Route
|
||||
import fr.dcproject.repository.OpinionRepositoryArticle as OpinionArticleRepository
|
||||
import fr.dcproject.component.opinion.OpinionRepositoryArticle as OpinionArticleRepository
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
object GetMyOpinionsArticle {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package fr.dcproject.component.opinion.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.opinion.OpinionChoiceRepository
|
||||
import fr.dcproject.component.opinion.OpinionChoiceVoter
|
||||
import fr.dcproject.voter.assert
|
||||
import io.ktor.application.call
|
||||
@@ -9,7 +10,6 @@ import io.ktor.locations.Location
|
||||
import io.ktor.locations.get
|
||||
import io.ktor.response.respond
|
||||
import io.ktor.routing.Route
|
||||
import fr.dcproject.repository.OpinionChoiceRepository as OpinionChoiceRepository
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
object GetOpinionChoices {
|
||||
|
||||
@@ -17,7 +17,7 @@ import io.ktor.request.receive
|
||||
import io.ktor.response.respond
|
||||
import io.ktor.routing.Route
|
||||
import java.util.UUID
|
||||
import fr.dcproject.repository.OpinionRepositoryArticle as OpinionArticleRepository
|
||||
import fr.dcproject.component.opinion.OpinionRepositoryArticle as OpinionArticleRepository
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
object OpinionArticle {
|
||||
|
||||
132
src/main/kotlin/component/vote/VoteRepositoryAbs.kt
Normal file
132
src/main/kotlin/component/vote/VoteRepositoryAbs.kt
Normal file
@@ -0,0 +1,132 @@
|
||||
package fr.dcproject.component.vote
|
||||
|
||||
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.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
|
||||
import fr.postgresjson.connexion.Requester
|
||||
import fr.postgresjson.repository.RepositoryI
|
||||
import java.util.UUID
|
||||
import fr.dcproject.component.citizen.Citizen as CitizenEntity
|
||||
import fr.dcproject.component.vote.entity.Vote as VoteEntity
|
||||
|
||||
abstract class VoteRepositoryAbs<T : TargetI>(override var requester: Requester) : RepositoryI {
|
||||
fun vote(vote: VoteForUpdateI<T, *>, anonymous: Boolean? = null): VoteAggregation {
|
||||
val author = vote.createdBy
|
||||
return requester
|
||||
.getFunction("vote")
|
||||
.selectOne(
|
||||
"reference" to vote.target.reference,
|
||||
"target_id" to vote.target.id,
|
||||
"note" to vote.note,
|
||||
"created_by_id" to author.id,
|
||||
"anonymous" to anonymous
|
||||
)!!
|
||||
}
|
||||
|
||||
fun findByCitizen(
|
||||
citizenId: UUID,
|
||||
target: String,
|
||||
typeReference: TypeReference<List<VoteEntity<T>>>,
|
||||
page: Int = 1,
|
||||
limit: Int = 50
|
||||
): Paginated<VoteEntity<T>> {
|
||||
return requester.run {
|
||||
getFunction("find_votes_by_citizen")
|
||||
.select(
|
||||
page,
|
||||
limit,
|
||||
typeReference,
|
||||
mapOf(
|
||||
"created_by_id" to citizenId,
|
||||
"reference" to target
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun findCitizenVotesByTargets(
|
||||
citizen: CitizenEntity,
|
||||
targets: List<UUID>
|
||||
): List<VoteEntity<*>> {
|
||||
val typeReference = object : TypeReference<List<VoteEntity<TargetRef>>>() {}
|
||||
return requester.run {
|
||||
getFunction("find_citizen_votes_by_target_ids")
|
||||
.select(
|
||||
typeReference,
|
||||
mapOf(
|
||||
"citizen_id" to citizen.id,
|
||||
"ids" to targets
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VoteRepository(requester: Requester) : VoteRepositoryAbs<TargetRef>(requester)
|
||||
|
||||
class VoteArticleRepository(requester: Requester) : VoteRepositoryAbs<ArticleForView>(requester) {
|
||||
fun findByCitizen(
|
||||
citizen: CitizenEntity,
|
||||
page: Int = 1,
|
||||
limit: Int = 50
|
||||
): Paginated<VoteEntity<ArticleForView>> =
|
||||
findByCitizen(
|
||||
citizen.id,
|
||||
"article",
|
||||
object : TypeReference<List<VoteEntity<ArticleForView>>>() {},
|
||||
page,
|
||||
limit
|
||||
)
|
||||
}
|
||||
|
||||
class VoteArticleCommentRepository(requester: Requester) : VoteRepositoryAbs<CommentForView<ArticleForView, CitizenRef>>(requester) {
|
||||
fun findByCitizen(
|
||||
citizen: CitizenEntity,
|
||||
page: Int = 1,
|
||||
limit: Int = 50
|
||||
): Paginated<VoteEntity<CommentForView<ArticleForView, CitizenRef>>> =
|
||||
findByCitizen(
|
||||
citizen.id,
|
||||
"article",
|
||||
object : TypeReference<List<VoteEntity<CommentForView<ArticleForView, CitizenRef>>>>() {},
|
||||
page,
|
||||
limit
|
||||
)
|
||||
}
|
||||
|
||||
class VoteCommentRepository(requester: Requester) : VoteRepositoryAbs<CommentForView<TargetRef, CitizenRef>>(requester) {
|
||||
fun findByCitizen(
|
||||
citizen: CitizenEntity,
|
||||
page: Int = 1,
|
||||
limit: Int = 50
|
||||
): Paginated<VoteEntity<CommentForView<TargetRef, CitizenRef>>> =
|
||||
findByCitizen(
|
||||
citizen.id,
|
||||
"article",
|
||||
object : TypeReference<List<VoteEntity<CommentForView<TargetRef, CitizenRef>>>>() {},
|
||||
page,
|
||||
limit
|
||||
)
|
||||
}
|
||||
|
||||
class VoteConstitutionRepository(requester: Requester) : VoteRepositoryAbs<Constitution>(requester) {
|
||||
fun findByCitizen(
|
||||
citizen: CitizenEntity,
|
||||
page: Int = 1,
|
||||
limit: Int = 50
|
||||
): Paginated<VoteEntity<Constitution>> =
|
||||
findByCitizen(
|
||||
citizen.id,
|
||||
"constitution",
|
||||
object : TypeReference<List<VoteEntity<Constitution>>>() {},
|
||||
page,
|
||||
limit
|
||||
)
|
||||
}
|
||||
26
src/main/kotlin/component/vote/VoteVoter.kt
Normal file
26
src/main/kotlin/component/vote/VoteVoter.kt
Normal file
@@ -0,0 +1,26 @@
|
||||
package fr.dcproject.component.vote
|
||||
|
||||
import fr.dcproject.component.citizen.CitizenI
|
||||
import fr.dcproject.component.vote.entity.VoteForUpdateI
|
||||
import fr.dcproject.entity.TargetI
|
||||
import fr.dcproject.voter.Voter
|
||||
import fr.dcproject.voter.VoterResponse
|
||||
import fr.postgresjson.entity.EntityDeletedAt
|
||||
import fr.dcproject.component.vote.entity.Vote as VoteEntity
|
||||
|
||||
class VoteVoter : Voter() {
|
||||
fun <S> canCreate(subject: VoteForUpdateI<S, *>, citizen: CitizenI?): VoterResponse where S : EntityDeletedAt, S : TargetI = when {
|
||||
citizen == null -> denied("You must be connected for vote", "vote.create.connected")
|
||||
subject.target.isDeleted() -> denied("You cannot vote on deleted target", "vote.create.isDeleted")
|
||||
else -> granted()
|
||||
}
|
||||
|
||||
fun <S : VoteEntity<*>> canView(subjects: List<S>, citizen: CitizenI?): VoterResponse =
|
||||
canAll(subjects) { canView(it, citizen) }
|
||||
|
||||
fun canView(subject: VoteEntity<*>, citizen: CitizenI?): VoterResponse = when {
|
||||
citizen == null -> denied("You must be connected for view your votes", "vote.view.connected")
|
||||
subject.createdBy.id != citizen.id -> denied("You can only display your votes", "vote.view.onlyYours")
|
||||
else -> granted()
|
||||
}
|
||||
}
|
||||
9
src/main/kotlin/component/vote/dto/Votable.kt
Normal file
9
src/main/kotlin/component/vote/dto/Votable.kt
Normal file
@@ -0,0 +1,9 @@
|
||||
package fr.dcproject.component.vote.dto
|
||||
|
||||
interface Votable {
|
||||
val votes: VoteAggregation
|
||||
|
||||
class Imp(parent: fr.dcproject.component.vote.entity.Votable) : Votable {
|
||||
override val votes: VoteAggregation = VoteAggregation(parent)
|
||||
}
|
||||
}
|
||||
11
src/main/kotlin/component/vote/dto/VoteAggregation.kt
Normal file
11
src/main/kotlin/component/vote/dto/VoteAggregation.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
package fr.dcproject.component.vote.dto
|
||||
|
||||
import fr.dcproject.component.vote.entity.Votable
|
||||
|
||||
class VoteAggregation(parent: Votable) {
|
||||
val up: Int = parent.votes.up
|
||||
val neutral: Int = parent.votes.neutral
|
||||
val down: Int = parent.votes.down
|
||||
val total: Int = parent.votes.total
|
||||
val score: Int = parent.votes.score
|
||||
}
|
||||
9
src/main/kotlin/component/vote/entity/Votable.kt
Normal file
9
src/main/kotlin/component/vote/entity/Votable.kt
Normal file
@@ -0,0 +1,9 @@
|
||||
package fr.dcproject.component.vote.entity
|
||||
|
||||
interface Votable {
|
||||
val votes: VoteAggregation
|
||||
}
|
||||
|
||||
class VotableImp : Votable {
|
||||
override val votes: VoteAggregation = VoteAggregation()
|
||||
}
|
||||
57
src/main/kotlin/component/vote/entity/Vote.kt
Normal file
57
src/main/kotlin/component/vote/entity/Vote.kt
Normal file
@@ -0,0 +1,57 @@
|
||||
package fr.dcproject.component.vote.entity
|
||||
|
||||
import fr.dcproject.component.citizen.CitizenBasic
|
||||
import fr.dcproject.component.citizen.CitizenBasicI
|
||||
import fr.dcproject.component.citizen.CitizenI
|
||||
import fr.dcproject.entity.ExtraI
|
||||
import fr.dcproject.entity.HasTarget
|
||||
import fr.dcproject.entity.TargetI
|
||||
import fr.postgresjson.entity.EntityCreatedAt
|
||||
import fr.postgresjson.entity.EntityCreatedAtImp
|
||||
import fr.postgresjson.entity.EntityCreatedBy
|
||||
import fr.postgresjson.entity.EntityCreatedByImp
|
||||
import fr.postgresjson.entity.EntityUpdatedAt
|
||||
import fr.postgresjson.entity.EntityUpdatedAtImp
|
||||
import fr.postgresjson.entity.UuidEntityI
|
||||
import java.util.UUID
|
||||
|
||||
@Deprecated("")
|
||||
class Vote<T : TargetI>(
|
||||
id: UUID = UUID.randomUUID(),
|
||||
override val createdBy: CitizenBasic,
|
||||
override val target: T,
|
||||
var note: Int,
|
||||
var anonymous: Boolean = true
|
||||
) : ExtraI<T, CitizenBasicI>,
|
||||
VoteRef(id),
|
||||
EntityCreatedAt by EntityCreatedAtImp(),
|
||||
EntityCreatedBy<CitizenBasicI> by EntityCreatedByImp(createdBy),
|
||||
EntityUpdatedAt by EntityUpdatedAtImp() {
|
||||
init {
|
||||
if (note > 1 && note < -1) {
|
||||
error("note must be 1, 0 or -1")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VoteForUpdate<T : TargetI, C : CitizenI>(
|
||||
override val id: UUID = UUID.randomUUID(),
|
||||
override val note: Int,
|
||||
override val target: T,
|
||||
override val createdBy: C
|
||||
) : VoteRef(id),
|
||||
VoteForUpdateI<T, C>,
|
||||
EntityCreatedBy<C> by EntityCreatedByImp<C>(createdBy)
|
||||
|
||||
interface VoteForUpdateI<T : TargetI, C : CitizenI> : VoteI, HasTarget<T>, EntityCreatedBy<C> {
|
||||
override val id: UUID
|
||||
val note: Int
|
||||
override val target: T
|
||||
override val createdBy: C
|
||||
}
|
||||
|
||||
open class VoteRef(
|
||||
override val id: UUID
|
||||
) : VoteI
|
||||
|
||||
interface VoteI : UuidEntityI
|
||||
16
src/main/kotlin/component/vote/entity/VoteAggregation.kt
Normal file
16
src/main/kotlin/component/vote/entity/VoteAggregation.kt
Normal file
@@ -0,0 +1,16 @@
|
||||
package fr.dcproject.component.vote.entity
|
||||
|
||||
import fr.postgresjson.entity.EntityI
|
||||
import fr.postgresjson.entity.EntityUpdatedAt
|
||||
import fr.postgresjson.entity.EntityUpdatedAtImp
|
||||
|
||||
class VoteAggregation(
|
||||
val up: Int,
|
||||
val neutral: Int,
|
||||
val down: Int,
|
||||
val total: Int,
|
||||
val score: Int
|
||||
) : EntityI,
|
||||
EntityUpdatedAt by EntityUpdatedAtImp() {
|
||||
constructor() : this(0, 0, 0, 0, 0)
|
||||
}
|
||||
33
src/main/kotlin/component/vote/routes/GetCitizenVotes.kt
Normal file
33
src/main/kotlin/component/vote/routes/GetCitizenVotes.kt
Normal file
@@ -0,0 +1,33 @@
|
||||
package fr.dcproject.component.vote.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.citizen.Citizen
|
||||
import fr.dcproject.component.vote.VoteRepository
|
||||
import fr.dcproject.component.vote.VoteVoter
|
||||
import fr.dcproject.utils.toUUID
|
||||
import fr.dcproject.voter.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 java.util.UUID
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
object GetCitizenVotes {
|
||||
@Location("/citizens/{citizen}/votes")
|
||||
class CitizenVotesRequest(val citizen: Citizen, id: List<String>) {
|
||||
val id: List<UUID> = id.toUUID()
|
||||
}
|
||||
|
||||
fun Route.getCitizenVote(repo: VoteRepository, voter: VoteVoter) {
|
||||
get<CitizenVotesRequest> {
|
||||
val votes = repo.findCitizenVotesByTargets(it.citizen, it.id)
|
||||
if (votes.isNotEmpty()) {
|
||||
voter.assert { canView(votes, citizenOrNull) }
|
||||
}
|
||||
call.respond(votes)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package fr.dcproject.component.vote.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.citizen.Citizen
|
||||
import fr.dcproject.component.vote.VoteArticleRepository
|
||||
import fr.dcproject.component.vote.VoteVoter
|
||||
import fr.dcproject.routes.PaginatedRequest
|
||||
import fr.dcproject.routes.PaginatedRequestI
|
||||
import fr.dcproject.voter.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
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
object GetCitizenVotesOnArticle {
|
||||
@Location("/citizens/{citizen}/votes/articles")
|
||||
class CitizenVoteArticleRequest(
|
||||
val citizen: Citizen,
|
||||
page: Int = 1,
|
||||
limit: Int = 50,
|
||||
val search: String? = null
|
||||
) : PaginatedRequestI by PaginatedRequest(page, limit)
|
||||
|
||||
fun Route.getCitizenVotesOnArticle(repo: VoteArticleRepository, voter: VoteVoter) {
|
||||
get<CitizenVoteArticleRequest> {
|
||||
val votes = repo.findByCitizen(it.citizen, it.page, it.limit)
|
||||
voter.assert { canView(votes.result, citizenOrNull) }
|
||||
|
||||
call.respond(votes)
|
||||
}
|
||||
}
|
||||
}
|
||||
39
src/main/kotlin/component/vote/routes/PutVoteOnArticle.kt
Normal file
39
src/main/kotlin/component/vote/routes/PutVoteOnArticle.kt
Normal file
@@ -0,0 +1,39 @@
|
||||
package fr.dcproject.component.vote.routes
|
||||
|
||||
import fr.dcproject.component.article.ArticleForView
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.vote.VoteArticleRepository
|
||||
import fr.dcproject.component.vote.VoteVoter
|
||||
import fr.dcproject.component.vote.entity.VoteForUpdate
|
||||
import fr.dcproject.voter.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.Location
|
||||
import io.ktor.locations.put
|
||||
import io.ktor.request.receive
|
||||
import io.ktor.response.respond
|
||||
import io.ktor.routing.Route
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
object PutVoteOnArticle {
|
||||
@Location("/articles/{article}/vote")
|
||||
class ArticleVoteRequest(val article: ArticleForView) {
|
||||
data class Content(var note: Int)
|
||||
}
|
||||
|
||||
fun Route.putVoteOnArticle(repo: VoteArticleRepository, voter: VoteVoter) {
|
||||
put<ArticleVoteRequest> {
|
||||
val content = call.receive<ArticleVoteRequest.Content>()
|
||||
val vote = VoteForUpdate(
|
||||
target = it.article,
|
||||
note = content.note,
|
||||
createdBy = this.citizen
|
||||
)
|
||||
voter.assert { canCreate(vote, citizenOrNull) }
|
||||
val votes = repo.vote(vote)
|
||||
call.respond(HttpStatusCode.Created, votes)
|
||||
}
|
||||
}
|
||||
}
|
||||
41
src/main/kotlin/component/vote/routes/PutVoteOnComment.kt
Normal file
41
src/main/kotlin/component/vote/routes/PutVoteOnComment.kt
Normal file
@@ -0,0 +1,41 @@
|
||||
package fr.dcproject.component.vote.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.comment.generic.CommentRepository
|
||||
import fr.dcproject.component.vote.VoteCommentRepository
|
||||
import fr.dcproject.component.vote.VoteVoter
|
||||
import fr.dcproject.component.vote.entity.VoteForUpdate
|
||||
import fr.dcproject.voter.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.Location
|
||||
import io.ktor.locations.put
|
||||
import io.ktor.request.receive
|
||||
import io.ktor.response.respond
|
||||
import io.ktor.routing.Route
|
||||
import java.util.UUID
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
object PutVoteOnComment {
|
||||
@Location("/comments/{comment}/vote")
|
||||
class CommentVoteRequest(val comment: UUID) {
|
||||
data class Content(var note: Int)
|
||||
}
|
||||
|
||||
fun Route.putVoteOnComment(voteCommentRepo: VoteCommentRepository, commentRepo: CommentRepository, voter: VoteVoter) {
|
||||
put<CommentVoteRequest> {
|
||||
val comment = commentRepo.findById(it.comment)!!
|
||||
val content = call.receive<CommentVoteRequest.Content>()
|
||||
val vote = VoteForUpdate(
|
||||
target = comment,
|
||||
note = content.note,
|
||||
createdBy = this.citizen
|
||||
)
|
||||
voter.assert { canCreate(vote, citizenOrNull) }
|
||||
val votes = voteCommentRepo.vote(vote)
|
||||
call.respond(HttpStatusCode.Created, votes)
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/main/kotlin/component/vote/routes/VoteConstitution.kt
Normal file
40
src/main/kotlin/component/vote/routes/VoteConstitution.kt
Normal file
@@ -0,0 +1,40 @@
|
||||
package fr.dcproject.component.vote.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.vote.VoteConstitutionRepository
|
||||
import fr.dcproject.component.vote.VoteVoter
|
||||
import fr.dcproject.component.vote.entity.VoteForUpdate
|
||||
import fr.dcproject.component.vote.routes.VoteConstitution.ConstitutionVoteRequest.Input
|
||||
import fr.dcproject.voter.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.Location
|
||||
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
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
object VoteConstitution {
|
||||
@Location("/constitutions/{constitution}/vote")
|
||||
class ConstitutionVoteRequest(val constitution: ConstitutionEntity) {
|
||||
data class Input(var note: Int)
|
||||
}
|
||||
|
||||
fun Route.voteConstitution(repo: VoteConstitutionRepository, voter: VoteVoter) {
|
||||
put<ConstitutionVoteRequest> {
|
||||
val content = call.receive<Input>()
|
||||
val vote = VoteForUpdate(
|
||||
target = it.constitution,
|
||||
note = content.note,
|
||||
createdBy = this.citizen
|
||||
)
|
||||
voter.assert { canCreate(vote, citizenOrNull) }
|
||||
repo.vote(vote)
|
||||
call.respond(HttpStatusCode.Created)
|
||||
}
|
||||
}
|
||||
}
|
||||
22
src/main/kotlin/component/vote/routes/install.kt
Normal file
22
src/main/kotlin/component/vote/routes/install.kt
Normal file
@@ -0,0 +1,22 @@
|
||||
package fr.dcproject.component.vote.routes
|
||||
|
||||
import fr.dcproject.component.vote.routes.GetCitizenVotes.getCitizenVote
|
||||
import fr.dcproject.component.vote.routes.GetCitizenVotesOnArticle.getCitizenVotesOnArticle
|
||||
import fr.dcproject.component.vote.routes.PutVoteOnArticle.putVoteOnArticle
|
||||
import fr.dcproject.component.vote.routes.PutVoteOnComment.putVoteOnComment
|
||||
import fr.dcproject.component.vote.routes.VoteConstitution.voteConstitution
|
||||
import io.ktor.auth.authenticate
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.routing.Routing
|
||||
import org.koin.ktor.ext.get
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
fun Routing.installVoteRoutes() {
|
||||
authenticate(optional = true) {
|
||||
getCitizenVote(get(), get())
|
||||
getCitizenVotesOnArticle(get(), get())
|
||||
putVoteOnArticle(get(), get())
|
||||
putVoteOnComment(get(), get(), get())
|
||||
voteConstitution(get(), get())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user