Rename Voter to AccessControl
This commit is contained in:
@@ -3,20 +3,20 @@ package fr.dcproject.component.article
|
||||
import fr.dcproject.component.citizen.CitizenI
|
||||
import fr.dcproject.entity.CreatedBy
|
||||
import fr.dcproject.entity.VersionableRef
|
||||
import fr.dcproject.voter.Voter
|
||||
import fr.dcproject.voter.VoterResponse
|
||||
import fr.dcproject.security.AccessControl
|
||||
import fr.dcproject.security.AccessResponse
|
||||
|
||||
class ArticleVoter(private val articleRepo: ArticleRepository) : Voter() {
|
||||
fun <S : ArticleAuthI<*>> canView(subjects: List<S>, citizen: CitizenI?): VoterResponse =
|
||||
class ArticleAccessControl(private val articleRepo: ArticleRepository) : AccessControl() {
|
||||
fun <S : ArticleAuthI<*>> canView(subjects: List<S>, citizen: CitizenI?): AccessResponse =
|
||||
canAll(subjects) { canView(it, citizen) }
|
||||
|
||||
fun <S : ArticleAuthI<*>> canView(subject: S, citizen: CitizenI?): VoterResponse {
|
||||
fun <S : ArticleAuthI<*>> canView(subject: S, citizen: CitizenI?): AccessResponse {
|
||||
return if (subject.isDeleted()) denied("Article is deleted", "article.deleted")
|
||||
else if (subject.draft && (citizen == null || subject.createdBy.id != citizen.id)) denied("Article is draft, but it's not yours", "article.draft.not.yours")
|
||||
else granted()
|
||||
}
|
||||
|
||||
fun <S : CreatedBy<*>> canDelete(subject: S, citizen: CitizenI?): VoterResponse {
|
||||
fun <S : CreatedBy<*>> canDelete(subject: S, citizen: CitizenI?): AccessResponse {
|
||||
if (citizen == null) return denied("You must be connected to create article", "article.create.notConnected")
|
||||
return if (subject.createdBy.id == citizen.id) {
|
||||
granted()
|
||||
@@ -25,7 +25,7 @@ class ArticleVoter(private val articleRepo: ArticleRepository) : Voter() {
|
||||
}
|
||||
}
|
||||
|
||||
fun <S> canUpsert(subject: S, citizen: CitizenI?): VoterResponse
|
||||
fun <S> canUpsert(subject: S, citizen: CitizenI?): AccessResponse
|
||||
where S : ArticleI,
|
||||
S : CreatedBy<*>,
|
||||
S : VersionableRef {
|
||||
@@ -1,10 +1,10 @@
|
||||
package fr.dcproject.component.article.routes
|
||||
|
||||
import fr.dcproject.component.article.ArticleAccessControl
|
||||
import fr.dcproject.component.article.ArticleForView
|
||||
import fr.dcproject.component.article.ArticleRepository
|
||||
import fr.dcproject.component.article.ArticleVoter
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import fr.postgresjson.repository.RepositoryI
|
||||
import io.ktor.application.call
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -31,10 +31,10 @@ object FindArticleVersions {
|
||||
private fun ArticleRepository.findVersions(request: ArticleVersionsRequest) =
|
||||
findVersionsByVersionId(request.page, request.limit, request.article.versionId)
|
||||
|
||||
fun Route.findArticleVersions(repo: ArticleRepository, voter: ArticleVoter) {
|
||||
fun Route.findArticleVersions(repo: ArticleRepository, ac: ArticleAccessControl) {
|
||||
get<ArticleVersionsRequest> {
|
||||
repo.findVersions(it)
|
||||
.apply { voter.assert { canView(it.article, citizenOrNull) } }
|
||||
.apply { ac.assert { canView(it.article, citizenOrNull) } }
|
||||
.let { call.respond(it) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package fr.dcproject.component.article.routes
|
||||
|
||||
import fr.dcproject.component.article.ArticleAccessControl
|
||||
import fr.dcproject.component.article.ArticleForListing
|
||||
import fr.dcproject.component.article.ArticleRepository
|
||||
import fr.dcproject.component.article.ArticleVoter
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.routes.PaginatedRequest
|
||||
import fr.dcproject.routes.PaginatedRequestI
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import fr.postgresjson.connexion.Paginated
|
||||
import fr.postgresjson.repository.RepositoryI
|
||||
import io.ktor.application.call
|
||||
@@ -40,10 +40,10 @@ object FindArticles {
|
||||
)
|
||||
}
|
||||
|
||||
fun Route.findArticles(repo: ArticleRepository, voter: ArticleVoter) {
|
||||
fun Route.findArticles(repo: ArticleRepository, ac: ArticleAccessControl) {
|
||||
get<ArticlesRequest> {
|
||||
repo.findArticles(it)
|
||||
.apply { voter.assert { canView(result, citizenOrNull) } }
|
||||
.apply { ac.assert { canView(result, citizenOrNull) } }
|
||||
.let { call.respond(it) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package fr.dcproject.component.article.routes
|
||||
|
||||
import fr.dcproject.component.article.ArticleAccessControl
|
||||
import fr.dcproject.component.article.ArticleForView
|
||||
import fr.dcproject.component.article.ArticleRepository
|
||||
import fr.dcproject.component.article.ArticleViewManager
|
||||
import fr.dcproject.component.article.ArticleVoter
|
||||
import fr.dcproject.component.article.routes.GetOneArticle.ArticleRequest.Output
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.opinion.dto.Opinionable
|
||||
@@ -11,7 +11,7 @@ import fr.dcproject.component.vote.dto.Votable
|
||||
import fr.dcproject.dto.CreatedAt
|
||||
import fr.dcproject.dto.Versionable
|
||||
import fr.dcproject.dto.Viewable
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.features.NotFoundException
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -53,9 +53,9 @@ object GetOneArticle {
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.getOneArticle(viewManager: ArticleViewManager, voter: ArticleVoter) {
|
||||
fun Route.getOneArticle(viewManager: ArticleViewManager, ac: ArticleAccessControl) {
|
||||
get<ArticleRequest> {
|
||||
voter.assert { canView(it.article, citizenOrNull) }
|
||||
ac.assert { canView(it.article, citizenOrNull) }
|
||||
|
||||
Output(
|
||||
it.article,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package fr.dcproject.component.article.routes
|
||||
|
||||
import fr.dcproject.component.article.ArticleAccessControl
|
||||
import fr.dcproject.component.article.ArticleForUpdate
|
||||
import fr.dcproject.component.article.ArticleForView
|
||||
import fr.dcproject.component.article.ArticleRepository
|
||||
import fr.dcproject.component.article.ArticleVoter
|
||||
import fr.dcproject.component.article.routes.UpsertArticle.UpsertArticleRequest.Input
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
@@ -11,7 +11,7 @@ import fr.dcproject.component.workgroup.WorkgroupRef
|
||||
import fr.dcproject.component.workgroup.WorkgroupRepository
|
||||
import fr.dcproject.event.ArticleUpdate
|
||||
import fr.dcproject.event.raiseEvent
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.ApplicationCall
|
||||
import io.ktor.application.call
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -39,7 +39,7 @@ object UpsertArticle {
|
||||
)
|
||||
}
|
||||
|
||||
fun Route.upsertArticle(repo: ArticleRepository, workgroupRepository: WorkgroupRepository, voter: ArticleVoter) {
|
||||
fun Route.upsertArticle(repo: ArticleRepository, workgroupRepository: WorkgroupRepository, ac: ArticleAccessControl) {
|
||||
suspend fun ApplicationCall.convertRequestToEntity(): ArticleForUpdate = receive<Input>().run {
|
||||
ArticleForUpdate(
|
||||
id = id ?: UUID.randomUUID(),
|
||||
@@ -57,7 +57,7 @@ object UpsertArticle {
|
||||
|
||||
post<UpsertArticleRequest> {
|
||||
val article = call.convertRequestToEntity()
|
||||
voter.assert { canUpsert(article, citizenOrNull) }
|
||||
ac.assert { canUpsert(article, citizenOrNull) }
|
||||
val newArticle: ArticleForView = repo.upsert(article) ?: error("Article not updated")
|
||||
call.respond(newArticle)
|
||||
raiseEvent(ArticleUpdate.event, ArticleUpdate(newArticle))
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
package fr.dcproject.component.citizen
|
||||
|
||||
import fr.dcproject.voter.Voter
|
||||
import fr.dcproject.voter.VoterResponse
|
||||
import fr.dcproject.security.AccessControl
|
||||
import fr.dcproject.security.AccessResponse
|
||||
import fr.postgresjson.entity.EntityDeletedAt
|
||||
|
||||
class CitizenVoter : Voter() {
|
||||
fun <S> canView(subjects: List<S>, connectedCitizen: CitizenI?): VoterResponse where S : CitizenI, S : EntityDeletedAt =
|
||||
class CitizenAccessControl : AccessControl() {
|
||||
fun <S> canView(subjects: List<S>, connectedCitizen: CitizenI?): AccessResponse where S : CitizenI, S : EntityDeletedAt =
|
||||
canAll(subjects) { canView(it, connectedCitizen) }
|
||||
|
||||
fun <S> canView(subject: S, connectedCitizen: CitizenI?): VoterResponse where S : CitizenI, S : EntityDeletedAt {
|
||||
fun <S> canView(subject: S, connectedCitizen: CitizenI?): AccessResponse where S : CitizenI, S : EntityDeletedAt {
|
||||
if (connectedCitizen == null) return denied("You must be connected to view citizen", "citizen.view.connected")
|
||||
return if (subject.isDeleted()) denied("You cannot view a deleted citizen", "citizen.view.deleted")
|
||||
else granted()
|
||||
}
|
||||
|
||||
fun <S : CitizenI> canUpdate(subject: S, connectedCitizen: CitizenI?): VoterResponse {
|
||||
fun <S : CitizenI> canUpdate(subject: S, connectedCitizen: CitizenI?): AccessResponse {
|
||||
if (connectedCitizen == null) return denied("You must be connected to update Citizen", "citizen.update.notConnected")
|
||||
return if (subject.id == connectedCitizen.id) granted() else denied("You can only update your citizen", "citizen.update.notYours")
|
||||
}
|
||||
|
||||
fun <S : CitizenI> canChangePassword(subject: S, connectedCitizen: CitizenI?): VoterResponse {
|
||||
fun <S : CitizenI> canChangePassword(subject: S, connectedCitizen: CitizenI?): AccessResponse {
|
||||
if (connectedCitizen == null) return denied("You must be connected to change your password", "citizen.changePassword.notConnected")
|
||||
return if (subject.id == connectedCitizen.id) granted() else denied("You can only change your password", "citizen.password.notYours")
|
||||
}
|
||||
@@ -5,8 +5,8 @@ import fr.dcproject.component.auth.UserRepository
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.citizen.Citizen
|
||||
import fr.dcproject.component.citizen.CitizenVoter
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.component.citizen.CitizenAccessControl
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.auth.UserPasswordCredential
|
||||
import io.ktor.http.HttpStatusCode
|
||||
@@ -24,9 +24,9 @@ object ChangeMyPassword {
|
||||
data class Input(val oldPassword: String, val newPassword: String)
|
||||
}
|
||||
|
||||
fun Route.changeMyPassword(voter: CitizenVoter, userRepository: UserRepository) {
|
||||
fun Route.changeMyPassword(ac: CitizenAccessControl, userRepository: UserRepository) {
|
||||
put<ChangePasswordCitizenRequest> {
|
||||
voter.assert { canChangePassword(it.citizen, citizenOrNull) }
|
||||
ac.assert { canChangePassword(it.citizen, citizenOrNull) }
|
||||
try {
|
||||
val content = call.receive<ChangePasswordCitizenRequest.Input>()
|
||||
val currentUser = userRepository.findByCredentials(UserPasswordCredential(citizen.user.username, content.oldPassword))
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package fr.dcproject.component.citizen.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.citizen.CitizenAccessControl
|
||||
import fr.dcproject.component.citizen.CitizenRepository
|
||||
import fr.dcproject.component.citizen.CitizenVoter
|
||||
import fr.dcproject.routes.PaginatedRequest
|
||||
import fr.dcproject.routes.PaginatedRequestI
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import fr.postgresjson.repository.RepositoryI
|
||||
import io.ktor.application.call
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -25,10 +25,10 @@ object FindCitizens {
|
||||
val search: String? = null
|
||||
) : PaginatedRequestI by PaginatedRequest(page, limit)
|
||||
|
||||
fun Route.findCitizen(voter: CitizenVoter, repo: CitizenRepository) {
|
||||
fun Route.findCitizen(ac: CitizenAccessControl, repo: CitizenRepository) {
|
||||
get<CitizensRequest> {
|
||||
val citizens = repo.find(it.page, it.limit, it.sort, it.direction, it.search)
|
||||
voter.assert { canView(citizens.result, citizenOrNull) }
|
||||
ac.assert { canView(citizens.result, citizenOrNull) }
|
||||
call.respond(citizens)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package fr.dcproject.component.citizen.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.citizen.CitizenVoter
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.component.citizen.CitizenAccessControl
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -17,13 +17,13 @@ object GetCurrentCitizen {
|
||||
@Location("/citizens/current")
|
||||
class CurrentCitizenRequest
|
||||
|
||||
fun Route.getCurrentCitizen(voter: CitizenVoter) {
|
||||
fun Route.getCurrentCitizen(ac: CitizenAccessControl) {
|
||||
get<CurrentCitizenRequest> {
|
||||
val currentUser = citizenOrNull
|
||||
if (currentUser === null) {
|
||||
call.respond(HttpStatusCode.Unauthorized)
|
||||
} else {
|
||||
voter.assert { canView(currentUser, citizenOrNull) }
|
||||
ac.assert { canView(currentUser, citizenOrNull) }
|
||||
call.respond(citizen)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package fr.dcproject.component.citizen.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.citizen.Citizen
|
||||
import fr.dcproject.component.citizen.CitizenVoter
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.component.citizen.CitizenAccessControl
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.Location
|
||||
@@ -16,9 +16,9 @@ object GetOneCitizen {
|
||||
@Location("/citizens/{citizen}")
|
||||
class CitizenRequest(val citizen: Citizen)
|
||||
|
||||
fun Route.getOneCitizen(voter: CitizenVoter) {
|
||||
fun Route.getOneCitizen(ac: CitizenAccessControl) {
|
||||
get<CitizenRequest> {
|
||||
voter.assert { canView(it.citizen, citizenOrNull) }
|
||||
ac.assert { canView(it.citizen, citizenOrNull) }
|
||||
|
||||
call.respond(it.citizen)
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ import fr.dcproject.component.article.ArticleForView
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.comment.article.CommentArticleRepository
|
||||
import fr.dcproject.component.comment.generic.CommentAccessControl
|
||||
import fr.dcproject.component.comment.generic.CommentForUpdate
|
||||
import fr.dcproject.component.comment.generic.CommentVoter
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.ApplicationCall
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
@@ -36,10 +36,10 @@ object CreateCommentArticle {
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.createCommentArticle(repo: CommentArticleRepository, voter: CommentVoter) {
|
||||
fun Route.createCommentArticle(repo: CommentArticleRepository, ac: CommentAccessControl) {
|
||||
post<PostArticleCommentRequest> {
|
||||
it.getComment(call).let { comment ->
|
||||
voter.assert { canCreate(comment, citizenOrNull) }
|
||||
ac.assert { canCreate(comment, citizenOrNull) }
|
||||
repo.comment(comment)
|
||||
call.respond(HttpStatusCode.Created, comment)
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@ package fr.dcproject.component.comment.article.routes
|
||||
import fr.dcproject.component.article.ArticleRef
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.comment.article.CommentArticleRepository
|
||||
import fr.dcproject.component.comment.generic.CommentVoter
|
||||
import fr.dcproject.component.comment.generic.CommentAccessControl
|
||||
import fr.dcproject.routes.PaginatedRequest
|
||||
import fr.dcproject.routes.PaginatedRequestI
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -28,11 +28,11 @@ object GetArticleComments {
|
||||
val sort: CommentArticleRepository.Sort = CommentArticleRepository.Sort.fromString(sort) ?: CommentArticleRepository.Sort.CREATED_AT
|
||||
}
|
||||
|
||||
fun Route.getArticleComments(repo: CommentArticleRepository, voter: CommentVoter) {
|
||||
fun Route.getArticleComments(repo: CommentArticleRepository, ac: CommentAccessControl) {
|
||||
get<ArticleCommentsRequest> {
|
||||
val comment = repo.findByTarget(it.article, it.page, it.limit, it.sort)
|
||||
if (comment.result.isNotEmpty()) {
|
||||
voter.assert { canView(comment.result, citizenOrNull) }
|
||||
ac.assert { canView(comment.result, citizenOrNull) }
|
||||
}
|
||||
call.respond(HttpStatusCode.OK, comment)
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ package fr.dcproject.component.comment.article.routes
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.citizen.Citizen
|
||||
import fr.dcproject.component.comment.article.CommentArticleRepository
|
||||
import fr.dcproject.component.comment.generic.CommentVoter
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.component.comment.generic.CommentAccessControl
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.Location
|
||||
@@ -17,10 +17,10 @@ object GetCitizenArticleComments {
|
||||
@Location("/citizens/{citizen}/comments/articles")
|
||||
class CitizenCommentArticleRequest(val citizen: Citizen)
|
||||
|
||||
fun Route.getCitizenArticleComments(repo: CommentArticleRepository, voter: CommentVoter) {
|
||||
fun Route.getCitizenArticleComments(repo: CommentArticleRepository, ac: CommentAccessControl) {
|
||||
get<CitizenCommentArticleRequest> {
|
||||
repo.findByCitizen(it.citizen).let { comments ->
|
||||
voter.assert { canView(comments.result, citizenOrNull) }
|
||||
ac.assert { canView(comments.result, citizenOrNull) }
|
||||
call.respond(comments)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,24 +2,24 @@ package fr.dcproject.component.comment.generic
|
||||
|
||||
import fr.dcproject.component.citizen.CitizenI
|
||||
import fr.dcproject.entity.HasTarget
|
||||
import fr.dcproject.voter.Voter
|
||||
import fr.dcproject.voter.VoterResponse
|
||||
import fr.dcproject.security.AccessControl
|
||||
import fr.dcproject.security.AccessResponse
|
||||
import fr.postgresjson.entity.EntityCreatedBy
|
||||
import fr.postgresjson.entity.EntityDeletedAt
|
||||
|
||||
class CommentVoter : Voter() {
|
||||
fun <S> canView(subjects: List<S>, citizen: CitizenI?): VoterResponse
|
||||
class CommentAccessControl : AccessControl() {
|
||||
fun <S> canView(subjects: List<S>, citizen: CitizenI?): AccessResponse
|
||||
where S : CommentI,
|
||||
S : EntityDeletedAt = canAll(subjects) { canView(it, citizen) }
|
||||
|
||||
fun <S> canView(subject: S, citizen: CitizenI?): VoterResponse
|
||||
fun <S> canView(subject: S, citizen: CitizenI?): AccessResponse
|
||||
where S : CommentI,
|
||||
S : EntityDeletedAt = when {
|
||||
subject.isDeleted() -> denied("Your cannot view a deleted comment", "comment.view.deleted")
|
||||
else -> granted()
|
||||
}
|
||||
|
||||
fun <S, CR : CitizenI> canCreate(subject: S, citizen: CitizenI?): VoterResponse
|
||||
fun <S, CR : CitizenI> canCreate(subject: S, citizen: CitizenI?): AccessResponse
|
||||
where S : CommentI,
|
||||
S : EntityCreatedBy<CR>,
|
||||
S : CommentWithParentI<*>,
|
||||
@@ -31,7 +31,7 @@ class CommentVoter : Voter() {
|
||||
else -> granted()
|
||||
}
|
||||
|
||||
fun <S, CR : CitizenI> canUpdate(subject: S, citizen: CitizenI?): VoterResponse
|
||||
fun <S, CR : CitizenI> canUpdate(subject: S, citizen: CitizenI?): AccessResponse
|
||||
where S : CommentI,
|
||||
S : EntityCreatedBy<CR> = when {
|
||||
citizen == null -> denied("You must be connected to update comment", "comment.update.notConnected")
|
||||
@@ -2,11 +2,11 @@ package fr.dcproject.component.comment.generic.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.comment.generic.CommentAccessControl
|
||||
import fr.dcproject.component.comment.generic.CommentForUpdate
|
||||
import fr.dcproject.component.comment.generic.CommentRef
|
||||
import fr.dcproject.component.comment.generic.CommentRepository
|
||||
import fr.dcproject.component.comment.generic.CommentVoter
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.features.NotFoundException
|
||||
import io.ktor.http.HttpStatusCode
|
||||
@@ -24,7 +24,7 @@ object CreateCommentChildren {
|
||||
class Input(val content: String)
|
||||
}
|
||||
|
||||
fun Route.createCommentChildren(repo: CommentRepository, voter: CommentVoter) {
|
||||
fun Route.createCommentChildren(repo: CommentRepository, ac: CommentAccessControl) {
|
||||
post<CreateCommentChildrenRequest> {
|
||||
val parent = repo.findById(it.comment.id) ?: throw NotFoundException("Comment not found")
|
||||
val newComment = CommentForUpdate(
|
||||
@@ -33,7 +33,7 @@ object CreateCommentChildren {
|
||||
parent = parent
|
||||
)
|
||||
|
||||
voter.assert { canCreate(newComment, citizenOrNull) }
|
||||
ac.assert { canCreate(newComment, citizenOrNull) }
|
||||
repo.comment(newComment)
|
||||
|
||||
call.respond(HttpStatusCode.Created, newComment)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package fr.dcproject.component.comment.generic.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.comment.generic.CommentAccessControl
|
||||
import fr.dcproject.component.comment.generic.CommentRef
|
||||
import fr.dcproject.component.comment.generic.CommentRepository
|
||||
import fr.dcproject.component.comment.generic.CommentVoter
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.features.NotFoundException
|
||||
import io.ktor.http.HttpStatusCode
|
||||
@@ -20,10 +20,10 @@ object EditComment {
|
||||
@Location("/comments/{comment}")
|
||||
class EditCommentRequest(val comment: CommentRef)
|
||||
|
||||
fun Route.editComment(repo: CommentRepository, voter: CommentVoter) {
|
||||
fun Route.editComment(repo: CommentRepository, ac: CommentAccessControl) {
|
||||
put<EditCommentRequest> {
|
||||
val comment = repo.findById(it.comment.id) ?: throw NotFoundException("Comment not found")
|
||||
voter.assert { canUpdate(comment, citizenOrNull) }
|
||||
ac.assert { canUpdate(comment, citizenOrNull) }
|
||||
|
||||
comment.content = call.receiveText()
|
||||
repo.edit(comment)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package fr.dcproject.component.comment.generic.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.comment.generic.CommentAccessControl
|
||||
import fr.dcproject.component.comment.generic.CommentRepository
|
||||
import fr.dcproject.component.comment.generic.CommentVoter
|
||||
import fr.dcproject.routes.PaginatedRequest
|
||||
import fr.dcproject.routes.PaginatedRequestI
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -25,7 +25,7 @@ object GetCommentChildren {
|
||||
val search: String? = null
|
||||
) : PaginatedRequestI by PaginatedRequest(page, limit)
|
||||
|
||||
fun Route.getChildrenComments(repo: CommentRepository, voter: CommentVoter) {
|
||||
fun Route.getChildrenComments(repo: CommentRepository, ac: CommentAccessControl) {
|
||||
get<CommentChildrenRequest> {
|
||||
val comments =
|
||||
repo.findByParent(
|
||||
@@ -34,7 +34,7 @@ object GetCommentChildren {
|
||||
it.limit
|
||||
)
|
||||
|
||||
voter.assert { canView(comments.result, citizenOrNull) }
|
||||
ac.assert { canView(comments.result, citizenOrNull) }
|
||||
|
||||
call.respond(HttpStatusCode.OK, comments)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package fr.dcproject.component.comment.generic.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.comment.generic.CommentAccessControl
|
||||
import fr.dcproject.component.comment.generic.CommentRef
|
||||
import fr.dcproject.component.comment.generic.CommentRepository
|
||||
import fr.dcproject.component.comment.generic.CommentVoter
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.features.NotFoundException
|
||||
import io.ktor.http.HttpStatusCode
|
||||
@@ -19,10 +19,10 @@ object GetOneComment {
|
||||
@Location("/comments/{comment}")
|
||||
class CommentRequest(val comment: CommentRef)
|
||||
|
||||
fun Route.getOneComment(repo: CommentRepository, voter: CommentVoter) {
|
||||
fun Route.getOneComment(repo: CommentRepository, ac: CommentAccessControl) {
|
||||
get<CommentRequest> {
|
||||
val comment = repo.findById(it.comment.id) ?: throw NotFoundException("Comment ${it.comment.id} not found")
|
||||
voter.assert { canView(comment, citizenOrNull) }
|
||||
ac.assert { canView(comment, citizenOrNull) }
|
||||
|
||||
call.respond(HttpStatusCode.OK, comment)
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
package fr.dcproject.component.follow
|
||||
|
||||
import fr.dcproject.component.citizen.CitizenI
|
||||
import fr.dcproject.voter.Voter
|
||||
import fr.dcproject.voter.VoterResponse
|
||||
import fr.dcproject.security.AccessControl
|
||||
import fr.dcproject.security.AccessResponse
|
||||
import fr.dcproject.component.follow.Follow as FollowEntity
|
||||
|
||||
class FollowVoter : Voter() {
|
||||
fun canCreate(subject: FollowI, citizen: CitizenI?): VoterResponse {
|
||||
class FollowAccessControl : AccessControl() {
|
||||
fun canCreate(subject: FollowI, citizen: CitizenI?): AccessResponse {
|
||||
return if (citizen == null) denied("You must be connected to follow", "follow.create.notConnected")
|
||||
else granted()
|
||||
}
|
||||
|
||||
fun canDelete(subject: FollowI, citizen: CitizenI?): VoterResponse {
|
||||
fun canDelete(subject: FollowI, citizen: CitizenI?): AccessResponse {
|
||||
return if (citizen == null) denied("You must be connected to unfollow", "follow.delete.notConnected")
|
||||
else granted()
|
||||
}
|
||||
|
||||
fun <S : FollowEntity<*>> canView(subjects: List<S>, citizen: CitizenI?): VoterResponse =
|
||||
fun <S : FollowEntity<*>> canView(subjects: List<S>, citizen: CitizenI?): AccessResponse =
|
||||
canAll(subjects) { canView(it, citizen) }
|
||||
|
||||
fun canView(subject: FollowEntity<*>, citizen: CitizenI?): VoterResponse {
|
||||
fun canView(subject: FollowEntity<*>, citizen: CitizenI?): AccessResponse {
|
||||
return if ((citizen != null && subject.createdBy.id == citizen.id) || !subject.createdBy.followAnonymous) granted()
|
||||
else denied("You cannot view an anonymous follow", "follow.view.anonymous")
|
||||
}
|
||||
@@ -3,10 +3,10 @@ package fr.dcproject.component.follow.routes.article
|
||||
import fr.dcproject.component.article.ArticleRef
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.follow.FollowAccessControl
|
||||
import fr.dcproject.component.follow.FollowArticleRepository
|
||||
import fr.dcproject.component.follow.FollowForUpdate
|
||||
import fr.dcproject.component.follow.FollowVoter
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -20,10 +20,10 @@ object FollowArticle {
|
||||
@Location("/articles/{article}/follows")
|
||||
class ArticleFollowRequest(val article: ArticleRef)
|
||||
|
||||
fun Route.followArticle(repo: FollowArticleRepository, voter: FollowVoter) {
|
||||
fun Route.followArticle(repo: FollowArticleRepository, ac: FollowAccessControl) {
|
||||
post<ArticleFollowRequest> {
|
||||
val follow = FollowForUpdate(target = it.article, createdBy = this.citizen)
|
||||
voter.assert { canCreate(follow, citizenOrNull) }
|
||||
ac.assert { canCreate(follow, citizenOrNull) }
|
||||
repo.follow(follow)
|
||||
call.respond(HttpStatusCode.Created)
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ package fr.dcproject.component.follow.routes.article
|
||||
import fr.dcproject.component.article.ArticleRef
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.follow.FollowAccessControl
|
||||
import fr.dcproject.component.follow.FollowArticleRepository
|
||||
import fr.dcproject.component.follow.FollowVoter
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -19,10 +19,10 @@ object GetFollowArticle {
|
||||
@Location("/articles/{article}/follows")
|
||||
class ArticleFollowRequest(val article: ArticleRef)
|
||||
|
||||
fun Route.getFollowArticle(repo: FollowArticleRepository, voter: FollowVoter) {
|
||||
fun Route.getFollowArticle(repo: FollowArticleRepository, ac: FollowAccessControl) {
|
||||
get<ArticleFollowRequest> {
|
||||
repo.findFollow(citizen, it.article)?.let { follow ->
|
||||
voter.assert { canView(follow, citizenOrNull) }
|
||||
ac.assert { canView(follow, citizenOrNull) }
|
||||
call.respond(follow)
|
||||
} ?: call.respond(HttpStatusCode.NoContent)
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ package fr.dcproject.component.follow.routes.article
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.citizen.Citizen
|
||||
import fr.dcproject.component.follow.FollowAccessControl
|
||||
import fr.dcproject.component.follow.FollowArticleRepository
|
||||
import fr.dcproject.component.follow.FollowVoter
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.Location
|
||||
@@ -17,10 +17,10 @@ object GetMyFollowsArticle {
|
||||
@Location("/citizens/{citizen}/follows/articles")
|
||||
class CitizenFollowArticleRequest(val citizen: Citizen)
|
||||
|
||||
fun Route.getMyFollowsArticle(repo: FollowArticleRepository, voter: FollowVoter) {
|
||||
fun Route.getMyFollowsArticle(repo: FollowArticleRepository, ac: FollowAccessControl) {
|
||||
get<CitizenFollowArticleRequest> {
|
||||
val follows = repo.findByCitizen(it.citizen)
|
||||
voter.assert { canView(follows.result, citizenOrNull) }
|
||||
ac.assert { canView(follows.result, citizenOrNull) }
|
||||
call.respond(follows)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@ package fr.dcproject.component.follow.routes.article
|
||||
import fr.dcproject.component.article.ArticleRef
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.follow.FollowAccessControl
|
||||
import fr.dcproject.component.follow.FollowArticleRepository
|
||||
import fr.dcproject.component.follow.FollowForUpdate
|
||||
import fr.dcproject.component.follow.FollowVoter
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -20,10 +20,10 @@ object UnfollowArticle {
|
||||
@Location("/articles/{article}/follows")
|
||||
class ArticleFollowRequest(val article: ArticleRef)
|
||||
|
||||
fun Route.unfollowArticle(repo: FollowArticleRepository, voter: FollowVoter) {
|
||||
fun Route.unfollowArticle(repo: FollowArticleRepository, ac: FollowAccessControl) {
|
||||
delete<ArticleFollowRequest> {
|
||||
val follow = FollowForUpdate(target = it.article, createdBy = this.citizen)
|
||||
voter.assert { canDelete(follow, citizenOrNull) }
|
||||
ac.assert { canDelete(follow, citizenOrNull) }
|
||||
repo.unfollow(follow)
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ package fr.dcproject.component.follow.routes.constitution
|
||||
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.follow.FollowAccessControl
|
||||
import fr.dcproject.component.follow.FollowConstitutionRepository
|
||||
import fr.dcproject.component.follow.FollowForUpdate
|
||||
import fr.dcproject.component.follow.FollowVoter
|
||||
import fr.dcproject.entity.ConstitutionRef
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -20,10 +20,10 @@ object FollowConstitution {
|
||||
@Location("/constitutions/{constitution}/follows")
|
||||
class ConstitutionFollowRequest(val constitution: ConstitutionRef)
|
||||
|
||||
fun Route.followConstitution(repo: FollowConstitutionRepository, voter: FollowVoter) {
|
||||
fun Route.followConstitution(repo: FollowConstitutionRepository, ac: FollowAccessControl) {
|
||||
post<ConstitutionFollowRequest> {
|
||||
val follow = FollowForUpdate(target = it.constitution, createdBy = this.citizen)
|
||||
voter.assert { canCreate(follow, citizenOrNull) }
|
||||
ac.assert { canCreate(follow, citizenOrNull) }
|
||||
repo.follow(follow)
|
||||
call.respond(HttpStatusCode.Created)
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@ package fr.dcproject.component.follow.routes.constitution
|
||||
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.follow.FollowAccessControl
|
||||
import fr.dcproject.component.follow.FollowConstitutionRepository
|
||||
import fr.dcproject.component.follow.FollowVoter
|
||||
import fr.dcproject.entity.ConstitutionRef
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -19,10 +19,10 @@ object GetFollowConstitution {
|
||||
@Location("/constitutions/{constitution}/follows")
|
||||
class ConstitutionFollowRequest(val constitution: ConstitutionRef)
|
||||
|
||||
fun Route.getFollowConstitution(repo: FollowConstitutionRepository, voter: FollowVoter) {
|
||||
fun Route.getFollowConstitution(repo: FollowConstitutionRepository, ac: FollowAccessControl) {
|
||||
get<ConstitutionFollowRequest> {
|
||||
repo.findFollow(citizen, it.constitution)?.let { follow ->
|
||||
voter.assert { canView(follow, citizenOrNull) }
|
||||
ac.assert { canView(follow, citizenOrNull) }
|
||||
call.respond(follow)
|
||||
} ?: call.respond(HttpStatusCode.NotFound)
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ package fr.dcproject.component.follow.routes.constitution
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.citizen.CitizenRef
|
||||
import fr.dcproject.component.follow.FollowAccessControl
|
||||
import fr.dcproject.component.follow.FollowConstitutionRepository
|
||||
import fr.dcproject.component.follow.FollowVoter
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.Location
|
||||
@@ -17,10 +17,10 @@ object GetMyFollowsConstitution {
|
||||
@Location("/citizens/{citizen}/follows/constitutions")
|
||||
class CitizenFollowConstitutionRequest(val citizen: CitizenRef)
|
||||
|
||||
fun Route.getMyFollowsConstitution(repo: FollowConstitutionRepository, voter: FollowVoter) {
|
||||
fun Route.getMyFollowsConstitution(repo: FollowConstitutionRepository, ac: FollowAccessControl) {
|
||||
get<CitizenFollowConstitutionRequest> {
|
||||
val follows = repo.findByCitizen(it.citizen)
|
||||
voter.assert { canView(follows.result, citizenOrNull) }
|
||||
ac.assert { canView(follows.result, citizenOrNull) }
|
||||
call.respond(follows)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ package fr.dcproject.component.follow.routes.constitution
|
||||
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.follow.FollowAccessControl
|
||||
import fr.dcproject.component.follow.FollowConstitutionRepository
|
||||
import fr.dcproject.component.follow.FollowForUpdate
|
||||
import fr.dcproject.component.follow.FollowVoter
|
||||
import fr.dcproject.entity.ConstitutionRef
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -20,10 +20,10 @@ object UnfollowConstitution {
|
||||
@Location("/constitutions/{constitution}/follows")
|
||||
class ConstitutionUnfollowRequest(val constitution: ConstitutionRef)
|
||||
|
||||
fun Route.unfollowConstitution(repo: FollowConstitutionRepository, voter: FollowVoter) {
|
||||
fun Route.unfollowConstitution(repo: FollowConstitutionRepository, ac: FollowAccessControl) {
|
||||
delete<ConstitutionUnfollowRequest> {
|
||||
val follow = FollowForUpdate(target = it.constitution, createdBy = this.citizen)
|
||||
voter.assert { canDelete(follow, citizenOrNull) }
|
||||
ac.assert { canDelete(follow, citizenOrNull) }
|
||||
repo.unfollow(follow)
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
}
|
||||
|
||||
@@ -3,17 +3,17 @@ package fr.dcproject.component.opinion
|
||||
import fr.dcproject.component.citizen.CitizenI
|
||||
import fr.dcproject.component.opinion.entity.OpinionI
|
||||
import fr.dcproject.entity.HasTarget
|
||||
import fr.dcproject.voter.Voter
|
||||
import fr.dcproject.voter.VoterResponse
|
||||
import fr.dcproject.security.AccessControl
|
||||
import fr.dcproject.security.AccessResponse
|
||||
import fr.postgresjson.entity.EntityCreatedBy
|
||||
import fr.postgresjson.entity.EntityDeletedAt
|
||||
|
||||
class OpinionVoter : Voter() {
|
||||
class OpinionAccessControl : AccessControl() {
|
||||
|
||||
fun <S> canCreate(subjects: List<S>, citizen: CitizenI?): VoterResponse where S : OpinionI, S : HasTarget<*> =
|
||||
fun <S> canCreate(subjects: List<S>, citizen: CitizenI?): AccessResponse where S : OpinionI, S : HasTarget<*> =
|
||||
canAll(subjects) { canCreate(it, citizen) }
|
||||
|
||||
fun <S> canCreate(subject: S, citizen: CitizenI?): VoterResponse where S : OpinionI, S : HasTarget<*> {
|
||||
fun <S> canCreate(subject: S, citizen: CitizenI?): AccessResponse where S : OpinionI, S : HasTarget<*> {
|
||||
val target = subject.target
|
||||
return when {
|
||||
citizen == null -> denied("You must be connected to make an opinion", "opinion.create.notConnected")
|
||||
@@ -22,12 +22,12 @@ class OpinionVoter : Voter() {
|
||||
}
|
||||
}
|
||||
|
||||
fun <S : OpinionI, SS : List<S>> canView(subjects: SS, citizen: CitizenI?): VoterResponse =
|
||||
fun <S : OpinionI, SS : List<S>> canView(subjects: SS, citizen: CitizenI?): AccessResponse =
|
||||
canAll(subjects) { canView(it, citizen) }
|
||||
|
||||
fun <S : OpinionI> canView(subject: S, citizen: CitizenI?): VoterResponse = granted()
|
||||
fun <S : OpinionI> canView(subject: S, citizen: CitizenI?): AccessResponse = granted()
|
||||
|
||||
fun <S, C : CitizenI> canDelete(subject: S, citizen: CitizenI?): VoterResponse where S : EntityCreatedBy<C>, S : OpinionI = when {
|
||||
fun <S, C : CitizenI> canDelete(subject: S, citizen: CitizenI?): AccessResponse where S : EntityCreatedBy<C>, S : OpinionI = when {
|
||||
citizen == null -> denied("You must be connected to delete opinion", "opinion.delete.notConnected")
|
||||
subject.createdBy.id != citizen.id -> denied("You can only delete your opinions", "opinion.delete.notYours")
|
||||
else -> granted()
|
||||
@@ -2,14 +2,14 @@ package fr.dcproject.component.opinion
|
||||
|
||||
import fr.dcproject.component.citizen.CitizenI
|
||||
import fr.dcproject.component.opinion.entity.OpinionChoice
|
||||
import fr.dcproject.voter.Voter
|
||||
import fr.dcproject.voter.VoterResponse
|
||||
import fr.dcproject.security.AccessControl
|
||||
import fr.dcproject.security.AccessResponse
|
||||
|
||||
class OpinionChoiceVoter : Voter() {
|
||||
fun canView(subjects: List<OpinionChoice>, citizen: CitizenI?): VoterResponse =
|
||||
class OpinionChoiceAccessControl : AccessControl() {
|
||||
fun canView(subjects: List<OpinionChoice>, citizen: CitizenI?): AccessResponse =
|
||||
canAll(subjects) { canView(it, citizen) }
|
||||
|
||||
fun canView(subject: OpinionChoice, citizen: CitizenI?): VoterResponse {
|
||||
fun canView(subject: OpinionChoice, citizen: CitizenI?): AccessResponse {
|
||||
return granted()
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,10 @@ package fr.dcproject.component.opinion.routes
|
||||
|
||||
import fr.dcproject.component.article.ArticleRef
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.opinion.OpinionVoter
|
||||
import fr.dcproject.component.opinion.OpinionAccessControl
|
||||
import fr.dcproject.component.opinion.entity.Opinion
|
||||
import fr.dcproject.security.assert
|
||||
import fr.dcproject.utils.toUUID
|
||||
import fr.dcproject.voter.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.Location
|
||||
@@ -27,10 +27,10 @@ object GetCitizenOpinions {
|
||||
val id: List<UUID> = id.toUUID()
|
||||
}
|
||||
|
||||
fun Route.getCitizenOpinions(repo: OpinionArticleRepository, voter: OpinionVoter) {
|
||||
fun Route.getCitizenOpinions(repo: OpinionArticleRepository, ac: OpinionAccessControl) {
|
||||
get<CitizenOpinions> {
|
||||
val opinionsEntities: List<Opinion<ArticleRef>> = repo.findCitizenOpinionsByTargets(it.citizen, it.id)
|
||||
voter.assert { canView(opinionsEntities, citizenOrNull) }
|
||||
ac.assert { canView(opinionsEntities, citizenOrNull) }
|
||||
|
||||
call.respond(opinionsEntities)
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@ package fr.dcproject.component.opinion.routes
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.citizen.CitizenRef
|
||||
import fr.dcproject.component.opinion.OpinionVoter
|
||||
import fr.dcproject.component.opinion.OpinionAccessControl
|
||||
import fr.dcproject.routes.PaginatedRequest
|
||||
import fr.dcproject.routes.PaginatedRequestI
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.Location
|
||||
@@ -27,10 +27,10 @@ object GetMyOpinionsArticle {
|
||||
limit: Int = 50
|
||||
) : PaginatedRequestI by PaginatedRequest(page, limit)
|
||||
|
||||
fun Route.getMyOpinionsArticle(repo: OpinionArticleRepository, voter: OpinionVoter) {
|
||||
fun Route.getMyOpinionsArticle(repo: OpinionArticleRepository, ac: OpinionAccessControl) {
|
||||
get<CitizenOpinionsArticleRequest> {
|
||||
val opinions = repo.findCitizenOpinions(citizen, it.page, it.limit)
|
||||
voter.assert { canView(opinions.result, citizenOrNull) }
|
||||
ac.assert { canView(opinions.result, citizenOrNull) }
|
||||
call.respond(opinions)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package fr.dcproject.component.opinion.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.opinion.OpinionChoiceVoter
|
||||
import fr.dcproject.component.opinion.OpinionChoiceAccessControl
|
||||
import fr.dcproject.component.opinion.entity.OpinionChoice
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.Location
|
||||
@@ -16,9 +16,9 @@ object GetOpinionChoice {
|
||||
@Location("/opinions/{opinionChoice}")
|
||||
class OpinionChoiceRequest(val opinionChoice: OpinionChoice)
|
||||
|
||||
fun Route.getOpinionChoice(voter: OpinionChoiceVoter) {
|
||||
fun Route.getOpinionChoice(ac: OpinionChoiceAccessControl) {
|
||||
get<OpinionChoiceRequest> {
|
||||
voter.assert { canView(it.opinionChoice, citizenOrNull) }
|
||||
ac.assert { canView(it.opinionChoice, citizenOrNull) }
|
||||
|
||||
call.respond(it.opinionChoice)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package fr.dcproject.component.opinion.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.opinion.OpinionChoiceAccessControl
|
||||
import fr.dcproject.component.opinion.OpinionChoiceRepository
|
||||
import fr.dcproject.component.opinion.OpinionChoiceVoter
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.Location
|
||||
@@ -16,10 +16,10 @@ object GetOpinionChoices {
|
||||
@Location("/opinions")
|
||||
class OpinionChoicesRequest(val targets: List<String> = emptyList())
|
||||
|
||||
fun Route.getOpinionChoices(repo: OpinionChoiceRepository, voter: OpinionChoiceVoter) {
|
||||
fun Route.getOpinionChoices(repo: OpinionChoiceRepository, ac: OpinionChoiceAccessControl) {
|
||||
get<OpinionChoicesRequest> {
|
||||
val opinionChoices = repo.findOpinionsChoices(it.targets)
|
||||
voter.assert { canView(opinionChoices, citizenOrNull) }
|
||||
ac.assert { canView(opinionChoices, citizenOrNull) }
|
||||
|
||||
call.respond(opinionChoices)
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@ package fr.dcproject.component.opinion.routes
|
||||
import fr.dcproject.component.article.ArticleForView
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.opinion.OpinionVoter
|
||||
import fr.dcproject.component.opinion.OpinionAccessControl
|
||||
import fr.dcproject.component.opinion.entity.OpinionChoiceRef
|
||||
import fr.dcproject.component.opinion.entity.OpinionForUpdate
|
||||
import fr.dcproject.security.assert
|
||||
import fr.dcproject.utils.toUUID
|
||||
import fr.dcproject.voter.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -31,7 +31,7 @@ object OpinionArticle {
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.setOpinionOnArticle(repo: OpinionArticleRepository, voter: OpinionVoter) {
|
||||
fun Route.setOpinionOnArticle(repo: OpinionArticleRepository, ac: OpinionAccessControl) {
|
||||
put<ArticleOpinion> {
|
||||
call.receive<ArticleOpinion.Body>().ids.map { id ->
|
||||
OpinionForUpdate(
|
||||
@@ -40,7 +40,7 @@ object OpinionArticle {
|
||||
createdBy = citizen
|
||||
)
|
||||
}.let { opinions ->
|
||||
voter.assert { canCreate(opinions, citizenOrNull) }
|
||||
ac.assert { canCreate(opinions, citizenOrNull) }
|
||||
repo.updateOpinions(opinions)
|
||||
}.let {
|
||||
call.respond(HttpStatusCode.Created, it)
|
||||
|
||||
@@ -3,22 +3,22 @@ package fr.dcproject.component.vote
|
||||
import fr.dcproject.component.citizen.CitizenI
|
||||
import fr.dcproject.component.vote.entity.VoteForUpdateI
|
||||
import fr.dcproject.entity.TargetI
|
||||
import fr.dcproject.voter.Voter
|
||||
import fr.dcproject.voter.VoterResponse
|
||||
import fr.dcproject.security.AccessControl
|
||||
import fr.dcproject.security.AccessResponse
|
||||
import fr.postgresjson.entity.EntityDeletedAt
|
||||
import fr.dcproject.component.vote.entity.Vote as VoteEntity
|
||||
|
||||
class VoteVoter : Voter() {
|
||||
fun <S> canCreate(subject: VoteForUpdateI<S, *>, citizen: CitizenI?): VoterResponse where S : EntityDeletedAt, S : TargetI = when {
|
||||
class VoteAccessControl : AccessControl() {
|
||||
fun <S> canCreate(subject: VoteForUpdateI<S, *>, citizen: CitizenI?): AccessResponse where S : EntityDeletedAt, S : TargetI = when {
|
||||
citizen == null -> denied("You must be connected for vote", "vote.create.connected")
|
||||
subject.target.isDeleted() -> denied("You cannot vote on deleted target", "vote.create.isDeleted")
|
||||
else -> granted()
|
||||
}
|
||||
|
||||
fun <S : VoteEntity<*>> canView(subjects: List<S>, citizen: CitizenI?): VoterResponse =
|
||||
fun <S : VoteEntity<*>> canView(subjects: List<S>, citizen: CitizenI?): AccessResponse =
|
||||
canAll(subjects) { canView(it, citizen) }
|
||||
|
||||
fun canView(subject: VoteEntity<*>, citizen: CitizenI?): VoterResponse = when {
|
||||
fun canView(subject: VoteEntity<*>, citizen: CitizenI?): AccessResponse = when {
|
||||
citizen == null -> denied("You must be connected for view your votes", "vote.view.connected")
|
||||
subject.createdBy.id != citizen.id -> denied("You can only display your votes", "vote.view.onlyYours")
|
||||
else -> granted()
|
||||
@@ -2,10 +2,10 @@ package fr.dcproject.component.vote.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.citizen.Citizen
|
||||
import fr.dcproject.component.vote.VoteAccessControl
|
||||
import fr.dcproject.component.vote.VoteRepository
|
||||
import fr.dcproject.component.vote.VoteVoter
|
||||
import fr.dcproject.security.assert
|
||||
import fr.dcproject.utils.toUUID
|
||||
import fr.dcproject.voter.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.Location
|
||||
@@ -21,11 +21,11 @@ object GetCitizenVotes {
|
||||
val id: List<UUID> = id.toUUID()
|
||||
}
|
||||
|
||||
fun Route.getCitizenVote(repo: VoteRepository, voter: VoteVoter) {
|
||||
fun Route.getCitizenVote(repo: VoteRepository, ac: VoteAccessControl) {
|
||||
get<CitizenVotesRequest> {
|
||||
val votes = repo.findCitizenVotesByTargets(it.citizen, it.id)
|
||||
if (votes.isNotEmpty()) {
|
||||
voter.assert { canView(votes, citizenOrNull) }
|
||||
ac.assert { canView(votes, citizenOrNull) }
|
||||
}
|
||||
call.respond(votes)
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ package fr.dcproject.component.vote.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.citizen.Citizen
|
||||
import fr.dcproject.component.vote.VoteAccessControl
|
||||
import fr.dcproject.component.vote.VoteArticleRepository
|
||||
import fr.dcproject.component.vote.VoteVoter
|
||||
import fr.dcproject.routes.PaginatedRequest
|
||||
import fr.dcproject.routes.PaginatedRequestI
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.Location
|
||||
@@ -24,10 +24,10 @@ object GetCitizenVotesOnArticle {
|
||||
val search: String? = null
|
||||
) : PaginatedRequestI by PaginatedRequest(page, limit)
|
||||
|
||||
fun Route.getCitizenVotesOnArticle(repo: VoteArticleRepository, voter: VoteVoter) {
|
||||
fun Route.getCitizenVotesOnArticle(repo: VoteArticleRepository, ac: VoteAccessControl) {
|
||||
get<CitizenVoteArticleRequest> {
|
||||
val votes = repo.findByCitizen(it.citizen, it.page, it.limit)
|
||||
voter.assert { canView(votes.result, citizenOrNull) }
|
||||
ac.assert { canView(votes.result, citizenOrNull) }
|
||||
|
||||
call.respond(votes)
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@ package fr.dcproject.component.vote.routes
|
||||
import fr.dcproject.component.article.ArticleForView
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.vote.VoteAccessControl
|
||||
import fr.dcproject.component.vote.VoteArticleRepository
|
||||
import fr.dcproject.component.vote.VoteVoter
|
||||
import fr.dcproject.component.vote.entity.VoteForUpdate
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -23,7 +23,7 @@ object PutVoteOnArticle {
|
||||
data class Content(var note: Int)
|
||||
}
|
||||
|
||||
fun Route.putVoteOnArticle(repo: VoteArticleRepository, voter: VoteVoter) {
|
||||
fun Route.putVoteOnArticle(repo: VoteArticleRepository, ac: VoteAccessControl) {
|
||||
put<ArticleVoteRequest> {
|
||||
val content = call.receive<ArticleVoteRequest.Content>()
|
||||
val vote = VoteForUpdate(
|
||||
@@ -31,7 +31,7 @@ object PutVoteOnArticle {
|
||||
note = content.note,
|
||||
createdBy = this.citizen
|
||||
)
|
||||
voter.assert { canCreate(vote, citizenOrNull) }
|
||||
ac.assert { canCreate(vote, citizenOrNull) }
|
||||
val votes = repo.vote(vote)
|
||||
call.respond(HttpStatusCode.Created, votes)
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@ package fr.dcproject.component.vote.routes
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.comment.generic.CommentRepository
|
||||
import fr.dcproject.component.vote.VoteAccessControl
|
||||
import fr.dcproject.component.vote.VoteCommentRepository
|
||||
import fr.dcproject.component.vote.VoteVoter
|
||||
import fr.dcproject.component.vote.entity.VoteForUpdate
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -24,7 +24,7 @@ object PutVoteOnComment {
|
||||
data class Content(var note: Int)
|
||||
}
|
||||
|
||||
fun Route.putVoteOnComment(voteCommentRepo: VoteCommentRepository, commentRepo: CommentRepository, voter: VoteVoter) {
|
||||
fun Route.putVoteOnComment(voteCommentRepo: VoteCommentRepository, commentRepo: CommentRepository, ac: VoteAccessControl) {
|
||||
put<CommentVoteRequest> {
|
||||
val comment = commentRepo.findById(it.comment)!!
|
||||
val content = call.receive<CommentVoteRequest.Content>()
|
||||
@@ -33,7 +33,7 @@ object PutVoteOnComment {
|
||||
note = content.note,
|
||||
createdBy = this.citizen
|
||||
)
|
||||
voter.assert { canCreate(vote, citizenOrNull) }
|
||||
ac.assert { canCreate(vote, citizenOrNull) }
|
||||
val votes = voteCommentRepo.vote(vote)
|
||||
call.respond(HttpStatusCode.Created, votes)
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ package fr.dcproject.component.vote.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.vote.VoteAccessControl
|
||||
import fr.dcproject.component.vote.VoteConstitutionRepository
|
||||
import fr.dcproject.component.vote.VoteVoter
|
||||
import fr.dcproject.component.vote.entity.VoteForUpdate
|
||||
import fr.dcproject.component.vote.routes.VoteConstitution.ConstitutionVoteRequest.Input
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -24,7 +24,7 @@ object VoteConstitution {
|
||||
data class Input(var note: Int)
|
||||
}
|
||||
|
||||
fun Route.voteConstitution(repo: VoteConstitutionRepository, voter: VoteVoter) {
|
||||
fun Route.voteConstitution(repo: VoteConstitutionRepository, ac: VoteAccessControl) {
|
||||
put<ConstitutionVoteRequest> {
|
||||
val content = call.receive<Input>()
|
||||
val vote = VoteForUpdate(
|
||||
@@ -32,7 +32,7 @@ object VoteConstitution {
|
||||
note = content.note,
|
||||
createdBy = this.citizen
|
||||
)
|
||||
voter.assert { canCreate(vote, citizenOrNull) }
|
||||
ac.assert { canCreate(vote, citizenOrNull) }
|
||||
repo.vote(vote)
|
||||
call.respond(HttpStatusCode.Created)
|
||||
}
|
||||
|
||||
@@ -2,48 +2,48 @@ package fr.dcproject.component.workgroup
|
||||
|
||||
import fr.dcproject.component.citizen.CitizenI
|
||||
import fr.dcproject.component.workgroup.WorkgroupWithMembersI.Member.Role
|
||||
import fr.dcproject.voter.Voter
|
||||
import fr.dcproject.voter.VoterResponse
|
||||
import fr.dcproject.security.AccessControl
|
||||
import fr.dcproject.security.AccessResponse
|
||||
|
||||
class WorkgroupVoter : Voter() {
|
||||
fun canCreate(subject: WorkgroupI, citizen: CitizenI?): VoterResponse {
|
||||
class WorkgroupAccessControl : AccessControl() {
|
||||
fun canCreate(subject: WorkgroupI, citizen: CitizenI?): AccessResponse {
|
||||
if (citizen == null) return denied("You must be connected to create workgroup", "workgroup.create.notConnected")
|
||||
return granted()
|
||||
}
|
||||
|
||||
fun <S : WorkgroupWithAuthI<*>> canView(subjects: List<S>, citizen: CitizenI?): VoterResponse =
|
||||
fun <S : WorkgroupWithAuthI<*>> canView(subjects: List<S>, citizen: CitizenI?): AccessResponse =
|
||||
canAll(subjects) { canView(it, citizen) }
|
||||
|
||||
fun canView(subject: WorkgroupWithAuthI<*>, citizen: CitizenI?): VoterResponse =
|
||||
fun canView(subject: WorkgroupWithAuthI<*>, citizen: CitizenI?): AccessResponse =
|
||||
if (subject.isDeleted()) denied("You cannot view a deleted workgroup", "workgroup.view.deleted")
|
||||
else if (!subject.anonymous) granted()
|
||||
else if (subject.anonymous && citizen != null && subject.isMember(citizen)) granted()
|
||||
else denied("You cannot view anonymous workgroup", "workgroup.view.anonymous")
|
||||
|
||||
fun canDelete(subject: WorkgroupWithAuthI<*>, citizen: CitizenI?): VoterResponse {
|
||||
fun canDelete(subject: WorkgroupWithAuthI<*>, citizen: CitizenI?): AccessResponse {
|
||||
if (citizen == null) return denied("You must be connected to delete workgroup", "workgroup.delete.notConnected")
|
||||
return if (subject.hasRole(Role.MASTER, citizen)) granted()
|
||||
else denied("You must hase role MASTER to delete workgroup", "workgroup.delete.role")
|
||||
}
|
||||
fun canUpdate(subject: WorkgroupWithAuthI<*>, citizen: CitizenI?): VoterResponse {
|
||||
fun canUpdate(subject: WorkgroupWithAuthI<*>, citizen: CitizenI?): AccessResponse {
|
||||
if (citizen == null) return denied("You must be connected to update workgroup", "workgroup.update.notConnected")
|
||||
return if (subject.hasRole(Role.MASTER, citizen)) granted()
|
||||
else denied("You must hase role MASTER to delete workgroup", "workgroup.delete.role")
|
||||
}
|
||||
|
||||
fun canAddMembers(subject: WorkgroupWithAuthI<*>, citizen: CitizenI?): VoterResponse = when {
|
||||
fun canAddMembers(subject: WorkgroupWithAuthI<*>, citizen: CitizenI?): AccessResponse = when {
|
||||
citizen == null -> denied("You must be connected to add member to the workgroup", "workgroup.addMember.notConnected")
|
||||
subject.hasRole(Role.MASTER, citizen) -> granted()
|
||||
else -> denied("You must have MASTER Role for add member to workgroup", "workgroup.addMember.role")
|
||||
}
|
||||
|
||||
fun canUpdateMembers(subject: WorkgroupWithAuthI<*>, citizen: CitizenI?): VoterResponse = when {
|
||||
fun canUpdateMembers(subject: WorkgroupWithAuthI<*>, citizen: CitizenI?): AccessResponse = when {
|
||||
citizen == null -> denied("You must be connected to update member of the workgroup", "workgroup.updateMember.notConnected")
|
||||
subject.hasRole(Role.MASTER, citizen) -> granted()
|
||||
else -> denied("You must have MASTER Role for update members of workgroup", "workgroup.updateMember.role")
|
||||
}
|
||||
|
||||
fun canRemoveMembers(subject: WorkgroupWithAuthI<*>, citizen: CitizenI?): VoterResponse = when {
|
||||
fun canRemoveMembers(subject: WorkgroupWithAuthI<*>, citizen: CitizenI?): AccessResponse = when {
|
||||
citizen == null -> denied("You must be connected to remove member of the workgroup", "workgroup.removeMember.notConnected")
|
||||
subject.hasRole(Role.MASTER, citizen) -> granted()
|
||||
else -> denied("You must have MASTER Role for remove members of workgroup", "workgroup.removeMember.role")
|
||||
@@ -2,11 +2,11 @@ package fr.dcproject.component.workgroup.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizen
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.workgroup.WorkgroupAccessControl
|
||||
import fr.dcproject.component.workgroup.WorkgroupRepository
|
||||
import fr.dcproject.component.workgroup.WorkgroupSimple
|
||||
import fr.dcproject.component.workgroup.WorkgroupVoter
|
||||
import fr.dcproject.component.workgroup.routes.CreateWorkgroup.PostWorkgroupRequest.Input
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -30,7 +30,7 @@ object CreateWorkgroup {
|
||||
)
|
||||
}
|
||||
|
||||
fun Route.createWorkgroup(repo: WorkgroupRepository, voter: WorkgroupVoter) {
|
||||
fun Route.createWorkgroup(repo: WorkgroupRepository, ac: WorkgroupAccessControl) {
|
||||
post<PostWorkgroupRequest> {
|
||||
call.receive<Input>().run {
|
||||
WorkgroupSimple(
|
||||
@@ -42,7 +42,7 @@ object CreateWorkgroup {
|
||||
citizen
|
||||
)
|
||||
}.let { workgroup ->
|
||||
voter.assert { canCreate(workgroup, citizenOrNull) }
|
||||
ac.assert { canCreate(workgroup, citizenOrNull) }
|
||||
repo.upsert(workgroup)
|
||||
}.let {
|
||||
call.respond(HttpStatusCode.Created, it)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package fr.dcproject.component.workgroup.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.workgroup.WorkgroupAccessControl
|
||||
import fr.dcproject.component.workgroup.WorkgroupRepository
|
||||
import fr.dcproject.component.workgroup.WorkgroupVoter
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -18,10 +18,10 @@ object DeleteWorkgroup {
|
||||
@Location("/workgroups/{workgroupId}")
|
||||
class DeleteWorkgroupRequest(val workgroupId: UUID)
|
||||
|
||||
fun Route.deleteWorkgroup(repo: WorkgroupRepository, voter: WorkgroupVoter) {
|
||||
fun Route.deleteWorkgroup(repo: WorkgroupRepository, ac: WorkgroupAccessControl) {
|
||||
delete<DeleteWorkgroupRequest> {
|
||||
repo.findById(it.workgroupId)?.let { workgroup ->
|
||||
voter.assert { canDelete(workgroup, citizenOrNull) }
|
||||
ac.assert { canDelete(workgroup, citizenOrNull) }
|
||||
repo.delete(workgroup)
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
} ?: call.respond(HttpStatusCode.NotFound)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package fr.dcproject.component.workgroup.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.workgroup.WorkgroupAccessControl
|
||||
import fr.dcproject.component.workgroup.WorkgroupRepository
|
||||
import fr.dcproject.component.workgroup.WorkgroupVoter
|
||||
import fr.dcproject.component.workgroup.routes.EditWorkgroup.PutWorkgroupRequest.Input
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -28,7 +28,7 @@ object EditWorkgroup {
|
||||
)
|
||||
}
|
||||
|
||||
fun Route.editWorkgroup(repo: WorkgroupRepository, voter: WorkgroupVoter) {
|
||||
fun Route.editWorkgroup(repo: WorkgroupRepository, ac: WorkgroupAccessControl) {
|
||||
put<PutWorkgroupRequest> {
|
||||
repo.findById(it.workgroupId)?.let { old ->
|
||||
call.receive<Input>().run {
|
||||
@@ -38,7 +38,7 @@ object EditWorkgroup {
|
||||
logo = logo ?: old.logo,
|
||||
anonymous = anonymous ?: old.anonymous
|
||||
).let { workgroup ->
|
||||
voter.assert { canUpdate(workgroup, citizenOrNull) }
|
||||
ac.assert { canUpdate(workgroup, citizenOrNull) }
|
||||
repo.upsert(workgroup)
|
||||
call.respond(HttpStatusCode.OK, it)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package fr.dcproject.component.workgroup.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.workgroup.WorkgroupAccessControl
|
||||
import fr.dcproject.component.workgroup.WorkgroupRepository
|
||||
import fr.dcproject.component.workgroup.WorkgroupVoter
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -18,10 +18,10 @@ object GetWorkgroup {
|
||||
@Location("/workgroups/{workgroupId}")
|
||||
class WorkgroupRequest(val workgroupId: UUID)
|
||||
|
||||
fun Route.getWorkgroup(repo: WorkgroupRepository, voter: WorkgroupVoter) {
|
||||
fun Route.getWorkgroup(repo: WorkgroupRepository, ac: WorkgroupAccessControl) {
|
||||
get<WorkgroupRequest> {
|
||||
repo.findById(it.workgroupId)?.let { workgroup ->
|
||||
voter.assert { canView(workgroup, citizenOrNull) }
|
||||
ac.assert { canView(workgroup, citizenOrNull) }
|
||||
call.respond(workgroup)
|
||||
} ?: call.respond(HttpStatusCode.NotFound)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package fr.dcproject.component.workgroup.routes
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.workgroup.WorkgroupAccessControl
|
||||
import fr.dcproject.component.workgroup.WorkgroupRepository
|
||||
import fr.dcproject.component.workgroup.WorkgroupVoter
|
||||
import fr.dcproject.security.assert
|
||||
import fr.dcproject.utils.toUUID
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.postgresjson.repository.RepositoryI
|
||||
import io.ktor.application.call
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
@@ -31,7 +31,7 @@ object GetWorkgroups {
|
||||
val members: List<UUID>? = members?.toUUID()
|
||||
}
|
||||
|
||||
fun Route.getWorkgroups(repo: WorkgroupRepository, voter: WorkgroupVoter) {
|
||||
fun Route.getWorkgroups(repo: WorkgroupRepository, ac: WorkgroupAccessControl) {
|
||||
get<WorkgroupsRequest> {
|
||||
val workgroups =
|
||||
repo.find(
|
||||
@@ -42,7 +42,7 @@ object GetWorkgroups {
|
||||
it.search,
|
||||
WorkgroupRepository.Filter(createdById = it.createdBy, members = it.members)
|
||||
)
|
||||
voter.assert { canView(workgroups.result, citizenOrNull) }
|
||||
ac.assert { canView(workgroups.result, citizenOrNull) }
|
||||
call.respond(workgroups)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@ package fr.dcproject.component.workgroup.routes.members
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.citizen.CitizenRef
|
||||
import fr.dcproject.component.workgroup.WorkgroupAccessControl
|
||||
import fr.dcproject.component.workgroup.WorkgroupRepository
|
||||
import fr.dcproject.component.workgroup.WorkgroupVoter
|
||||
import fr.dcproject.component.workgroup.WorkgroupWithMembersI
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.ApplicationCall
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
@@ -40,12 +40,12 @@ object AddMemberToWorkgroup {
|
||||
}
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
fun Route.addMemberToWorkgroup(repo: WorkgroupRepository, voter: WorkgroupVoter) {
|
||||
fun Route.addMemberToWorkgroup(repo: WorkgroupRepository, ac: WorkgroupAccessControl) {
|
||||
/* Add members to workgroup */
|
||||
post<WorkgroupsMembersRequest> {
|
||||
repo.findById(it.workgroupId)?.let { workgroup ->
|
||||
call.getMembersFromRequest().let { members ->
|
||||
voter.assert { canAddMembers(workgroup, citizenOrNull) }
|
||||
ac.assert { canAddMembers(workgroup, citizenOrNull) }
|
||||
repo.addMembers(workgroup, members)
|
||||
}.let { members ->
|
||||
call.respond(HttpStatusCode.Created, members)
|
||||
|
||||
@@ -2,10 +2,10 @@ package fr.dcproject.component.workgroup.routes.members
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.citizen.CitizenRef
|
||||
import fr.dcproject.component.workgroup.WorkgroupAccessControl
|
||||
import fr.dcproject.component.workgroup.WorkgroupRepository
|
||||
import fr.dcproject.component.workgroup.WorkgroupVoter
|
||||
import fr.dcproject.component.workgroup.WorkgroupWithMembersI
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.ApplicationCall
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
@@ -38,12 +38,12 @@ object DeleteMembersOfWorkgroup {
|
||||
)
|
||||
}
|
||||
|
||||
fun Route.deleteMemberOfWorkgroup(repo: WorkgroupRepository, voter: WorkgroupVoter) {
|
||||
fun Route.deleteMemberOfWorkgroup(repo: WorkgroupRepository, ac: WorkgroupAccessControl) {
|
||||
/* Delete members of workgroup */
|
||||
delete<WorkgroupsMembersRequest> {
|
||||
repo.findById(it.workgroupId)?.let { workgroup ->
|
||||
call.getMembersFromRequest().let { members ->
|
||||
voter.assert { canView(workgroup, citizenOrNull) }
|
||||
ac.assert { canView(workgroup, citizenOrNull) }
|
||||
repo.removeMembers(workgroup, members)
|
||||
}.let { members ->
|
||||
call.respond(HttpStatusCode.OK, members)
|
||||
|
||||
@@ -2,10 +2,10 @@ package fr.dcproject.component.workgroup.routes.members
|
||||
|
||||
import fr.dcproject.component.auth.citizenOrNull
|
||||
import fr.dcproject.component.citizen.CitizenRef
|
||||
import fr.dcproject.component.workgroup.WorkgroupAccessControl
|
||||
import fr.dcproject.component.workgroup.WorkgroupRepository
|
||||
import fr.dcproject.component.workgroup.WorkgroupVoter
|
||||
import fr.dcproject.component.workgroup.WorkgroupWithMembersI
|
||||
import fr.dcproject.voter.assert
|
||||
import fr.dcproject.security.assert
|
||||
import io.ktor.application.ApplicationCall
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.HttpStatusCode
|
||||
@@ -38,12 +38,12 @@ object UpdateMemberOfWorkgroup {
|
||||
)
|
||||
}
|
||||
|
||||
fun Route.updateMemberOfWorkgroup(repo: WorkgroupRepository, voter: WorkgroupVoter) {
|
||||
fun Route.updateMemberOfWorkgroup(repo: WorkgroupRepository, ac: WorkgroupAccessControl) {
|
||||
/* Update members of workgroup */
|
||||
put<WorkgroupsMembersRequest> {
|
||||
repo.findById(it.workgroupId)?.let { workgroup ->
|
||||
call.getMembersFromRequest().let { members ->
|
||||
voter.assert { canUpdateMembers(workgroup, citizenOrNull) }
|
||||
ac.assert { canUpdateMembers(workgroup, citizenOrNull) }
|
||||
repo.updateMembers(workgroup, members)
|
||||
}.let { members ->
|
||||
call.respond(HttpStatusCode.OK, members)
|
||||
|
||||
Reference in New Issue
Block a user