Add validation on route CreateComments & EditComment
rename POST /comments/{comment}/children
method edit and create comment of repository return edited/created comment
This commit is contained in:
@@ -63,12 +63,14 @@ open class CommentForUpdate<T : TargetI, C : CitizenI>(
|
||||
constructor(
|
||||
createdBy: C,
|
||||
parent: CommentParent<T>,
|
||||
content: String
|
||||
content: String,
|
||||
id: UUID? = null,
|
||||
) : this(
|
||||
createdBy = createdBy,
|
||||
parent = parent,
|
||||
target = parent.target,
|
||||
content = content
|
||||
content = content,
|
||||
id = id ?: UUID.randomUUID(),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -58,35 +58,29 @@ abstract class CommentRepositoryAbs<T : TargetI>(override var requester: Request
|
||||
page: Int = 1,
|
||||
limit: Int = 50,
|
||||
sort: String = "createdAt"
|
||||
): Paginated<CommentForView<T, CitizenCreatorI>> {
|
||||
return requester.run {
|
||||
getFunction("find_comments_by_target")
|
||||
.select<CommentForView<T, CitizenCreator>>(
|
||||
page,
|
||||
limit,
|
||||
"target_id" to targetId,
|
||||
"sort" to sort
|
||||
)
|
||||
as Paginated<CommentForView<T, CitizenCreatorI>>
|
||||
}
|
||||
}
|
||||
): Paginated<CommentForView<T, CitizenCreatorI>> = requester
|
||||
.getFunction("find_comments_by_target")
|
||||
.select<CommentForView<T, CitizenCreator>>(
|
||||
page,
|
||||
limit,
|
||||
"target_id" to targetId,
|
||||
"sort" to sort
|
||||
) as Paginated<CommentForView<T, CitizenCreatorI>>
|
||||
|
||||
fun <I : TargetI, C : CitizenCreatorI> comment(comment: CommentForUpdate<I, C>) {
|
||||
requester
|
||||
.getFunction("comment")
|
||||
.sendQuery(
|
||||
"reference" to comment.target.reference,
|
||||
"resource" to comment
|
||||
)
|
||||
}
|
||||
fun <I : TargetI, C : CitizenCreatorI> comment(comment: CommentForUpdate<I, C>): CommentForView<TargetRef, CitizenCreator> = requester
|
||||
.getFunction("comment")
|
||||
.selectOne(
|
||||
"reference" to comment.target.reference,
|
||||
"resource" to comment
|
||||
)!!
|
||||
|
||||
fun <I : T> edit(comment: CommentForUpdate<I, CitizenCreatorI>) {
|
||||
requester
|
||||
fun <I : T> edit(comment: CommentForUpdate<I, CitizenCreatorI>): CommentForView<TargetRef, CitizenCreator> {
|
||||
return requester
|
||||
.getFunction("edit_comment")
|
||||
.sendQuery(
|
||||
.selectOne(
|
||||
"id" to comment.id,
|
||||
"content" to comment.content
|
||||
)
|
||||
)!!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package fr.dcproject.component.comment.generic.routes
|
||||
|
||||
import fr.dcproject.application.http.badRequestIfNotValid
|
||||
import fr.dcproject.common.security.assert
|
||||
import fr.dcproject.common.utils.receiveOrBadRequest
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.auth.mustBeAuth
|
||||
import fr.dcproject.component.comment.generic.CommentAccessControl
|
||||
import fr.dcproject.component.comment.generic.database.CommentForUpdate
|
||||
import fr.dcproject.component.comment.generic.database.CommentRef
|
||||
import fr.dcproject.component.comment.generic.database.CommentRepository
|
||||
import fr.dcproject.component.comment.toOutput
|
||||
import io.konform.validation.Validation
|
||||
import io.konform.validation.jsonschema.maxLength
|
||||
import io.konform.validation.jsonschema.minLength
|
||||
import io.ktor.application.call
|
||||
import io.ktor.features.NotFoundException
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.Location
|
||||
import io.ktor.locations.post
|
||||
import io.ktor.response.respond
|
||||
import io.ktor.routing.Route
|
||||
import java.util.UUID
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
object CreateComment {
|
||||
@Location("/comments/{comment}")
|
||||
class CreateCommentRequest(comment: UUID) {
|
||||
val comment = CommentRef(comment)
|
||||
class Input(val content: String) {
|
||||
fun validate() = Validation<Input> {
|
||||
Input::content {
|
||||
minLength(20)
|
||||
maxLength(6000)
|
||||
}
|
||||
}.validate(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.createCommentChildren(repo: CommentRepository, ac: CommentAccessControl) {
|
||||
post<CreateCommentRequest> {
|
||||
mustBeAuth()
|
||||
|
||||
call.receiveOrBadRequest<CreateCommentRequest.Input>()
|
||||
.apply { validate().badRequestIfNotValid() }
|
||||
.run {
|
||||
val parent = repo.findById(it.comment.id) ?: throw NotFoundException("Comment not found")
|
||||
CommentForUpdate(
|
||||
content = content,
|
||||
createdBy = citizen,
|
||||
target = parent.target,
|
||||
parent = parent,
|
||||
)
|
||||
}.let { newComment ->
|
||||
ac.assert { canCreate(newComment, citizenOrNull) }
|
||||
repo.comment(newComment)
|
||||
call.respond(HttpStatusCode.Created, newComment.toOutput())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package fr.dcproject.component.comment.generic.routes
|
||||
|
||||
import fr.dcproject.common.security.assert
|
||||
import fr.dcproject.common.utils.receiveOrBadRequest
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.auth.mustBeAuth
|
||||
import fr.dcproject.component.comment.generic.CommentAccessControl
|
||||
import fr.dcproject.component.comment.generic.database.CommentForUpdate
|
||||
import fr.dcproject.component.comment.generic.database.CommentRef
|
||||
import fr.dcproject.component.comment.generic.database.CommentRepository
|
||||
import fr.dcproject.component.comment.toOutput
|
||||
import io.ktor.application.call
|
||||
import io.ktor.features.NotFoundException
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.Location
|
||||
import io.ktor.locations.post
|
||||
import io.ktor.response.respond
|
||||
import io.ktor.routing.Route
|
||||
import java.util.UUID
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
object CreateCommentChildren {
|
||||
@Location("/comments/{comment}/children")
|
||||
class CreateCommentChildrenRequest(comment: UUID) {
|
||||
val comment = CommentRef(comment)
|
||||
class Input(val content: String)
|
||||
}
|
||||
|
||||
fun Route.createCommentChildren(repo: CommentRepository, ac: CommentAccessControl) {
|
||||
post<CreateCommentChildrenRequest> {
|
||||
mustBeAuth()
|
||||
val parent = repo.findById(it.comment.id) ?: throw NotFoundException("Comment not found")
|
||||
val newComment = CommentForUpdate(
|
||||
content = call.receiveOrBadRequest<CreateCommentChildrenRequest.Input>().content,
|
||||
createdBy = citizen,
|
||||
parent = parent
|
||||
)
|
||||
|
||||
ac.assert { canCreate(newComment, citizenOrNull) }
|
||||
repo.comment(newComment)
|
||||
|
||||
call.respond(HttpStatusCode.Created, newComment.toOutput())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,18 @@
|
||||
package fr.dcproject.component.comment.generic.routes
|
||||
|
||||
import fr.dcproject.common.response.toOutput
|
||||
import fr.dcproject.application.http.badRequestIfNotValid
|
||||
import fr.dcproject.common.security.assert
|
||||
import fr.dcproject.common.utils.receiveOrBadRequest
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.auth.mustBeAuth
|
||||
import fr.dcproject.component.comment.generic.CommentAccessControl
|
||||
import fr.dcproject.component.comment.generic.database.CommentForUpdate
|
||||
import fr.dcproject.component.comment.generic.database.CommentRef
|
||||
import fr.dcproject.component.comment.generic.database.CommentRepository
|
||||
import fr.dcproject.component.comment.toOutput
|
||||
import io.konform.validation.Validation
|
||||
import io.konform.validation.jsonschema.maxLength
|
||||
import io.konform.validation.jsonschema.minLength
|
||||
import io.ktor.application.call
|
||||
import io.ktor.features.NotFoundException
|
||||
import io.ktor.http.HttpStatusCode
|
||||
@@ -24,22 +28,40 @@ object EditComment {
|
||||
@Location("/comments/{comment}")
|
||||
class EditCommentRequest(comment: UUID) {
|
||||
val comment = CommentRef(comment)
|
||||
class Input(val content: String)
|
||||
class Input(val content: String) {
|
||||
fun validate() = Validation<Input> {
|
||||
Input::content {
|
||||
minLength(20)
|
||||
maxLength(6000)
|
||||
}
|
||||
}.validate(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.editComment(repo: CommentRepository, ac: CommentAccessControl) {
|
||||
put<EditCommentRequest> {
|
||||
mustBeAuth()
|
||||
val comment = repo.findById(it.comment.id) ?: throw NotFoundException("Comment not found")
|
||||
ac.assert { canUpdate(comment, citizenOrNull) }
|
||||
val commentOld = repo.findById(it.comment.id) ?: throw NotFoundException("Comment not found")
|
||||
ac.assert { canUpdate(commentOld, citizenOrNull) }
|
||||
|
||||
comment.content = call.receiveOrBadRequest<EditCommentRequest.Input>().content
|
||||
repo.edit(comment)
|
||||
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
comment.toOutput()
|
||||
)
|
||||
call.receiveOrBadRequest<EditCommentRequest.Input>()
|
||||
.apply { validate().badRequestIfNotValid() }
|
||||
.run {
|
||||
CommentForUpdate(
|
||||
id = commentOld.id,
|
||||
createdBy = commentOld.createdBy,
|
||||
target = commentOld.target,
|
||||
parent = commentOld.parent,
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
.let { repo.edit(it) }
|
||||
.let {
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
it.toOutput()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package fr.dcproject.component.comment.generic.routes
|
||||
|
||||
import fr.dcproject.component.comment.generic.routes.CreateCommentChildren.createCommentChildren
|
||||
import fr.dcproject.component.comment.generic.routes.CreateComment.createCommentChildren
|
||||
import fr.dcproject.component.comment.generic.routes.EditComment.editComment
|
||||
import fr.dcproject.component.comment.generic.routes.GetCommentChildren.getChildrenComments
|
||||
import fr.dcproject.component.comment.generic.routes.GetOneComment.getOneComment
|
||||
|
||||
Reference in New Issue
Block a user