diff --git a/src/main/kotlin/fr/dcproject/application/http/HttpStatusError.kt b/src/main/kotlin/fr/dcproject/application/http/HttpStatusError.kt index 01803c2..215add9 100644 --- a/src/main/kotlin/fr/dcproject/application/http/HttpStatusError.kt +++ b/src/main/kotlin/fr/dcproject/application/http/HttpStatusError.kt @@ -11,23 +11,72 @@ import io.ktor.http.HttpStatusCode import io.ktor.response.respond import java.util.concurrent.CompletionException +class HttpError( + statusCode: HttpStatusCode, + val cause: Throwable? = null, + val type: String? = null, + val title: String = cause?.message ?: statusCode.description, + val detail: String? = null, + val invalidParams: List? = null, + val stackTrace: String? = cause?.stackTraceToString() +) { + val statusCode: Int = statusCode.value + data class InvalidParam( + val name: String, + val reason: String + ) +} + fun statusPagesInstallation(): StatusPages.Configuration.() -> Unit = { exception { e -> val parent = e.cause?.cause if (parent is GenericDatabaseException) { - call.respond(HttpStatusCode.BadRequest, parent.errorMessage.message!!) + HttpError( + HttpStatusCode.BadRequest, + cause = parent + ).let { + call.respond(HttpStatusCode.BadRequest, it) + } } else { - throw e + HttpError( + HttpStatusCode.BadRequest, + cause = e + ).let { + call.respond(HttpStatusCode.InternalServerError, it) + } } } exception { e -> - call.respond(HttpStatusCode.NotFound, e.message!!) + HttpError( + HttpStatusCode.NotFound, + cause = e + ).let { + call.respond(HttpStatusCode.NotFound, it) + } } - exception { - if (call.user == null) call.respond(HttpStatusCode.Unauthorized) - else call.respond(HttpStatusCode.Forbidden) + exception { e -> + if (call.user == null) { + HttpError( + HttpStatusCode.Unauthorized, + cause = e + ).let { + call.respond(HttpStatusCode.Unauthorized, it) + } + } else { + HttpError( + HttpStatusCode.Forbidden, + cause = e + ).let { + call.respond(HttpStatusCode.Forbidden, it) + } + } } - exception { - call.respond(HttpStatusCode.Forbidden) + exception { e -> + HttpError( + HttpStatusCode.Forbidden, + cause = e + ).let { + call.respond(HttpStatusCode.Forbidden, it) + } } } diff --git a/src/main/resources/openapi.yaml b/src/main/resources/openapi.yaml index e016f54..2d7d924 100644 --- a/src/main/resources/openapi.yaml +++ b/src/main/resources/openapi.yaml @@ -108,6 +108,18 @@ paths: type: integer 401: $ref: '#/components/responses/401' + 403: + description: Forbiden + content: + application/json: + schema: + description: Forbiden + properties: + statusCode: + type: integer + title: + type: string + /articles/{article}: parameters: - $ref: '#/components/parameters/article' diff --git a/src/test/kotlin/integration/Article routes.kt b/src/test/kotlin/integration/Article routes.kt index 5c9140b..661e4f9 100644 --- a/src/test/kotlin/integration/Article routes.kt +++ b/src/test/kotlin/integration/Article routes.kt @@ -12,11 +12,13 @@ import integration.steps.given.`authenticated as` import integration.steps.then.`And have property` import integration.steps.then.`And the response should contain list` import integration.steps.then.`And the response should contain pattern` +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 contain` import integration.steps.then.`Then the response should be` import integration.steps.then.`whish contains` import integration.steps.then.and +import io.ktor.http.HttpStatusCode.Companion.Forbidden import io.ktor.http.HttpStatusCode.Companion.OK import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Tags @@ -104,4 +106,30 @@ class `Article routes` : BaseTest() { } } } + + @Test + fun `I cannot create an article if I'm not connected`() { + withIntegrationApplication { + `When I send a POST request`("/articles") { + `with body`( + """ + { + "versionId": "e3c7ce42-241c-4caf-9a59-aba4e466440e", + "title": "title2", + "anonymous": false, + "content": "content2", + "description": "description2", + "tags": [ + "green" + ] + } + """ + ) + } `Then the response should be` Forbidden and { + `And the response should not be null`() + `And the response should contain`("$.statusCode", 403) + `And the response should contain`("$.title", "No User Connected") + } + } + } }