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::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 { 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 { 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 } } ) } } } }