diff --git a/build.gradle.kts b/build.gradle.kts index 1d811c4..283e4c8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -356,6 +356,12 @@ tasks.register("testNotifications", Test::class) { includeTags("notification") } } +tasks.register("testOpinions", Test::class) { + group = "tests" + useJUnitPlatform { + includeTags("opinion") + } +} dependencyCheck { formats = listOf(ReportGenerator.Format.HTML, ReportGenerator.Format.XML) diff --git a/src/main/kotlin/fr/dcproject/component/opinion/routes/GetMyOpinionsArticle.kt b/src/main/kotlin/fr/dcproject/component/opinion/routes/GetMyOpinionsArticle.kt index 7679ace..fe28926 100644 --- a/src/main/kotlin/fr/dcproject/component/opinion/routes/GetMyOpinionsArticle.kt +++ b/src/main/kotlin/fr/dcproject/component/opinion/routes/GetMyOpinionsArticle.kt @@ -1,5 +1,6 @@ package fr.dcproject.component.opinion.routes +import fr.dcproject.application.http.badRequestIfNotValid import fr.dcproject.common.entity.TargetRef import fr.dcproject.common.response.toOutput import fr.dcproject.common.security.assert @@ -12,6 +13,9 @@ import fr.dcproject.component.opinion.database.Opinion import fr.dcproject.routes.PaginatedRequest import fr.dcproject.routes.PaginatedRequestI import fr.postgresjson.connexion.Paginated +import io.konform.validation.Validation +import io.konform.validation.jsonschema.maximum +import io.konform.validation.jsonschema.minimum import io.ktor.application.call import io.ktor.http.HttpStatusCode import io.ktor.locations.KtorExperimentalLocationsAPI @@ -34,11 +38,22 @@ object GetMyOpinionsArticle { limit: Int = 50 ) : PaginatedRequestI by PaginatedRequest(page, limit) { val citizen = CitizenRef(citizen) + fun validate() = Validation { + CitizenOpinionsArticleRequest::page { + minimum(1) + } + CitizenOpinionsArticleRequest::limit { + minimum(1) + maximum(50) + } + }.validate(this) } fun Route.getMyOpinionsArticle(repo: OpinionArticleRepository, ac: OpinionAccessControl) { get { mustBeAuth() + it.validate().badRequestIfNotValid() + val opinions: Paginated> = repo.findCitizenOpinions(citizen, it.page, it.limit) ac.assert { canView(opinions.result, citizenOrNull) } call.respond( diff --git a/src/main/resources/openapi.yaml b/src/main/resources/openapi.yaml index 0dbd143..e4a1fd1 100644 --- a/src/main/resources/openapi.yaml +++ b/src/main/resources/openapi.yaml @@ -1118,6 +1118,9 @@ paths: tags: - opinion - citizen + parameters: + - $ref: '#/components/parameters/page' + - $ref: '#/components/parameters/limit' responses: 200: description: Opinions @@ -1132,6 +1135,13 @@ paths: type: array items: $ref: '#/components/schemas/Opinion' + 400: + description: BadReqest + content: + application/json: + schema: + $ref: '#/components/schemas/400' + /articles/{article}/opinions: parameters: - $ref: '#/components/parameters/article' diff --git a/src/test/kotlin/integration/Opinion routes.kt b/src/test/kotlin/integration/Opinion routes.kt index 4613372..14e8d13 100644 --- a/src/test/kotlin/integration/Opinion routes.kt +++ b/src/test/kotlin/integration/Opinion 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_PARAM import integration.steps.`when`.`When I send a GET request` import integration.steps.`when`.`When I send a PUT request` import integration.steps.`when`.`with body` @@ -11,8 +13,10 @@ import integration.steps.given.`Given I have opinion on article` import integration.steps.given.`authenticated as` import integration.steps.then.`And the response should contain list` 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 import io.ktor.http.HttpStatusCode.Companion.Created import io.ktor.http.HttpStatusCode.Companion.OK import org.junit.jupiter.api.Tag @@ -133,7 +137,7 @@ class `Opinion routes` : BaseTest() { article = "8651b530-ac1b-4214-a784-706781371074", Name("Albert", "Einstein") ) - `When I send a GET request`("/citizens/c1542096-3431-432d-8e35-9dc071d4c818/opinions/articles") { + `When I send a GET request`("/citizens/c1542096-3431-432d-8e35-9dc071d4c818/opinions/articles?page=1&limit=10") { `authenticated as`("Albert", "Einstein") } `Then the response should be` OK and { `And the response should contain`("$.result[0].name", "Opinion9") @@ -141,4 +145,26 @@ class `Opinion routes` : BaseTest() { } } } + + @Test + @Tags(Tag("article"), Tag("BadRequest")) + fun `I cannot get all my opinion of one article with wrong request`() { + withIntegrationApplication { + `Given I have citizen`("Albert", "Einstein", id = "c1542096-3431-432d-8e35-9dc071d4c818") + `Given I have an opinion choice`("Opinion9") + `Given I have article`("8651b530-ac1b-4214-a784-706781371074") + `Given I have opinion on article`( + "Opinion9", + article = "8651b530-ac1b-4214-a784-706781371074", + Name("Albert", "Einstein") + ) + `When I send a GET request`("/citizens/c1542096-3431-432d-8e35-9dc071d4c818/opinions/articles?page=1&limit=60", ALL - REQUEST_PARAM) { + `authenticated as`("Albert", "Einstein") + } `Then the response should be` HttpStatusCode.BadRequest and { + `And the response should not be null`() + `And the response should contain`("$.invalidParams[0].name", ".limit") + `And the response should contain`("$.invalidParams[0].reason", "must be at most '50'") + } + } + } }