101 lines
3.5 KiB
Kotlin
101 lines
3.5 KiB
Kotlin
package fr.dcproject.component.article.routes
|
|
|
|
import fr.dcproject.application.http.badRequestIfNotValid
|
|
import fr.dcproject.common.response.toOutput
|
|
import fr.dcproject.common.security.assert
|
|
import fr.dcproject.common.validation.isUuid
|
|
import fr.dcproject.component.article.ArticleAccessControl
|
|
import fr.dcproject.component.article.database.ArticleForListing
|
|
import fr.dcproject.component.article.database.ArticleRepository
|
|
import fr.dcproject.component.auth.citizenOrNull
|
|
import fr.dcproject.routes.PaginatedRequest
|
|
import fr.dcproject.routes.PaginatedRequestI
|
|
import fr.postgresjson.connexion.Paginated
|
|
import fr.postgresjson.repository.RepositoryI
|
|
import io.konform.validation.Validation
|
|
import io.konform.validation.jsonschema.enum
|
|
import io.konform.validation.jsonschema.maximum
|
|
import io.konform.validation.jsonschema.minimum
|
|
import io.ktor.application.call
|
|
import io.ktor.locations.KtorExperimentalLocationsAPI
|
|
import io.ktor.locations.Location
|
|
import io.ktor.locations.get
|
|
import io.ktor.response.respond
|
|
import io.ktor.routing.Route
|
|
|
|
@KtorExperimentalLocationsAPI
|
|
object FindArticles {
|
|
@Location("/articles")
|
|
class ArticlesRequest(
|
|
page: Int = 1,
|
|
limit: Int = 50,
|
|
val sort: String? = null,
|
|
val direction: RepositoryI.Direction? = null,
|
|
val search: String? = null,
|
|
val createdBy: String? = null,
|
|
val workgroup: String? = null
|
|
) : PaginatedRequestI by PaginatedRequest(page, limit) {
|
|
fun validate() = Validation<ArticlesRequest> {
|
|
ArticlesRequest::page {
|
|
minimum(1)
|
|
}
|
|
ArticlesRequest::limit {
|
|
minimum(1)
|
|
maximum(50)
|
|
}
|
|
ArticlesRequest::sort ifPresent {
|
|
enum(
|
|
"title",
|
|
"createdAt",
|
|
"vote",
|
|
"popularity",
|
|
)
|
|
}
|
|
ArticlesRequest::createdBy ifPresent {
|
|
isUuid()
|
|
}
|
|
ArticlesRequest::workgroup ifPresent {
|
|
isUuid()
|
|
}
|
|
}.validate(this)
|
|
}
|
|
|
|
private fun ArticleRepository.findArticles(request: ArticlesRequest): Paginated<ArticleForListing> {
|
|
return find(
|
|
request.page,
|
|
request.limit,
|
|
request.sort,
|
|
request.direction,
|
|
request.search,
|
|
ArticleRepository.Filter(createdById = request.createdBy, workgroupId = request.workgroup)
|
|
)
|
|
}
|
|
|
|
fun Route.findArticles(repo: ArticleRepository, ac: ArticleAccessControl) {
|
|
get<ArticlesRequest> {
|
|
it.validate().badRequestIfNotValid()
|
|
|
|
repo.findArticles(it)
|
|
.apply { ac.assert { canView(result, citizenOrNull) } }
|
|
.let {
|
|
call.respond(
|
|
it.toOutput {
|
|
object {
|
|
val id = it.id
|
|
val title = it.title
|
|
val createdBy: Any = it.createdBy.toOutput()
|
|
val workgroup = it.workgroup?.let {
|
|
object {
|
|
val id = it.id
|
|
val name = it.name
|
|
}
|
|
}
|
|
val draft = it.draft
|
|
}
|
|
}
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|