Valider les resource entrente #91

Merged
flecomte merged 46 commits from 21-valid-input into master 2021-04-16 03:27:11 +02:00
4 changed files with 68 additions and 18 deletions
Showing only changes of commit a07b19a3cb - Show all commits

View File

@@ -332,6 +332,12 @@ tasks.register("testCitizens", Test::class) {
includeTags("citizen") includeTags("citizen")
} }
} }
tasks.register("testComments", Test::class) {
group = "tests"
useJUnitPlatform {
includeTags("comment")
}
}
dependencyCheck { dependencyCheck {
formats = listOf(ReportGenerator.Format.HTML, ReportGenerator.Format.XML) formats = listOf(ReportGenerator.Format.HTML, ReportGenerator.Format.XML)

View File

@@ -1,6 +1,6 @@
package fr.dcproject.component.comment.article.routes package fr.dcproject.component.comment.article.routes
import fr.dcproject.common.response.toOutput import fr.dcproject.application.http.badRequestIfNotValid
import fr.dcproject.common.security.assert import fr.dcproject.common.security.assert
import fr.dcproject.common.utils.receiveOrBadRequest import fr.dcproject.common.utils.receiveOrBadRequest
import fr.dcproject.component.article.database.ArticleRef import fr.dcproject.component.article.database.ArticleRef
@@ -12,6 +12,9 @@ import fr.dcproject.component.comment.article.routes.CreateCommentArticle.PostAr
import fr.dcproject.component.comment.generic.CommentAccessControl import fr.dcproject.component.comment.generic.CommentAccessControl
import fr.dcproject.component.comment.generic.database.CommentForUpdate import fr.dcproject.component.comment.generic.database.CommentForUpdate
import fr.dcproject.component.comment.toOutput 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.application.call
import io.ktor.http.HttpStatusCode import io.ktor.http.HttpStatusCode
import io.ktor.locations.KtorExperimentalLocationsAPI import io.ktor.locations.KtorExperimentalLocationsAPI
@@ -26,27 +29,36 @@ object CreateCommentArticle {
@Location("/articles/{article}/comments") @Location("/articles/{article}/comments")
class PostArticleCommentRequest(article: UUID) { class PostArticleCommentRequest(article: UUID) {
val article = ArticleRef(article) val article = ArticleRef(article)
class Input(val content: String) class Input(val content: String) {
fun validate() = Validation<Input> {
Input::content {
minLength(20)
maxLength(6000)
}
}.validate(this)
}
} }
fun Route.createCommentArticle(repo: CommentArticleRepository, ac: CommentAccessControl) { fun Route.createCommentArticle(repo: CommentArticleRepository, ac: CommentAccessControl) {
post<PostArticleCommentRequest> { post<PostArticleCommentRequest> {
mustBeAuth() mustBeAuth()
call.receiveOrBadRequest<Input>().run { call.receiveOrBadRequest<Input>()
CommentForUpdate( .apply { validate().badRequestIfNotValid() }
target = it.article, .run {
createdBy = citizen, CommentForUpdate(
content = content target = it.article,
) createdBy = citizen,
}.let { comment -> content = content
ac.assert { canCreate(comment, citizenOrNull) } )
repo.comment(comment) }.let { comment ->
ac.assert { canCreate(comment, citizenOrNull) }
repo.comment(comment)
call.respond( call.respond(
HttpStatusCode.Created, HttpStatusCode.Created,
comment.toOutput() comment.toOutput()
) )
} }
} }
} }
} }

View File

@@ -563,6 +563,12 @@ paths:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/CommentResponse' $ref: '#/components/schemas/CommentResponse'
400:
description: BadReqest
content:
application/json:
schema:
$ref: '#/components/schemas/400'
401: 401:
$ref: '#/components/responses/401' $ref: '#/components/responses/401'
/comments/{comment}: /comments/{comment}:

View File

@@ -1,6 +1,8 @@
package integration package integration
import fr.dcproject.component.citizen.database.CitizenI.Name import fr.dcproject.component.citizen.database.CitizenI.Name
import integration.steps.`when`.Validate.ALL
import integration.steps.`when`.Validate.REQUEST_BODY
import integration.steps.`when`.`When I send a GET request` import integration.steps.`when`.`When I send a GET request`
import integration.steps.`when`.`When I send a POST request` import integration.steps.`when`.`When I send a POST request`
import integration.steps.`when`.`When I send a PUT request` import integration.steps.`when`.`When I send a PUT request`
@@ -13,6 +15,7 @@ import integration.steps.then.`And the response should contain`
import integration.steps.then.`And the response should not be null` import integration.steps.then.`And the response should not be null`
import integration.steps.then.`Then the response should be` import integration.steps.then.`Then the response should be`
import integration.steps.then.and import integration.steps.then.and
import io.ktor.http.HttpStatusCode.Companion.BadRequest
import io.ktor.http.HttpStatusCode.Companion.Created import io.ktor.http.HttpStatusCode.Companion.Created
import io.ktor.http.HttpStatusCode.Companion.OK import io.ktor.http.HttpStatusCode.Companion.OK
import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Tag
@@ -33,14 +36,37 @@ class `Comment articles routes` : BaseTest() {
`with body`( `with body`(
""" """
{ {
"content": "Hello mister" "content": "Hello mister MARABOUTCHA"
} }
""" """
) )
} `Then the response should be` Created and { } `Then the response should be` Created and {
`And the response should not be null`() `And the response should not be null`()
`And the response should contain`("$.target.id", "aa16c635-28da-46f0-9a89-934eef88c7ca") `And the response should contain`("$.target.id", "aa16c635-28da-46f0-9a89-934eef88c7ca")
`And the response should contain`("$.content", "Hello mister") `And the response should contain`("$.content", "Hello mister MARABOUTCHA")
}
}
}
@Test
@Tag("BadRequest")
fun `I cannot comment article with bad request`() {
withIntegrationApplication {
`Given I have citizen`("Michael", "Faraday")
`Given I have article`(id = "aa16c635-28da-46f0-9a89-934eef88c7ca")
`When I send a POST request`("/articles/aa16c635-28da-46f0-9a89-934eef88c7ca/comments", ALL - REQUEST_BODY) {
`authenticated as`("Michael", "Faraday")
`with body`(
"""
{
"content": "To small content"
}
"""
)
} `Then the response should be` BadRequest and {
`And the response should not be null`()
`And the response should contain`("$.invalidParams[0].name", ".content")
`And the response should contain`("$.invalidParams[0].reason", "must have at least 20 characters")
} }
} }
} }