diff --git a/build.gradle.kts b/build.gradle.kts index 36f4c7e..2f95015 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -332,6 +332,12 @@ tasks.register("testCitizens", Test::class) { includeTags("citizen") } } +tasks.register("testComments", Test::class) { + group = "tests" + useJUnitPlatform { + includeTags("comment") + } +} dependencyCheck { formats = listOf(ReportGenerator.Format.HTML, ReportGenerator.Format.XML) diff --git a/src/main/kotlin/fr/dcproject/component/comment/article/routes/CreateCommentArticle.kt b/src/main/kotlin/fr/dcproject/component/comment/article/routes/CreateCommentArticle.kt index fd10799..493f9aa 100644 --- a/src/main/kotlin/fr/dcproject/component/comment/article/routes/CreateCommentArticle.kt +++ b/src/main/kotlin/fr/dcproject/component/comment/article/routes/CreateCommentArticle.kt @@ -1,6 +1,6 @@ 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.utils.receiveOrBadRequest 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.database.CommentForUpdate 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.http.HttpStatusCode import io.ktor.locations.KtorExperimentalLocationsAPI @@ -26,27 +29,36 @@ object CreateCommentArticle { @Location("/articles/{article}/comments") class PostArticleCommentRequest(article: UUID) { val article = ArticleRef(article) - class Input(val content: String) + class Input(val content: String) { + fun validate() = Validation { + Input::content { + minLength(20) + maxLength(6000) + } + }.validate(this) + } } fun Route.createCommentArticle(repo: CommentArticleRepository, ac: CommentAccessControl) { post { mustBeAuth() - call.receiveOrBadRequest().run { - CommentForUpdate( - target = it.article, - createdBy = citizen, - content = content - ) - }.let { comment -> - ac.assert { canCreate(comment, citizenOrNull) } - repo.comment(comment) + call.receiveOrBadRequest() + .apply { validate().badRequestIfNotValid() } + .run { + CommentForUpdate( + target = it.article, + createdBy = citizen, + content = content + ) + }.let { comment -> + ac.assert { canCreate(comment, citizenOrNull) } + repo.comment(comment) - call.respond( - HttpStatusCode.Created, - comment.toOutput() - ) - } + call.respond( + HttpStatusCode.Created, + comment.toOutput() + ) + } } } } diff --git a/src/main/resources/openapi.yaml b/src/main/resources/openapi.yaml index af39955..810cb48 100644 --- a/src/main/resources/openapi.yaml +++ b/src/main/resources/openapi.yaml @@ -563,6 +563,12 @@ paths: application/json: schema: $ref: '#/components/schemas/CommentResponse' + 400: + description: BadReqest + content: + application/json: + schema: + $ref: '#/components/schemas/400' 401: $ref: '#/components/responses/401' /comments/{comment}: diff --git a/src/test/kotlin/integration/Comment articles routes.kt b/src/test/kotlin/integration/Comment articles routes.kt index 6c7c00e..0962e86 100644 --- a/src/test/kotlin/integration/Comment articles routes.kt +++ b/src/test/kotlin/integration/Comment articles routes.kt @@ -1,6 +1,8 @@ package integration 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 POST 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.`Then the response should be` 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.OK import org.junit.jupiter.api.Tag @@ -33,14 +36,37 @@ class `Comment articles routes` : BaseTest() { `with body`( """ { - "content": "Hello mister" + "content": "Hello mister MARABOUTCHA" } """ ) } `Then the response should be` Created and { `And the response should not be null`() `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") } } }