Valider les resource entrente #91
@@ -38,7 +38,6 @@ object FindArticles {
|
||||
fun validate() = Validation<ArticlesRequest> {
|
||||
ArticlesRequest::page {
|
||||
minimum(1)
|
||||
maximum(100)
|
||||
}
|
||||
ArticlesRequest::limit {
|
||||
minimum(1)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package fr.dcproject.component.article.routes
|
||||
|
||||
import fr.dcproject.application.http.badRequestIfNotValid
|
||||
import fr.dcproject.common.security.assert
|
||||
import fr.dcproject.common.utils.receiveOrBadRequest
|
||||
import fr.dcproject.component.article.ArticleAccessControl
|
||||
@@ -12,6 +13,11 @@ import fr.dcproject.component.auth.mustBeAuth
|
||||
import fr.dcproject.component.notification.ArticleUpdateNotification
|
||||
import fr.dcproject.component.notification.Publisher
|
||||
import fr.dcproject.component.workgroup.database.WorkgroupRef
|
||||
import io.konform.validation.Validation
|
||||
import io.konform.validation.jsonschema.maxItems
|
||||
import io.konform.validation.jsonschema.maxLength
|
||||
import io.konform.validation.jsonschema.minItems
|
||||
import io.konform.validation.jsonschema.minLength
|
||||
import io.ktor.application.ApplicationCall
|
||||
import io.ktor.application.call
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -35,11 +41,31 @@ object UpsertArticle {
|
||||
val draft: Boolean = false,
|
||||
val versionId: UUID,
|
||||
val workgroup: WorkgroupRef? = null,
|
||||
)
|
||||
) {
|
||||
fun validate() = Validation<Input> {
|
||||
Input::title {
|
||||
minLength(5)
|
||||
maxLength(80)
|
||||
}
|
||||
Input::content {
|
||||
minLength(50)
|
||||
maxLength(6000)
|
||||
}
|
||||
Input::description {
|
||||
minLength(50)
|
||||
maxLength(6000)
|
||||
}
|
||||
Input::tags {
|
||||
minItems(0)
|
||||
maxItems(15)
|
||||
}
|
||||
}.validate(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.upsertArticle(repo: ArticleRepository, publisher: Publisher, ac: ArticleAccessControl) {
|
||||
suspend fun ApplicationCall.convertRequestToEntity(): ArticleForUpdate = receiveOrBadRequest<Input>().run {
|
||||
validate().badRequestIfNotValid()
|
||||
ArticleForUpdate(
|
||||
id = id ?: UUID.randomUUID(),
|
||||
title = title,
|
||||
|
||||
@@ -71,16 +71,21 @@ paths:
|
||||
Limit power of press
|
||||
content:
|
||||
type: string
|
||||
minLength: 50
|
||||
maxLength: 6000
|
||||
example:
|
||||
Lorem upsum...
|
||||
description:
|
||||
type: string
|
||||
minLength: 50
|
||||
maxLength: 6000
|
||||
example:
|
||||
I think is the bether choice
|
||||
tags:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
maxItems: 15
|
||||
default: [ ]
|
||||
example: [ power, press ]
|
||||
anonymous:
|
||||
@@ -112,6 +117,12 @@ paths:
|
||||
format: uuid
|
||||
versionNumber:
|
||||
type: integer
|
||||
400:
|
||||
description: BadReqest
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/400'
|
||||
401:
|
||||
$ref: '#/components/responses/401'
|
||||
403:
|
||||
|
||||
@@ -145,8 +145,8 @@ class `Article routes` : BaseTest() {
|
||||
"versionId": "09c418b6-63ba-448b-b38b-502b41cd500e",
|
||||
"title": "title2",
|
||||
"anonymous": false,
|
||||
"content": "content2",
|
||||
"description": "description2",
|
||||
"content": "Sed malesuada ante et sem congue, scelerisque feugiat lorem viverra.",
|
||||
"description": "Sed vulputate, ligula id porta posuere, sapien lorem mattis arcu, sit amet luctus erat orci sed tellus.",
|
||||
"tags": [
|
||||
"green"
|
||||
]
|
||||
@@ -161,6 +161,7 @@ class `Article routes` : BaseTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Tag("Forbidden")
|
||||
fun `I cannot create an article if I'm not connected`() {
|
||||
withIntegrationApplication {
|
||||
`When I send a POST request`("/articles") {
|
||||
@@ -170,8 +171,8 @@ class `Article routes` : BaseTest() {
|
||||
"versionId": "e3c7ce42-241c-4caf-9a59-aba4e466440e",
|
||||
"title": "title2",
|
||||
"anonymous": false,
|
||||
"content": "content2",
|
||||
"description": "description2",
|
||||
"content": "Sed malesuada ante et sem congue, scelerisque feugiat lorem viverra.",
|
||||
"description": "Sed vulputate, ligula id porta posuere, sapien lorem mattis arcu, sit amet luctus erat orci sed tellus.",
|
||||
"tags": [
|
||||
"green"
|
||||
]
|
||||
@@ -185,4 +186,35 @@ class `Article routes` : BaseTest() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Tag("BadRequest")
|
||||
fun `I cannot create an article with wrong request`() {
|
||||
withIntegrationApplication {
|
||||
`Given I have citizen`("John", "Doe")
|
||||
`When I send a POST request`("/articles", Validate.NONE) {
|
||||
`authenticated as`("John", "Doe")
|
||||
`with body`(
|
||||
"""
|
||||
{
|
||||
"versionId": "09c418b6-63ba-448b-b38b-502b41cd500e",
|
||||
"title": "title2",
|
||||
"anonymous": false,
|
||||
"content": "content2",
|
||||
"description": "description2",
|
||||
"tags": [
|
||||
"green"
|
||||
]
|
||||
}
|
||||
"""
|
||||
)
|
||||
} `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 50 characters")
|
||||
`And the response should contain`("$.invalidParams[1].name", ".description")
|
||||
`And the response should contain`("$.invalidParams[1].reason", "must have at least 50 characters")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import io.ktor.server.testing.TestApplicationRequest
|
||||
import io.ktor.server.testing.setBody
|
||||
|
||||
enum class Validate(override val bit: Long) : BitMaskI {
|
||||
NONE(0),
|
||||
REQUEST_BODY(1),
|
||||
REQUEST_PARAM(2),
|
||||
REQUEST_HEADER(4),
|
||||
|
||||
Reference in New Issue
Block a user