Improve Vote Comment
Add "targetReference" field into Extra Entity Add VoteCommentRoute to OpenApi
This commit is contained in:
@@ -15,7 +15,7 @@ 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.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.VoteArticleComment as VoteArticleCommentRepository
|
import fr.dcproject.repository.VoteComment as VoteCommentRepository
|
||||||
import fr.dcproject.repository.VoteConstitution as VoteConstitutionRepository
|
import fr.dcproject.repository.VoteConstitution as VoteConstitutionRepository
|
||||||
|
|
||||||
val config = Config()
|
val config = Config()
|
||||||
@@ -44,7 +44,7 @@ val Module = module {
|
|||||||
single { CommentConstitutionRepository(get()) }
|
single { CommentConstitutionRepository(get()) }
|
||||||
single { VoteArticleRepository(get()) }
|
single { VoteArticleRepository(get()) }
|
||||||
single { VoteConstitutionRepository(get()) }
|
single { VoteConstitutionRepository(get()) }
|
||||||
single { VoteArticleCommentRepository(get()) }
|
single { VoteCommentRepository(get()) }
|
||||||
|
|
||||||
single { Migrations(connection = get(), directory = config.sqlFiles) }
|
single { Migrations(connection = get(), directory = config.sqlFiles) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ import java.util.*
|
|||||||
open class Comment <T: UuidEntity> (
|
open class Comment <T: UuidEntity> (
|
||||||
id: UUID = UUID.randomUUID(),
|
id: UUID = UUID.randomUUID(),
|
||||||
createdBy: Citizen,
|
createdBy: Citizen,
|
||||||
override var target: T,
|
target: T,
|
||||||
var content: String,
|
var content: String,
|
||||||
var responses: List<Comment<T>>? = null,
|
var responses: List<Comment<T>>? = null,
|
||||||
var parent: Comment<T>? = null,
|
var parent: Comment<T>? = null,
|
||||||
var parentsIds: List<UUID>? = null,
|
var parentsIds: List<UUID>? = null,
|
||||||
val childrenCount: Int? = null
|
val childrenCount: Int? = null
|
||||||
): Extra<T>(id, createdBy),
|
): Extra<T>(id, createdBy, target),
|
||||||
EntityUpdatedAt by EntityUpdatedAtImp(),
|
EntityUpdatedAt by EntityUpdatedAtImp(),
|
||||||
EntityDeletedAt by EntityDeletedAtImp()
|
EntityDeletedAt by EntityDeletedAtImp()
|
||||||
|
|||||||
@@ -8,11 +8,14 @@ interface ExtraI <T: EntityI>:
|
|||||||
EntityCreatedAt,
|
EntityCreatedAt,
|
||||||
EntityCreatedBy<Citizen>{
|
EntityCreatedBy<Citizen>{
|
||||||
var target: T
|
var target: T
|
||||||
|
var targetReference: String
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class Extra<T: UuidEntity>(
|
abstract class Extra<T: UuidEntity>(
|
||||||
id: UUID? = UUID.randomUUID(),
|
id: UUID? = UUID.randomUUID(),
|
||||||
createdBy: Citizen
|
createdBy: Citizen,
|
||||||
|
override var target: T,
|
||||||
|
override var targetReference: String = target::class.simpleName!!.toLowerCase()
|
||||||
):
|
):
|
||||||
ExtraI<T>,
|
ExtraI<T>,
|
||||||
UuidEntity(id),
|
UuidEntity(id),
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ import java.util.*
|
|||||||
class Follow <T: UuidEntity> (
|
class Follow <T: UuidEntity> (
|
||||||
id: UUID = UUID.randomUUID(),
|
id: UUID = UUID.randomUUID(),
|
||||||
createdBy: Citizen,
|
createdBy: Citizen,
|
||||||
override var target: T
|
target: T
|
||||||
): Extra<T>(id, createdBy)
|
): Extra<T>(id, createdBy, target)
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import java.util.*
|
|||||||
open class Vote <T: UuidEntity> (
|
open class Vote <T: UuidEntity> (
|
||||||
id: UUID = UUID.randomUUID(),
|
id: UUID = UUID.randomUUID(),
|
||||||
createdBy: Citizen,
|
createdBy: Citizen,
|
||||||
override var target: T,
|
target: T,
|
||||||
var note: Int,
|
var note: Int,
|
||||||
var anonymous: Boolean = true
|
var anonymous: Boolean = true
|
||||||
): Extra<T>(id, createdBy),
|
): Extra<T>(id, createdBy, target),
|
||||||
EntityUpdatedAt by EntityUpdatedAtImp() {
|
EntityUpdatedAt by EntityUpdatedAtImp() {
|
||||||
init {
|
init {
|
||||||
if (note > 1 && note < -1) {
|
if (note > 1 && note < -1) {
|
||||||
|
|||||||
@@ -84,10 +84,8 @@ abstract class Comment <T: UuidEntity>(override var requester: Requester): Repos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GenericTargetEntity(id: UUID = UUID.randomUUID()): UuidEntity(id)
|
class CommentGeneric (requester: Requester): Comment<UuidEntity>(requester) {
|
||||||
|
override fun findById(id: UUID): CommentEntity<UuidEntity>? {
|
||||||
class CommentGeneric (requester: Requester): Comment<GenericTargetEntity>(requester) {
|
|
||||||
override fun findById(id: UUID): CommentEntity<GenericTargetEntity>? {
|
|
||||||
return requester
|
return requester
|
||||||
.getFunction("find_comment_by_id")
|
.getFunction("find_comment_by_id")
|
||||||
.selectOne(mapOf("id" to id))
|
.selectOne(mapOf("id" to id))
|
||||||
@@ -97,7 +95,7 @@ class CommentGeneric (requester: Requester): Comment<GenericTargetEntity>(reques
|
|||||||
citizen: CitizenEntity,
|
citizen: CitizenEntity,
|
||||||
page: Int,
|
page: Int,
|
||||||
limit: Int
|
limit: Int
|
||||||
): Paginated<CommentEntity<GenericTargetEntity>> {
|
): Paginated<CommentEntity<UuidEntity>> {
|
||||||
return requester.run {
|
return requester.run {
|
||||||
getFunction("find_comments_by_citizen")
|
getFunction("find_comments_by_citizen")
|
||||||
.select(page, limit,
|
.select(page, limit,
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ open class Vote <T: UuidEntity>(override var requester: Requester): RepositoryI<
|
|||||||
val reference = if (target is Comment<*>) {
|
val reference = if (target is Comment<*>) {
|
||||||
target::class.simpleName!!.toLowerCase() +
|
target::class.simpleName!!.toLowerCase() +
|
||||||
"_on_" +
|
"_on_" +
|
||||||
target.target::class.simpleName!!.toLowerCase()
|
target.targetReference
|
||||||
} else {
|
} else {
|
||||||
target::class.simpleName!!.toLowerCase()
|
target::class.simpleName!!.toLowerCase()
|
||||||
}
|
}
|
||||||
@@ -101,6 +101,21 @@ class VoteArticleComment (requester: Requester): Vote<Comment<Article>>(requeste
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class VoteComment (requester: Requester): Vote<Comment<UuidEntity>>(requester) {
|
||||||
|
fun findByCitizen(
|
||||||
|
citizen: CitizenEntity,
|
||||||
|
page: Int = 1,
|
||||||
|
limit: Int = 50
|
||||||
|
): Paginated<VoteEntity<Comment<UuidEntity>>> =
|
||||||
|
findByCitizen(
|
||||||
|
citizen.id ?: error("The citizen must have an id"),
|
||||||
|
"article",
|
||||||
|
object: TypeReference<List<VoteEntity<Comment<UuidEntity>>>>() {},
|
||||||
|
page,
|
||||||
|
limit
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
class VoteConstitution (requester: Requester): Vote<Constitution>(requester) {
|
class VoteConstitution (requester: Requester): Vote<Constitution>(requester) {
|
||||||
fun findByCitizen(
|
fun findByCitizen(
|
||||||
citizen: CitizenEntity,
|
citizen: CitizenEntity,
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ package fr.dcproject.routes
|
|||||||
|
|
||||||
import fr.dcproject.citizen
|
import fr.dcproject.citizen
|
||||||
import fr.dcproject.entity.Citizen
|
import fr.dcproject.entity.Citizen
|
||||||
import fr.dcproject.repository.CommentArticle
|
import fr.dcproject.repository.CommentGeneric
|
||||||
import fr.dcproject.repository.VoteArticleComment
|
import fr.dcproject.repository.VoteComment
|
||||||
import fr.dcproject.routes.VoteArticlePaths.ArticleCommentVoteRequest
|
|
||||||
import fr.dcproject.routes.VoteArticlePaths.ArticleVoteRequest
|
import fr.dcproject.routes.VoteArticlePaths.ArticleVoteRequest
|
||||||
|
import fr.dcproject.routes.VoteArticlePaths.CommentVoteRequest
|
||||||
import fr.dcproject.security.voter.VoteVoter.Action.CREATE
|
import fr.dcproject.security.voter.VoteVoter.Action.CREATE
|
||||||
import fr.dcproject.security.voter.VoteVoter.Action.VIEW
|
import fr.dcproject.security.voter.VoteVoter.Action.VIEW
|
||||||
import fr.dcproject.security.voter.assertCan
|
import fr.dcproject.security.voter.assertCan
|
||||||
@@ -30,8 +30,8 @@ object VoteArticlePaths {
|
|||||||
data class Content(var note: Int)
|
data class Content(var note: Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Location("/articles/{article}/comments/{comment}/vote")
|
@Location("/comments/{comment}/vote")
|
||||||
class ArticleCommentVoteRequest(val article: ArticleEntity, val comment: UUID) {
|
class CommentVoteRequest(val comment: UUID) {
|
||||||
data class Content(var note: Int)
|
data class Content(var note: Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ object VoteArticlePaths {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@KtorExperimentalLocationsAPI
|
@KtorExperimentalLocationsAPI
|
||||||
fun Route.voteArticle(repo: VoteArticleRepository, voteCommentRepo: VoteArticleComment, commentRepo: CommentArticle) {
|
fun Route.voteArticle(repo: VoteArticleRepository, voteCommentRepo: VoteComment, commentRepo: CommentGeneric) {
|
||||||
put<ArticleVoteRequest> {
|
put<ArticleVoteRequest> {
|
||||||
val content = call.receive<ArticleVoteRequest.Content>()
|
val content = call.receive<ArticleVoteRequest.Content>()
|
||||||
val vote = VoteEntity(
|
val vote = VoteEntity(
|
||||||
@@ -66,9 +66,9 @@ fun Route.voteArticle(repo: VoteArticleRepository, voteCommentRepo: VoteArticleC
|
|||||||
call.respond(HttpStatusCode.Created, votes)
|
call.respond(HttpStatusCode.Created, votes)
|
||||||
}
|
}
|
||||||
|
|
||||||
put<ArticleCommentVoteRequest> {
|
put<CommentVoteRequest> {
|
||||||
val comment = commentRepo.findById(it.comment)!!
|
val comment = commentRepo.findById(it.comment)!!
|
||||||
val content = call.receive<ArticleCommentVoteRequest.Content>()
|
val content = call.receive<CommentVoteRequest.Content>()
|
||||||
val vote = VoteEntity(
|
val vote = VoteEntity(
|
||||||
target = comment,
|
target = comment,
|
||||||
note = content.note,
|
note = content.note,
|
||||||
|
|||||||
@@ -405,6 +405,7 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/CommentResponse'
|
$ref: '#/components/schemas/CommentResponse'
|
||||||
|
|
||||||
/articles/{article}/follows:
|
/articles/{article}/follows:
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: '#/components/parameters/article'
|
- $ref: '#/components/parameters/article'
|
||||||
@@ -451,6 +452,7 @@ paths:
|
|||||||
responses:
|
responses:
|
||||||
204:
|
204:
|
||||||
description: Return only http status 204 on success
|
description: Return only http status 204 on success
|
||||||
|
|
||||||
/articles/{article}/vote:
|
/articles/{article}/vote:
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: '#/components/parameters/article'
|
- $ref: '#/components/parameters/article'
|
||||||
@@ -492,6 +494,31 @@ paths:
|
|||||||
responses:
|
responses:
|
||||||
201:
|
201:
|
||||||
description: Return only http status 201 on success
|
description: Return only http status 201 on success
|
||||||
|
/comments/{comment}/vote:
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/comment'
|
||||||
|
put:
|
||||||
|
security:
|
||||||
|
- JWTAuth: []
|
||||||
|
summary: Vote for a comment
|
||||||
|
tags:
|
||||||
|
- vote
|
||||||
|
- comment
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/VoteRequest'
|
||||||
|
responses:
|
||||||
|
201:
|
||||||
|
description: Return votes aggregation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/VoteAggregation'
|
||||||
|
404:
|
||||||
|
description: article or comment not found
|
||||||
|
|
||||||
|
|
||||||
/citizens/{citizen}/votes/articles:
|
/citizens/{citizen}/votes/articles:
|
||||||
parameters:
|
parameters:
|
||||||
@@ -584,6 +611,7 @@ components:
|
|||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
description: the ID of article
|
description: the ID of article
|
||||||
|
example: d91aa0cd-61d6-83cc-41bb-8d5656e130f7
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
|
|||||||
@@ -40,10 +40,12 @@ Feature: vote Article
|
|||||||
Scenario: Can vote a comment on article
|
Scenario: Can vote a comment on article
|
||||||
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 comment "ea5c9e87-c99e-4646-a381-2910219e077f" on article "cc9c624e-a27e-42de-af78-ae821c657a68"
|
And I have comment "ea5c9e87-c99e-4646-a381-2910219e077f" on article "cc9c624e-a27e-42de-af78-ae821c657a68"
|
||||||
When I send a PUT request to "/articles/cc9c624e-a27e-42de-af78-ae821c657a68/comments/ea5c9e87-c99e-4646-a381-2910219e077f/vote" with body:
|
When I send a PUT request to "/comments/ea5c9e87-c99e-4646-a381-2910219e077f/vote" with body:
|
||||||
"""
|
"""
|
||||||
{
|
{
|
||||||
"note": -1
|
"note": -1
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
Then the response status code should be 201
|
Then the response status code should be 201
|
||||||
|
And the response should contain object:
|
||||||
|
| down | 1 |
|
||||||
|
|||||||
Reference in New Issue
Block a user