Update ktor-voter to version 2.2.0

This commit is contained in:
2020-10-05 15:00:34 +02:00
parent 74923891d0
commit 03401f711e
38 changed files with 403 additions and 384 deletions

View File

@@ -38,6 +38,7 @@ import io.ktor.response.respond
import io.ktor.routing.Routing
import io.ktor.util.KtorExperimentalAPI
import io.ktor.websocket.WebSockets
import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.eclipse.jetty.util.log.Slf4jLog
import org.koin.core.qualifier.named
import org.koin.ktor.ext.Koin
@@ -58,6 +59,7 @@ fun main(args: Array<String>): Unit = io.ktor.server.jetty.EngineMain.main(args)
enum class Env { PROD, TEST, CUCUMBER }
@ExperimentalCoroutinesApi
@KtorExperimentalAPI
@KtorExperimentalLocationsAPI
@Suppress("unused") // Referenced in application.conf
@@ -173,8 +175,8 @@ fun Application.module(env: Env = PROD) {
}
install(AuthorizationVoter) {
voters = mutableListOf(
ArticleVoter(),
voters = listOf(
ArticleVoter(get()),
ConstitutionVoter(),
CitizenVoter(),
CommentVoter(),

View File

@@ -16,9 +16,9 @@ import fr.dcproject.views.ArticleViewManager
import fr.postgresjson.connexion.Connection
import fr.postgresjson.connexion.Requester
import fr.postgresjson.migration.Migrations
import io.ktor.client.HttpClient
import io.ktor.client.features.websocket.WebSockets
import io.ktor.util.KtorExperimentalAPI
import io.ktor.client.*
import io.ktor.client.features.websocket.*
import io.ktor.util.*
import io.lettuce.core.RedisClient
import io.lettuce.core.api.async.RedisAsyncCommands
import org.apache.http.HttpHost
@@ -123,7 +123,7 @@ val Module = module {
single { ArticleViewManager(get()) }
// Mailler
// Mailer
single { Mailer(Config.sendGridKey) }
// SSO Manager for connection

View File

@@ -19,6 +19,7 @@ class Article(
override val createdBy: CitizenBasic,
workgroup: WorkgroupSimple<CitizenRef>? = null
) : ArticleFull,
ArticleForUpdateI,
ArticleAuthI<CitizenBasicI>,
ArticleSimple(id, title, createdBy, draft, workgroup),
Viewable by ViewableImp() {
@@ -26,19 +27,28 @@ class Article(
tags = tags.distinct()
}
}
interface ArticleForUpdateI: ArticleI, EntityVersioning<UUID, Int>, TargetI {
val title: String
val anonymous: Boolean
val content: String
val description: String
val draft: Boolean
val createdBy: CitizenRef
val workgroup: WorkgroupRef?
}
class ArticleForUpdate(
id: UUID?,
val title: String,
val anonymous: Boolean = true,
val content: String,
val description: String,
override val title: String,
override val anonymous: Boolean = true,
override val content: String,
override val description: String,
tags: List<String> = emptyList(),
val draft: Boolean = false,
val createdBy: CitizenRef,
val workgroup: WorkgroupRef? = null,
override val draft: Boolean = false,
override val createdBy: CitizenRef,
override val workgroup: WorkgroupRef? = null,
versionId: UUID?
) : ArticleRefVersioning(id, versionId = versionId ?: UUID.randomUUID()) {
) : ArticleForUpdateI,
ArticleRefVersioning(id, versionId = versionId ?: UUID.randomUUID()) {
val tags: List<String> = tags.distinct()
val isNew = versionId == null
}

View File

@@ -3,34 +3,29 @@ package fr.dcproject.routes
import fr.dcproject.citizen
import fr.dcproject.citizenOrNull
import fr.dcproject.entity.ArticleForUpdate
import fr.dcproject.entity.CitizenRef
import fr.dcproject.entity.WorkgroupRef
import fr.dcproject.entity.WorkgroupSimple
import fr.dcproject.event.ArticleUpdate
import fr.dcproject.event.raiseEvent
import fr.dcproject.repository.Article.Filter
import fr.dcproject.repository.Workgroup as WorkgroupRepository
import fr.dcproject.security.voter.ArticleVoter.Action.CREATE
import fr.dcproject.security.voter.ArticleVoter.Action.UPDATE
import fr.dcproject.security.voter.ArticleVoter.Action.VIEW
import fr.dcproject.views.ArticleViewManager
import fr.ktorVoter.assertCan
import fr.ktorVoter.assertCanAll
import fr.postgresjson.repository.RepositoryI
import io.ktor.application.ApplicationCall
import io.ktor.application.call
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.locations.Location
import io.ktor.locations.get
import io.ktor.locations.post
import io.ktor.request.receive
import io.ktor.response.respond
import io.ktor.routing.Route
import io.ktor.application.*
import io.ktor.locations.*
import io.ktor.request.*
import io.ktor.response.*
import io.ktor.routing.*
import kotlinx.coroutines.launch
import org.koin.core.KoinComponent
import org.koin.core.inject
import java.util.*
import fr.dcproject.entity.Article as ArticleEntity
import fr.dcproject.repository.Article as ArticleRepository
import fr.dcproject.repository.Workgroup as WorkgroupRepository
@KtorExperimentalLocationsAPI
object ArticlesPaths {
@@ -90,7 +85,7 @@ object ArticlesPaths {
tags = tags,
draft = draft,
createdBy = call.citizen,
workgroup = if (workgroup != null) workgroupRepository.findById(workgroup.id) as WorkgroupSimple<CitizenRef> else null,
workgroup = if (workgroup != null) workgroupRepository.findById(workgroup.id) else null,
versionId = versionId
)
}
@@ -108,7 +103,7 @@ fun Route.article(repo: ArticleRepository, viewManager: ArticleViewManager) {
it.search,
Filter(createdById = it.createdBy, workgroupId = it.workgroup)
)
assertCan(VIEW, articles.result)
assertCanAll(VIEW, articles.result)
call.respond(articles)
}

View File

@@ -11,17 +11,15 @@ import fr.dcproject.routes.CitizenPaths.CurrentCitizenRequest
import fr.dcproject.security.voter.CitizenVoter.Action.CHANGE_PASSWORD
import fr.dcproject.security.voter.CitizenVoter.Action.VIEW
import fr.ktorVoter.assertCan
import fr.ktorVoter.assertCanAll
import fr.postgresjson.repository.RepositoryI.Direction
import io.ktor.application.call
import io.ktor.auth.UserPasswordCredential
import io.ktor.http.HttpStatusCode
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.locations.Location
import io.ktor.locations.get
import io.ktor.locations.put
import io.ktor.request.receive
import io.ktor.response.respond
import io.ktor.routing.Route
import io.ktor.application.*
import io.ktor.auth.*
import io.ktor.http.*
import io.ktor.locations.*
import io.ktor.request.*
import io.ktor.response.*
import io.ktor.routing.*
import fr.dcproject.repository.Citizen as CitizenRepository
import fr.dcproject.repository.User as UserRepository
@@ -58,7 +56,7 @@ fun Route.citizen(
) {
get<CitizensRequest> {
val citizens = repo.find(it.page, it.limit, it.sort, it.direction, it.search)
assertCan(VIEW, citizens.result)
assertCanAll(VIEW, citizens.result)
call.respond(citizens)
}

View File

@@ -4,17 +4,19 @@ import fr.dcproject.citizen
import fr.dcproject.entity.Comment
import fr.dcproject.entity.CommentRef
import fr.dcproject.routes.CommentPaths.CreateCommentRequest.Content
import fr.dcproject.security.voter.CommentVoter.Action.*
import fr.dcproject.security.voter.CommentVoter.Action.CREATE
import fr.dcproject.security.voter.CommentVoter.Action.UPDATE
import fr.dcproject.security.voter.CommentVoter.Action.VIEW
import fr.ktorVoter.assertCan
import io.ktor.application.call
import io.ktor.features.NotFoundException
import io.ktor.http.HttpStatusCode
import fr.ktorVoter.assertCanAll
import io.ktor.application.*
import io.ktor.features.*
import io.ktor.http.*
import io.ktor.locations.*
import io.ktor.request.receive
import io.ktor.request.receiveText
import io.ktor.response.respond
import io.ktor.routing.Route
import io.ktor.util.KtorExperimentalAPI
import io.ktor.request.*
import io.ktor.response.*
import io.ktor.routing.*
import io.ktor.util.*
import java.util.*
import fr.dcproject.repository.CommentGeneric as CommentRepository
@@ -58,7 +60,7 @@ fun Route.comment(repo: CommentRepository) {
it.limit
)
assertCan(VIEW, comments.result)
assertCanAll(VIEW, comments.result)
call.respond(HttpStatusCode.OK, comments)
}

View File

@@ -7,16 +7,13 @@ import fr.dcproject.repository.CommentArticle.Sort
import fr.dcproject.security.voter.CommentVoter.Action.CREATE
import fr.dcproject.security.voter.CommentVoter.Action.VIEW
import fr.ktorVoter.assertCan
import io.ktor.application.ApplicationCall
import io.ktor.application.call
import io.ktor.http.HttpStatusCode
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.locations.Location
import io.ktor.locations.get
import io.ktor.locations.post
import io.ktor.request.receive
import io.ktor.response.respond
import io.ktor.routing.Route
import fr.ktorVoter.assertCanAll
import io.ktor.application.*
import io.ktor.http.*
import io.ktor.locations.*
import io.ktor.request.*
import io.ktor.response.*
import io.ktor.routing.*
import fr.dcproject.entity.Comment as CommentEntity
import fr.dcproject.repository.CommentArticle as CommentArticleRepository
@@ -61,7 +58,7 @@ fun Route.commentArticle(repo: CommentArticleRepository) {
get<CommentArticlePaths.ArticleCommentRequest> {
val comment = repo.findByTarget(it.article, it.page, it.limit, it.sort)
if (comment.result.isNotEmpty()) {
assertCan(VIEW, comment.result)
assertCanAll(VIEW, comment.result)
}
call.respond(HttpStatusCode.OK, comment)
}
@@ -76,7 +73,7 @@ fun Route.commentArticle(repo: CommentArticleRepository) {
get<CommentArticlePaths.CitizenCommentArticleRequest> {
repo.findByCitizen(it.citizen).let { comments ->
assertCan(VIEW, comments.result)
assertCanAll(VIEW, comments.result)
call.respond(comments)
}
}

View File

@@ -6,15 +6,13 @@ import fr.dcproject.entity.ConstitutionRef
import fr.dcproject.security.voter.CommentVoter.Action.CREATE
import fr.dcproject.security.voter.CommentVoter.Action.VIEW
import fr.ktorVoter.assertCan
import io.ktor.application.call
import io.ktor.http.HttpStatusCode
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.locations.Location
import io.ktor.locations.get
import io.ktor.locations.post
import io.ktor.request.receiveText
import io.ktor.response.respond
import io.ktor.routing.Route
import fr.ktorVoter.assertCanAll
import io.ktor.application.*
import io.ktor.http.*
import io.ktor.locations.*
import io.ktor.request.*
import io.ktor.response.*
import io.ktor.routing.*
import fr.dcproject.entity.Comment as CommentEntity
import fr.dcproject.repository.CommentConstitution as CommentConstitutionRepository
@@ -31,7 +29,7 @@ object CommentConstitutionPaths {
fun Route.commentConstitution(repo: CommentConstitutionRepository) {
get<CommentConstitutionPaths.ConstitutionCommentRequest> {
val comments = repo.findByTarget(it.constitution)
assertCan(VIEW, comments.result)
assertCanAll(VIEW, comments.result)
call.respond(HttpStatusCode.OK, comments)
}
@@ -50,7 +48,7 @@ fun Route.commentConstitution(repo: CommentConstitutionRepository) {
get<CommentConstitutionPaths.CitizenCommentConstitutionRequest> {
val comments = repo.findByCitizen(it.citizen)
assertCan(VIEW, comments.result)
assertCanAll(VIEW, comments.result)
call.respond(comments)
}
}

View File

@@ -7,17 +7,14 @@ import fr.dcproject.entity.ConstitutionSimple
import fr.dcproject.security.voter.ConstitutionVoter.Action.CREATE
import fr.dcproject.security.voter.ConstitutionVoter.Action.VIEW
import fr.ktorVoter.assertCan
import fr.ktorVoter.assertCanAll
import fr.postgresjson.entity.immutable.UuidEntity
import fr.postgresjson.repository.RepositoryI
import io.ktor.application.ApplicationCall
import io.ktor.application.call
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.locations.Location
import io.ktor.locations.get
import io.ktor.locations.post
import io.ktor.request.receive
import io.ktor.response.respond
import io.ktor.routing.Route
import io.ktor.application.*
import io.ktor.locations.*
import io.ktor.request.*
import io.ktor.response.*
import io.ktor.routing.*
import java.util.*
import fr.dcproject.entity.Constitution as ConstitutionEntity
import fr.dcproject.repository.Constitution as ConstitutionRepository
@@ -86,7 +83,7 @@ object ConstitutionPaths {
fun Route.constitution(repo: ConstitutionRepository) {
get<ConstitutionPaths.ConstitutionsRequest> {
val constitutions = repo.find(it.page, it.limit, it.sort, it.direction, it.search)
assertCan(VIEW, constitutions.result)
assertCanAll(VIEW, constitutions.result)
call.respond(constitutions)
}

View File

@@ -3,13 +3,16 @@ package fr.dcproject.routes
import fr.dcproject.citizen
import fr.dcproject.entity.ArticleRef
import fr.dcproject.entity.Citizen
import fr.dcproject.security.voter.FollowVoter.Action.*
import fr.dcproject.security.voter.FollowVoter.Action.CREATE
import fr.dcproject.security.voter.FollowVoter.Action.DELETE
import fr.dcproject.security.voter.FollowVoter.Action.VIEW
import fr.ktorVoter.assertCan
import io.ktor.application.call
import io.ktor.http.HttpStatusCode
import fr.ktorVoter.assertCanAll
import io.ktor.application.*
import io.ktor.http.*
import io.ktor.locations.*
import io.ktor.response.respond
import io.ktor.routing.Route
import io.ktor.response.*
import io.ktor.routing.*
import fr.dcproject.entity.Follow as FollowEntity
import fr.dcproject.repository.FollowArticle as FollowArticleRepository
@@ -48,7 +51,7 @@ fun Route.followArticle(repo: FollowArticleRepository) {
get<FollowArticlePaths.CitizenFollowArticleRequest> {
val follows = repo.findByCitizen(it.citizen)
if (follows.result.isNotEmpty()) {
assertCan(VIEW, follows.result)
assertCanAll(VIEW, follows.result)
}
call.respond(follows)
}

View File

@@ -3,13 +3,16 @@ package fr.dcproject.routes
import fr.dcproject.citizen
import fr.dcproject.entity.CitizenRef
import fr.dcproject.entity.ConstitutionRef
import fr.dcproject.security.voter.FollowVoter.Action.*
import fr.dcproject.security.voter.FollowVoter.Action.CREATE
import fr.dcproject.security.voter.FollowVoter.Action.DELETE
import fr.dcproject.security.voter.FollowVoter.Action.VIEW
import fr.ktorVoter.assertCan
import io.ktor.application.call
import io.ktor.http.HttpStatusCode
import fr.ktorVoter.assertCanAll
import io.ktor.application.*
import io.ktor.http.*
import io.ktor.locations.*
import io.ktor.response.respond
import io.ktor.routing.Route
import io.ktor.response.*
import io.ktor.routing.*
import fr.dcproject.entity.Follow as FollowEntity
import fr.dcproject.repository.FollowConstitution as FollowConstitutionRepository
@@ -47,7 +50,7 @@ fun Route.followConstitution(repo: FollowConstitutionRepository) {
get<FollowConstitutionPaths.CitizenFollowConstitutionRequest> {
val follows = repo.findByCitizen(it.citizen)
assertCan(VIEW, follows.result)
assertCanAll(VIEW, follows.result)
call.respond(follows)
}
}

View File

@@ -5,18 +5,16 @@ import fr.dcproject.entity.CitizenRef
import fr.dcproject.entity.OpinionChoiceRef
import fr.dcproject.security.voter.OpinionVoter.Action.CREATE
import fr.dcproject.security.voter.OpinionVoter.Action.VIEW
import fr.ktorVoter.assertCan
import fr.dcproject.utils.toUUID
import io.ktor.application.call
import io.ktor.http.HttpStatusCode
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.locations.Location
import io.ktor.locations.get
import io.ktor.locations.put
import io.ktor.request.receive
import io.ktor.response.respond
import io.ktor.routing.Route
import io.ktor.util.KtorExperimentalAPI
import fr.ktorVoter.assertCan
import fr.ktorVoter.assertCanAll
import io.ktor.application.*
import io.ktor.http.*
import io.ktor.locations.*
import io.ktor.request.*
import io.ktor.response.*
import io.ktor.routing.*
import io.ktor.util.*
import org.koin.core.KoinComponent
import org.koin.core.get
import java.util.*
@@ -67,7 +65,7 @@ fun Route.opinionArticle(repo: OpinionArticleRepository) {
}
get<OpinionArticlePaths.CitizenOpinions> {
assertCan(VIEW, it.opinionsEntities)
assertCanAll(VIEW, it.opinionsEntities)
call.respond(it.opinionsEntities)
}

View File

@@ -3,12 +3,11 @@ package fr.dcproject.routes
import fr.dcproject.entity.OpinionChoice
import fr.dcproject.security.voter.OpinionChoiceVoter.Action.VIEW
import fr.ktorVoter.assertCan
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
import fr.ktorVoter.assertCanAll
import io.ktor.application.*
import io.ktor.locations.*
import io.ktor.response.*
import io.ktor.routing.*
import fr.dcproject.repository.OpinionChoice as OpinionChoiceRepository
@KtorExperimentalLocationsAPI
@@ -30,7 +29,7 @@ fun Route.opinionChoice(repo: OpinionChoiceRepository) {
get<OpinionChoicePaths.OpinionChoicesRequest> {
val opinions = repo.findOpinionsChoices(it.targets)
assertCan(VIEW, opinions)
assertCanAll(VIEW, opinions)
call.respond(opinions)
}

View File

@@ -8,17 +8,15 @@ import fr.dcproject.routes.VoteArticlePaths.ArticleVoteRequest
import fr.dcproject.routes.VoteArticlePaths.CommentVoteRequest
import fr.dcproject.security.voter.VoteVoter.Action.CREATE
import fr.dcproject.security.voter.VoteVoter.Action.VIEW
import fr.ktorVoter.assertCan
import fr.dcproject.utils.toUUID
import io.ktor.application.call
import io.ktor.http.HttpStatusCode
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.locations.Location
import io.ktor.locations.get
import io.ktor.locations.put
import io.ktor.request.receive
import io.ktor.response.respond
import io.ktor.routing.Route
import fr.ktorVoter.assertCan
import fr.ktorVoter.assertCanAll
import io.ktor.application.*
import io.ktor.http.*
import io.ktor.locations.*
import io.ktor.request.*
import io.ktor.response.*
import io.ktor.routing.*
import java.util.*
import fr.dcproject.entity.Article as ArticleEntity
import fr.dcproject.entity.Vote as VoteEntity
@@ -79,7 +77,7 @@ fun Route.voteArticle(repo: VoteArticleRepository, voteCommentRepo: VoteComment,
get<VoteArticlePaths.CitizenVoteArticleRequest> {
val votes = repo.findByCitizen(it.citizen, it.page, it.limit)
assertCan(VIEW, votes.result)
assertCanAll(VIEW, votes.result)
call.respond(votes)
}
@@ -87,7 +85,7 @@ fun Route.voteArticle(repo: VoteArticleRepository, voteCommentRepo: VoteComment,
get<VoteArticlePaths.CitizenVotesByIdsRequest> {
val votes = repo.findCitizenVotesByTargets(it.citizen, it.id)
if (votes.isNotEmpty()) {
assertCan(VIEW, votes)
assertCanAll(VIEW, votes)
}
call.respond(votes)
}

View File

@@ -11,14 +11,14 @@ import fr.dcproject.security.voter.WorkgroupVoter.Action.UPDATE
import fr.dcproject.security.voter.WorkgroupVoter.Action.VIEW
import fr.dcproject.utils.toUUID
import fr.ktorVoter.assertCan
import fr.ktorVoter.assertCanAll
import fr.postgresjson.repository.RepositoryI
import io.ktor.application.ApplicationCall
import io.ktor.application.call
import io.ktor.http.HttpStatusCode
import io.ktor.application.*
import io.ktor.http.*
import io.ktor.locations.*
import io.ktor.request.receive
import io.ktor.response.respond
import io.ktor.routing.Route
import io.ktor.request.*
import io.ktor.response.*
import io.ktor.routing.*
import java.util.*
import fr.dcproject.entity.Workgroup as WorkgroupEntity
import fr.dcproject.repository.Workgroup as WorkgroupRepository
@@ -115,7 +115,7 @@ fun Route.workgroup(repo: WorkgroupRepository) {
get<WorkgroupsPaths.WorkgroupsRequest> {
val workgroups =
repo.find(it.page, it.limit, it.sort, it.direction, it.search, Filter(createdById = it.createdBy, members = it.members))
assertCan(VIEW, workgroups.result)
assertCanAll(VIEW, workgroups.result)
call.respond(workgroups)
}

View File

@@ -2,7 +2,7 @@ package fr.dcproject.security.voter
import fr.dcproject.citizenOrNull
import fr.dcproject.entity.ArticleAuthI
import fr.dcproject.entity.ArticleForUpdate
import fr.dcproject.entity.ArticleForUpdateI
import fr.dcproject.entity.ArticleI
import fr.dcproject.entity.Citizen as CitizenEntity
import fr.dcproject.entity.CitizenI
@@ -11,16 +11,15 @@ import fr.dcproject.repository.Article as ArticleRepo
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.Vote
import fr.ktorVoter.Vote.Companion.toVote
import fr.ktorVoter.Voter
import fr.ktorVoter.checkClass
import io.ktor.application.ApplicationCall
import org.koin.core.KoinComponent
import org.koin.core.inject
import fr.dcproject.entity.Comment as CommentEntity
import fr.dcproject.entity.Vote as VoteEntity
class ArticleVoter : Voter, KoinComponent {
private val articleRepo: ArticleRepo by inject()
class ArticleVoter(private val articleRepo: ArticleRepo) : Voter<ApplicationCall> {
enum class Action : ActionI {
CREATE,
UPDATE,
@@ -28,17 +27,16 @@ class ArticleVoter : Voter, KoinComponent {
DELETE
}
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
return (action is Action || action is CommentVoter.Action || action is VoteVoter.Action)
.and(subject is ArticleI? || subject is VoteEntity<*> || subject is CommentEntity<*>)
}
override fun invoke(action: Any, context: ApplicationCall, subject: Any?): Vote {
if (!((action is Action || action is CommentVoter.Action || action is VoteVoter.Action)
&& (subject is ArticleI? || subject is VoteEntity<*> || subject is CommentEntity<*>))
) return Vote.ABSTAIN
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
val user = call.user
val user = context.user
if (action == Action.CREATE && user is UserI) return Vote.GRANTED
if (action == Action.VIEW) return view(subject, user)
if (action == Action.DELETE) return delete(subject, user)
if (action == Action.UPDATE) return update(subject, call.citizenOrNull)
if (action == Action.UPDATE) return update(subject, context.citizenOrNull)
if (action is CommentVoter.Action) return voteForComment(action, subject)
if (action is VoteVoter.Action) return voteForVote(action, subject)
if (action is Action) return Vote.DENIED
@@ -47,7 +45,6 @@ class ArticleVoter : Voter, KoinComponent {
}
private fun view(subject: Any?, user: UserI?): Vote {
checkClass(ArticleAuthI::class, subject)
if (subject is ArticleAuthI<*>) {
return if (subject.isDeleted()) Vote.DENIED
else if (subject.draft && (user == null || subject.createdBy.user.id != user.id)) Vote.DENIED
@@ -57,7 +54,6 @@ class ArticleVoter : Voter, KoinComponent {
}
private fun delete(subject: Any?, user: UserI?): Vote {
checkClass(ArticleAuthI::class, subject)
if (subject is ArticleAuthI<*>) {
if (user is UserI && subject.createdBy.user.id == user.id) {
return Vote.GRANTED
@@ -67,15 +63,14 @@ class ArticleVoter : Voter, KoinComponent {
}
private fun update(subject: Any?, citizen: CitizenEntity?): Vote {
checkClass(ArticleForUpdate::class, subject)
if (subject is ArticleForUpdate) {
/* The new Article must by created by the same citizen of the connected citizen */
if (citizen is CitizenI && subject.createdBy.id == citizen.id) {
/* The creator must be the same of the creator of preview version of article */
if(articleRepo.findVerionsByVersionsId(1, 1, subject.versionId).result.first().createdBy.id == citizen.id) {
return Vote.GRANTED
}
return Vote.DENIED
/* The new Article must by created by the same citizen of the connected citizen */
if (subject is ArticleForUpdateI && citizen is CitizenI && subject.createdBy.id == citizen.id) {
/* The creator must be the same of the creator of preview version of article */
return toVote {
articleRepo
.findVerionsByVersionsId(1, 1, subject.versionId)
.result.first()
.createdBy.id == citizen.id
}
}
return Vote.DENIED

View File

@@ -10,7 +10,7 @@ import io.ktor.application.ApplicationCall
import io.ktor.locations.KtorExperimentalLocationsAPI
@KtorExperimentalLocationsAPI
class CitizenVoter : Voter {
class CitizenVoter : Voter<ApplicationCall> {
enum class Action : ActionI {
CREATE,
UPDATE,
@@ -19,13 +19,11 @@ class CitizenVoter : Voter {
CHANGE_PASSWORD
}
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
return (action is Action)
.and(subject is CitizenBasicI?)
}
override fun invoke(action: Any, context: ApplicationCall, subject: Any?): Vote {
if (!((action is Action)
&& (subject is CitizenBasicI?))) return Vote.ABSTAIN
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
val user = call.user
val user = context.user
if (action == Action.CREATE && user != null) {
return Vote.GRANTED
}
@@ -56,14 +54,10 @@ class CitizenVoter : Voter {
return if (user.id == userToChange.id) {
Vote.GRANTED
} else {
Vote.ABSTAIN
Vote.DENIED
}
}
if (action is Action) {
return Vote.DENIED
}
return Vote.ABSTAIN
return Vote.DENIED
}
}

View File

@@ -7,7 +7,7 @@ import fr.ktorVoter.Vote
import fr.ktorVoter.Voter
import io.ktor.application.ApplicationCall
class CommentVoter : Voter {
class CommentVoter : Voter<ApplicationCall> {
enum class Action : ActionI {
CREATE,
UPDATE,
@@ -15,15 +15,12 @@ class CommentVoter : Voter {
DELETE
}
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
return (action is Action)
.and(subject is Comment<*>?)
}
override fun invoke(action: Any, context: ApplicationCall, subject: Any?): Vote {
if (!(action is Action && subject is Comment<*>?)) return Vote.ABSTAIN
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
val user = call.user
val user = context.user
if (subject !is Comment<*>) {
if (subject == null) {
return Vote.DENIED
}
@@ -50,10 +47,6 @@ class CommentVoter : Voter {
return Vote.DENIED
}
if (action is Action) {
return Vote.DENIED
}
return Vote.ABSTAIN
return Vote.DENIED
}
}

View File

@@ -10,7 +10,7 @@ import fr.ktorVoter.Voter
import io.ktor.application.ApplicationCall
import fr.dcproject.entity.Vote as VoteEntity
class ConstitutionVoter : Voter {
class ConstitutionVoter : Voter<ApplicationCall> {
enum class Action : ActionI {
CREATE,
UPDATE,
@@ -18,13 +18,11 @@ class ConstitutionVoter : Voter {
DELETE
}
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
return (action is Action || action is CommentVoter.Action || action is VoteVoter.Action)
.and(subject is ConstitutionSimple<*, *>? || subject is VoteEntity<*> || subject is Comment<*>)
}
override fun invoke(action: Any, context: ApplicationCall, subject: Any?): Vote {
if(!((action is Action || action is CommentVoter.Action || action is VoteVoter.Action)
&& (subject is ConstitutionSimple<*, *>? || subject is VoteEntity<*> || subject is Comment<*>))) return Vote.ABSTAIN
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
val user = call.user
val user = context.user
if (action == Action.CREATE && user != null) {
return Vote.GRANTED
}

View File

@@ -8,20 +8,18 @@ import io.ktor.application.ApplicationCall
import fr.dcproject.entity.Follow as FollowEntity
import fr.dcproject.entity.User as UserEntity
class FollowVoter : Voter {
class FollowVoter : Voter<ApplicationCall> {
enum class Action : ActionI {
CREATE,
DELETE,
VIEW
}
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
return (action is Action)
.and(subject is FollowEntity<*>?)
}
override fun invoke(action: Any, context: ApplicationCall, subject: Any?): Vote {
if (!((action is Action)
&& (subject is FollowEntity<*>?))) return Vote.ABSTAIN
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
val user = call.user
val user = context.user
if (action == Action.CREATE) {
return if (user != null) Vote.GRANTED
else Vote.DENIED

View File

@@ -6,17 +6,15 @@ import fr.ktorVoter.Vote
import fr.ktorVoter.Voter
import io.ktor.application.ApplicationCall
class OpinionChoiceVoter : Voter {
class OpinionChoiceVoter : Voter<ApplicationCall> {
enum class Action : ActionI {
VIEW
}
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
return (action is Action)
.and(subject is OpinionChoice?)
}
override fun invoke(action: Any, context: ApplicationCall, subject: Any?): Vote {
if (!((action is Action)
&& (subject is OpinionChoice?))) return Vote.ABSTAIN
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
if (action == Action.VIEW) {
if (subject is OpinionChoice) {
return Vote.GRANTED

View File

@@ -1,49 +1,46 @@
package fr.dcproject.security.voter
import fr.dcproject.entity.Article
import fr.dcproject.entity.ArticleAuthI
import fr.dcproject.entity.Opinion
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.Vote
import fr.ktorVoter.Vote.Companion.toVote
import fr.ktorVoter.Voter
import io.ktor.application.ApplicationCall
class OpinionVoter : Voter {
class OpinionVoter : Voter<ApplicationCall> {
enum class Action : ActionI {
CREATE,
VIEW,
DELETE
}
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
return (action is Action)
.and(subject is Opinion<*>? || subject is ArticleAuthI<*>)
}
override fun invoke(action: Any, context: ApplicationCall, subject: Any?): Vote {
if (!((action is Action)
&& (subject is Opinion<*>? || subject is ArticleAuthI<*>))) return Vote.ABSTAIN
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
val user = call.user
val user = context.user
if (action == Action.CREATE) {
return if (user != null && (
(subject is ArticleAuthI<*> && !subject.isDeleted()) ||
(subject is Opinion<*> && subject.createdBy.user.id == user.id)
)) Vote.GRANTED
else Vote.DENIED
return toVote {
user != null && (
(subject is ArticleAuthI<*> && !subject.isDeleted()) ||
(subject is Opinion<*> && subject.createdBy.user.id == user.id)
)
}
}
if (action == Action.VIEW) {
if (subject is Opinion<*>) {
return Vote.GRANTED
}
return Vote.DENIED
return toVote { subject is Opinion<*> || subject is Article }
}
if (action == Action.DELETE) {
return if (subject is Opinion<*> &&
return toVote {
subject is Opinion<*> &&
user != null &&
subject.createdBy.user.id == user.id
)
Vote.GRANTED
else Vote.DENIED
}
}
return Vote.ABSTAIN

View File

@@ -7,23 +7,22 @@ import fr.ktorVoter.Voter
import io.ktor.application.ApplicationCall
import fr.dcproject.entity.Vote as VoteEntity
class VoteVoter : Voter {
class VoteVoter : Voter<ApplicationCall> {
enum class Action : ActionI {
CREATE,
VIEW
}
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
return action is Action && subject is VoteEntity<*>?
}
override fun invoke(action: Any, context: ApplicationCall, subject: Any?): Vote {
if (!(action is Action && subject is VoteEntity<*>?)) return Vote.ABSTAIN
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
val user = call.user
if (action == Action.CREATE && user != null) {
val user = context.user ?: return Vote.DENIED
if (action == Action.CREATE) {
return Vote.GRANTED
}
if (action == Action.VIEW && user != null) {
if (action == Action.VIEW) {
if (subject is VoteEntity<*>) {
return if (subject.createdBy.user.id != user.id) {
Vote.DENIED

View File

@@ -9,7 +9,7 @@ import fr.ktorVoter.Voter
import fr.ktorVoter.VoterException
import io.ktor.application.ApplicationCall
class WorkgroupVoter : Voter {
class WorkgroupVoter : Voter<ApplicationCall> {
enum class Action : ActionI {
CREATE,
UPDATE,
@@ -24,13 +24,11 @@ class WorkgroupVoter : Voter {
REMOVE,
}
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
return (action is Action || action is ActionMembers)
.and(subject is WorkgroupI?)
}
override fun invoke(action: Any, context: ApplicationCall, subject: Any?): Vote {
if (!((action is Action || action is ActionMembers)
&& (subject is WorkgroupI? || (subject is List<*> && subject.first() is WorkgroupI)))) return Vote.ABSTAIN
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
val user = call.user
val user = context.user
if (subject is WorkgroupI && action == Action.CREATE && user is UserI) {
return Vote.GRANTED
}
@@ -62,7 +60,7 @@ class WorkgroupVoter : Voter {
if (action == ActionMembers.ADD) {
// TODO create ROLES
return Vote.isGranted {
return Vote.toVote {
user is UserI &&
subject is WorkgroupWithAuthI<*> &&
subject.hasRole(Role.MASTER, user)
@@ -71,7 +69,7 @@ class WorkgroupVoter : Voter {
if (action == ActionMembers.UPDATE) {
// TODO create ROLES
return Vote.isGranted {
return Vote.toVote {
user is UserI &&
subject is WorkgroupWithAuthI<*> &&
subject.hasRole(Role.MASTER, user)
@@ -80,7 +78,7 @@ class WorkgroupVoter : Voter {
if (action == ActionMembers.REMOVE) {
// TODO create ROLES
return Vote.isGranted {
return Vote.toVote {
user is UserI &&
subject is WorkgroupWithAuthI<*> &&
subject.hasRole(Role.MASTER, user)