diff --git a/src/main/kotlin/fr/dcproject/Application.kt b/src/main/kotlin/fr/dcproject/Application.kt index 9d248e3..a58ca1a 100644 --- a/src/main/kotlin/fr/dcproject/Application.kt +++ b/src/main/kotlin/fr/dcproject/Application.kt @@ -159,6 +159,7 @@ fun Application.module(env: Env = PROD) { comment(get()) commentArticle(get()) commentConstitution(get()) + voteArticle(get()) } } diff --git a/src/main/kotlin/fr/dcproject/Module.kt b/src/main/kotlin/fr/dcproject/Module.kt index df48f94..f3f09ee 100644 --- a/src/main/kotlin/fr/dcproject/Module.kt +++ b/src/main/kotlin/fr/dcproject/Module.kt @@ -14,6 +14,8 @@ import fr.dcproject.repository.Constitution as ConstitutionRepository import fr.dcproject.repository.FollowArticle as FollowArticleRepository import fr.dcproject.repository.FollowConstitution as FollowConstitutionRepository import fr.dcproject.repository.User as UserRepository +import fr.dcproject.repository.VoteArticle as VoteArticleRepository +import fr.dcproject.repository.VoteConstitution as VoteConstitutionRepository val config = Config() @@ -39,6 +41,8 @@ val Module = module { single { CommentGenericRepository(get()) } single { CommentArticleRepository(get()) } single { CommentConstitutionRepository(get()) } + single { VoteArticleRepository(get()) } + single { VoteConstitutionRepository(get()) } single { Migrations(connection = get(), directory = config.sqlFiles) } } diff --git a/src/main/kotlin/fr/dcproject/entity/Vote.kt b/src/main/kotlin/fr/dcproject/entity/Vote.kt new file mode 100644 index 0000000..3375318 --- /dev/null +++ b/src/main/kotlin/fr/dcproject/entity/Vote.kt @@ -0,0 +1,21 @@ +package fr.dcproject.entity + +import fr.postgresjson.entity.EntityUpdatedAt +import fr.postgresjson.entity.EntityUpdatedAtImp +import fr.postgresjson.entity.UuidEntity +import java.util.* + +open class Vote ( + id: UUID = UUID.randomUUID(), + createdBy: Citizen, + override var target: T, + var note: Int, + var annonymous: Boolean = true +): Extra(id, createdBy), + EntityUpdatedAt by EntityUpdatedAtImp() { + init { + if (note > 1 && note < -1) { + error("note must be 1, 0 or -1") + } + } +} diff --git a/src/main/kotlin/fr/dcproject/repository/Vote.kt b/src/main/kotlin/fr/dcproject/repository/Vote.kt new file mode 100644 index 0000000..033220c --- /dev/null +++ b/src/main/kotlin/fr/dcproject/repository/Vote.kt @@ -0,0 +1,31 @@ +package fr.dcproject.repository + +import fr.dcproject.entity.Article +import fr.dcproject.entity.Constitution +import fr.postgresjson.connexion.Requester +import fr.postgresjson.entity.UuidEntity +import fr.postgresjson.repository.RepositoryI +import kotlin.reflect.KClass +import fr.dcproject.entity.Vote as VoteEntity + +open class Vote (override var requester: Requester): RepositoryI> { + override val entityName = VoteEntity::class as KClass> + + fun vote(vote: VoteEntity) { + val reference = vote.target::class.simpleName!!.toLowerCase() + val author = vote.createdBy ?: error("vote must be contain an author") + val anonymous = author.voteAnnonymous + requester + .getFunction("vote") + .sendQuery( + "reference" to reference, + "target_id" to vote.target.id, + "note" to vote.note, + "created_by_id" to author.id, + "anonymous" to anonymous + ) + } +} + +class VoteArticle (requester: Requester): Vote
(requester) +class VoteConstitution (requester: Requester): Vote(requester) \ No newline at end of file diff --git a/src/main/kotlin/fr/dcproject/routes/VoteArticle.kt b/src/main/kotlin/fr/dcproject/routes/VoteArticle.kt new file mode 100644 index 0000000..2db57dd --- /dev/null +++ b/src/main/kotlin/fr/dcproject/routes/VoteArticle.kt @@ -0,0 +1,37 @@ +package fr.dcproject.routes + +import fr.dcproject.citizen +import fr.dcproject.entity.Citizen +import fr.dcproject.routes.VoteArticlePaths.ArticleVoteRequest.Content +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.Article as ArticleEntity +import fr.dcproject.entity.Vote as VoteEntity +import fr.dcproject.repository.VoteArticle as VoteArticleRepository + +@KtorExperimentalLocationsAPI +object VoteArticlePaths { + @Location("/articles/{article}/vote") class ArticleVoteRequest(val article: ArticleEntity) { + data class Content(var note: Int) + } + @Location("/citizens/{citizen}/votes/articles") class CitizenVoteArticleRequest(val citizen: Citizen) +} + +@KtorExperimentalLocationsAPI +fun Route.voteArticle(repo: VoteArticleRepository) { + put { + val content = call.receive() + repo.vote(VoteEntity( + target = it.article, + note = content.note, + createdBy = this.citizen + )) + call.respond(HttpStatusCode.Created) + } +} \ No newline at end of file diff --git a/src/test/resources/feature/vote.feature b/src/test/resources/feature/vote.feature new file mode 100644 index 0000000..ce9be45 --- /dev/null +++ b/src/test/resources/feature/vote.feature @@ -0,0 +1,21 @@ +Feature: vote Article + + Scenario: Vote article + Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd" + When I send a PUT request to "/articles/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/vote" with body: + """ + { + "note": 1 + } + """ + Then the response status code should be 201 + + Scenario: Vote article + Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd" + When I send a PUT request to "/articles/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/vote" with body: + """ + { + "note": -1 + } + """ + Then the response status code should be 201