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

@@ -1,6 +1,6 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.owasp.dependencycheck.reporting.ReportGenerator
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.slf4j.LoggerFactory
val ktor_version: String by project
@@ -139,7 +139,7 @@ dependencies {
implementation("com.auth0:java-jwt:3.8.2")
implementation("com.github.jasync-sql:jasync-postgresql:1.0.7")
implementation("com.github.flecomte:postgres-json:1.2.1")
implementation("com.github.flecomte:ktor-voter:1.0.1")
implementation("com.github.flecomte:ktor-voter:2.2.1")
implementation("com.sendgrid:sendgrid-java:4.4.1")
implementation("io.lettuce:lettuce-core:5.2.2.RELEASE")
implementation("com.rabbitmq:amqp-client:5.8.0")
@@ -152,7 +152,7 @@ dependencies {
testImplementation("org.koin:koin-test:$koinVersion")
testImplementation("io.mockk:mockk:1.9.3")
testImplementation("org.junit.jupiter:junit-jupiter:5.5.0")
testImplementation("org.amshove.kluent:kluent:1.4")
testImplementation("org.amshove.kluent:kluent:1.61")
testImplementation("io.cucumber:cucumber-java8:$cucumber_version")
testImplementation("io.cucumber:cucumber-junit:$cucumber_version")
}

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)

View File

@@ -6,7 +6,7 @@ import fr.postgresjson.serializer.deserialize
import fr.postgresjson.serializer.serialize
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.util.KtorExperimentalAPI
import org.amshove.kluent.`should equal`
import org.amshove.kluent.`should be equal to`
import org.amshove.kluent.shouldBe
import org.intellij.lang.annotations.Language
import org.joda.time.DateTime
@@ -96,6 +96,6 @@ class ArticleTest {
@Test
fun `test Article Deserialize`() {
val article2: Article = articleJson.deserialize()!!
article2.id.toString() `should equal` "83b0b60a-5ab3-44f2-b243-1dc469a7564f"
article2.id.toString() `should be equal to` "83b0b60a-5ab3-44f2-b243-1dc469a7564f"
}
}

View File

@@ -6,6 +6,7 @@ import fr.postgresjson.serializer.deserialize
import fr.postgresjson.serializer.serialize
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.util.KtorExperimentalAPI
import org.amshove.kluent.`should be equal to`
import org.amshove.kluent.`should equal`
import org.amshove.kluent.shouldBe
import org.intellij.lang.annotations.Language
@@ -101,6 +102,6 @@ class ConstitutionTest {
@Test
fun `test Constitution Deserialize`() {
val constitution2: Constitution = constitutionJson.deserialize()!!
constitution2.id.toString() `should equal` "15814bb6-8d90-4c6a-a456-c3939a8ec75e"
constitution2.id.toString() `should be equal to` "15814bb6-8d90-4c6a-a456-c3939a8ec75e"
}
}

View File

@@ -3,6 +3,7 @@ import fr.postgresjson.serializer.deserialize
import fr.postgresjson.serializer.serialize
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.util.KtorExperimentalAPI
import org.amshove.kluent.`should be equal to`
import org.amshove.kluent.`should equal`
import org.amshove.kluent.shouldBe
import org.intellij.lang.annotations.Language
@@ -103,6 +104,6 @@ class FollowTest {
@Test
fun `test Follow Article Deserialize`() {
val follow: Follow<ArticleSimple> = followJson.deserialize()!!
follow.id.toString() `should equal` "bae81585-d985-4d7a-9b58-3a13e911688a"
follow.id.toString() `should be equal to` "bae81585-d985-4d7a-9b58-3a13e911688a"
}
}

View File

@@ -6,7 +6,7 @@ import fr.dcproject.views.ArticleViewManager
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.server.testing.withTestApplication
import io.ktor.util.KtorExperimentalAPI
import org.amshove.kluent.`should equal`
import org.amshove.kluent.`should be equal to`
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
@@ -61,8 +61,8 @@ class ViewTest {
val afterView = viewManager.getViewsCount(article)
/* Check if view has increment */
afterView.total `should equal` startView.total + 4
afterView.unique `should equal` startView.unique + 3
afterView.total `should be equal to` startView.total + 4
afterView.unique `should be equal to` startView.unique + 3
}
}
}

View File

@@ -3,6 +3,7 @@ import fr.postgresjson.serializer.deserialize
import fr.postgresjson.serializer.serialize
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.util.KtorExperimentalAPI
import org.amshove.kluent.`should be equal to`
import org.amshove.kluent.`should equal`
import org.amshove.kluent.shouldBe
import org.intellij.lang.annotations.Language
@@ -125,7 +126,7 @@ class VoteTest {
@Test
fun `test Vote Article Deserialize`() {
val vote: Vote<Article> = voteJson.deserialize()!!
vote.id.toString() `should equal` "032acc3d-e8c5-4cb2-9297-bec913ff8d9b"
vote.note.toString() `should equal` "-1"
vote.id.toString() `should be equal to` "032acc3d-e8c5-4cb2-9297-bec913ff8d9b"
vote.note.toString() `should be equal to` "-1"
}
}

View File

@@ -1,9 +1,12 @@
package fr.dcproject.security.voter
import fr.dcproject.citizenOrNull
import fr.dcproject.entity.*
import fr.dcproject.user
import fr.ktorVoter.Vote
import fr.ktorVoter.can
import fr.ktorVoter.canAll
import fr.postgresjson.connexion.Paginated
import io.ktor.application.ApplicationCall
import io.mockk.every
import io.mockk.mockk
@@ -13,11 +16,12 @@ import org.joda.time.DateTime
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import fr.dcproject.repository.Article as ArticleRepo
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@Tag("voter")
internal class ArticleVoterTest {
val tesla = CitizenBasic(
class ArticleVoterTest {
private val tesla = Citizen(
user = User(
username = "nicolas-tesla",
roles = listOf(UserI.Roles.ROLE_USER)
@@ -26,7 +30,7 @@ internal class ArticleVoterTest {
email = "tesla@best.com",
name = CitizenI.Name("Nicolas", "Tesla")
)
val einstein = CitizenBasic(
private val einstein = Citizen(
user = User(
username = "albert-einstein",
roles = listOf(UserI.Roles.ROLE_USER)
@@ -36,24 +40,30 @@ internal class ArticleVoterTest {
name = CitizenI.Name("Albert", "Einstein")
)
private fun getRepo(article: Article): ArticleRepo {
return mockk {
every { findVerionsByVersionsId(1, 1, any()) } returns Paginated(listOf(article), 0, 1, 1)
}
}
init {
mockkStatic("fr.dcproject.ApplicationContextKt")
}
@Test
fun `creator can be view the article`() = ArticleVoter().run {
fun `creator can be view the article`(): Unit {
val article = getArticle(tesla).apply { draft = true }
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
supports(ArticleVoter.Action.VIEW, it, article) `should be` true
vote(ArticleVoter.Action.VIEW, it, article) `should be` Vote.GRANTED
ArticleVoter(getRepo(article)).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
this(ArticleVoter.Action.VIEW, it, article) `should be` Vote.GRANTED
}
}
}
@Test
fun `other user can be view the article`() = listOf(ArticleVoter()).run {
fun `other user can be view the article`(): Unit = listOf(ArticleVoter(mockk())).run {
val article = getArticle(tesla)
mockk<ApplicationCall> {
@@ -64,19 +74,19 @@ internal class ArticleVoterTest {
}
@Test
fun `other user can be view the article list`() = listOf(ArticleVoter()).run {
fun `other user can be view the article list`(): Unit = listOf(ArticleVoter(mockk())).run {
val article = getArticle(tesla)
val article2 = getArticle(tesla)
mockk<ApplicationCall> {
every { user } returns einstein.user
}.let {
can(ArticleVoter.Action.VIEW, it, listOf(article, article2)) `should be` true
canAll(ArticleVoter.Action.VIEW, it, listOf(article, article2)) `should be` true
}
}
@Test
fun `the no creator can not be view the article on draft`() = listOf(ArticleVoter()).run {
fun `the no creator can not be view the article on draft`(): Unit = listOf(ArticleVoter(mockk())).run {
val article = getArticle(tesla).apply { draft = true }
mockk<ApplicationCall> {
@@ -87,19 +97,19 @@ internal class ArticleVoterTest {
}
@Test
fun `the no creator can not be view list of articles if one is on draft`() = listOf(ArticleVoter()).run {
fun `the no creator can not be view list of articles if one is on draft`(): Unit = listOf(ArticleVoter(mockk())).run {
val article = getArticle(tesla)
val article2 = getArticle(tesla).apply { draft = true }
mockk<ApplicationCall> {
every { user } returns einstein.user
}.let {
can(ArticleVoter.Action.VIEW, it, listOf(article, article2)) `should be` false
canAll(ArticleVoter.Action.VIEW, it, listOf(article, article2)) `should be` false
}
}
@Test
fun `can not view deleted article`() = listOf(ArticleVoter()).run {
fun `can not view deleted article`(): Unit = listOf(ArticleVoter(mockk())).run {
val article = getArticle(tesla).apply { deletedAt = DateTime.now() }
mockk<ApplicationCall> {
@@ -110,7 +120,7 @@ internal class ArticleVoterTest {
}
@Test
fun `can delete article if owner`() = listOf(ArticleVoter()).run {
fun `can delete article if owner`(): Unit = listOf(ArticleVoter(mockk())).run {
val article = getArticle(tesla)
mockk<ApplicationCall> {
@@ -121,7 +131,7 @@ internal class ArticleVoterTest {
}
@Test
fun `can not delete article if not owner`() = listOf(ArticleVoter()).run {
fun `can not delete article if not owner`(): Unit = listOf(ArticleVoter(mockk())).run {
val article = getArticle(tesla).apply { deletedAt = DateTime.now() }
mockk<ApplicationCall> {
@@ -132,7 +142,7 @@ internal class ArticleVoterTest {
}
@Test
fun `can create article if logged`() = listOf(ArticleVoter()).run {
fun `can create article if logged`(): Unit = listOf(ArticleVoter(mockk())).run {
val article = getArticle(tesla)
mockk<ApplicationCall> {
@@ -143,7 +153,7 @@ internal class ArticleVoterTest {
}
@Test
fun `can not create article if not logged`() = listOf(ArticleVoter()).run {
fun `can not create article if not logged`(): Unit = listOf(ArticleVoter(mockk())).run {
val article = getArticle(tesla)
mockk<ApplicationCall> {
@@ -154,24 +164,28 @@ internal class ArticleVoterTest {
}
@Test
fun `can update article if yours`() = listOf(ArticleVoter()).run {
fun `can update article if yours`(): Unit {
val article = getArticle(tesla)
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
can(ArticleVoter.Action.UPDATE, it, article) `should be` true
listOf(ArticleVoter(getRepo(article))).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
every { citizenOrNull } returns tesla
}.let {
can(ArticleVoter.Action.UPDATE, it, article) `should be` true
}
}
}
@Test
fun `can not update article if not yours`() = listOf(ArticleVoter()).run {
fun `can not update article if not yours`(): Unit {
val article = getArticle(tesla)
mockk<ApplicationCall> {
every { user } returns einstein.user
}.let {
can(ArticleVoter.Action.UPDATE, it, article) `should be` false
listOf(ArticleVoter(getRepo(article))).run {
mockk<ApplicationCall> {
every { user } returns einstein.user
every { citizenOrNull } returns einstein
}.let {
can(ArticleVoter.Action.UPDATE, it, article) `should be` false
}
}
}

View File

@@ -6,7 +6,9 @@ import fr.dcproject.entity.User
import fr.dcproject.entity.UserI
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.Vote
import fr.ktorVoter.can
import fr.ktorVoter.canAll
import io.ktor.application.ApplicationCall
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.mockk.every
@@ -21,7 +23,7 @@ import org.junit.jupiter.api.TestInstance
@KtorExperimentalLocationsAPI
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@Tag("voter")
internal class CitizenVoterTest {
class CitizenVoterTest {
private val tesla = CitizenBasic(
user = User(
username = "nicolas-tesla",
@@ -56,18 +58,18 @@ internal class CitizenVoterTest {
}
@Test
fun `support citizen`() = CitizenVoter().run {
fun `support citizen`(): Unit = CitizenVoter().run {
val p = object : ActionI {}
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
supports(CitizenVoter.Action.VIEW, it, einstein) `should be` true
supports(p, it, einstein) `should be` false
this(CitizenVoter.Action.VIEW, it, einstein) `should be` Vote.GRANTED
this(p, it, einstein) `should be` Vote.ABSTAIN
}
}
@Test
fun `can be view the citizen`() = listOf(CitizenVoter()).run {
fun `can be view the citizen`(): Unit = listOf(CitizenVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -76,16 +78,16 @@ internal class CitizenVoterTest {
}
@Test
fun `can be view the citizen list`() = listOf(CitizenVoter()).run {
fun `can be view the citizen list`(): Unit = listOf(CitizenVoter()).run {
mockk<ApplicationCall> {
every { user } returns einstein.user
}.let {
can(CitizenVoter.Action.VIEW, it, listOf(einstein, tesla)) `should be` true
canAll(CitizenVoter.Action.VIEW, it, listOf(einstein, tesla)) `should be` true
}
}
@Test
fun `can not view deleted citizen`() = listOf(CitizenVoter()).run {
fun `can not view deleted citizen`(): Unit = listOf(CitizenVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -94,7 +96,7 @@ internal class CitizenVoterTest {
}
@Test
fun `can be update itself`() = listOf(CitizenVoter()).run {
fun `can be update itself`(): Unit = listOf(CitizenVoter()).run {
mockk<ApplicationCall> {
every { user } returns einstein.user
}.let {
@@ -103,7 +105,7 @@ internal class CitizenVoterTest {
}
@Test
fun `can not be update other citizen`() = listOf(CitizenVoter()).run {
fun `can not be update other citizen`(): Unit = listOf(CitizenVoter()).run {
mockk<ApplicationCall> {
every { user } returns einstein.user
}.let {
@@ -112,7 +114,7 @@ internal class CitizenVoterTest {
}
@Test
fun `can be change password of itself`() = listOf(CitizenVoter()).run {
fun `can be change password of itself`(): Unit = listOf(CitizenVoter()).run {
mockk<ApplicationCall> {
every { user } returns einstein.user
}.let {
@@ -121,7 +123,7 @@ internal class CitizenVoterTest {
}
@Test
fun `can not be change password of other citizen`() = listOf(CitizenVoter()).run {
fun `can not be change password of other citizen`(): Unit = listOf(CitizenVoter()).run {
mockk<ApplicationCall> {
every { user } returns einstein.user
}.let {

View File

@@ -3,7 +3,10 @@ package fr.dcproject.security.voter
import fr.dcproject.entity.*
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.Vote
import fr.ktorVoter.can
import fr.ktorVoter.canAll
import fr.postgresjson.connexion.Paginated
import io.ktor.application.ApplicationCall
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.mockk.every
@@ -14,6 +17,7 @@ import org.joda.time.DateTime
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import fr.dcproject.repository.Article as ArticleRepo
@KtorExperimentalLocationsAPI
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@@ -51,6 +55,12 @@ internal class CommentVoterTest {
target = article1
)
private val comment2 = Comment(
content = "Hello2",
createdBy = einstein,
target = article1
)
private val commentTargetDeleted = Comment(
content = "Hello",
createdBy = tesla,
@@ -69,42 +79,48 @@ internal class CommentVoterTest {
target = ArticleRef()
)
private val repoArticle1 = mockk<ArticleRepo> {
every { findVerionsByVersionsId(1, 1, any()) } returns Paginated(listOf(article1), 0, 1, 1)
}
init {
mockkStatic("fr.dcproject.ApplicationContextKt")
}
@Test
fun `support comment`() = CommentVoter().run {
fun `support comment`(): Unit = CommentVoter().run {
val p = object : ActionI {}
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
supports(CommentVoter.Action.VIEW, it, comment1) `should be` true
supports(CommentVoter.Action.VIEW, it, article1) `should be` false
supports(p, it, comment1) `should be` false
this(CommentVoter.Action.VIEW, it, comment1) `should be` Vote.GRANTED
this(CommentVoter.Action.VIEW, it, article1) `should be` Vote.ABSTAIN
this(p, it, comment1) `should be` Vote.ABSTAIN
}
}
@Test
fun `can be view the comment`() = listOf(CommentVoter(), ArticleVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
can(CommentVoter.Action.VIEW, it, comment1) `should be` true
fun `can be view the comment`(): Unit {
listOf(CommentVoter(), ArticleVoter(repoArticle1)).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
can(CommentVoter.Action.VIEW, it, comment1) `should be` true
}
}
}
@Test
fun `can be view the comment list`() = listOf(CommentVoter()).run {
fun `can be view the comment list`(): Unit = listOf(CommentVoter()).run {
mockk<ApplicationCall> {
every { user } returns einstein.user
}.let {
can(CommentVoter.Action.VIEW, it, listOf(comment1)) `should be` true
canAll(CommentVoter.Action.VIEW, it, listOf(comment1)) `should be` true
}
}
@Test
fun `can be update your comment`() = listOf(CommentVoter()).run {
fun `can be update your comment`(): Unit = listOf(CommentVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -113,7 +129,7 @@ internal class CommentVoterTest {
}
@Test
fun `can not be update other comment`() = listOf(CommentVoter()).run {
fun `can not be update other comment`(): Unit = listOf(CommentVoter()).run {
mockk<ApplicationCall> {
every { user } returns einstein.user
}.let {
@@ -122,7 +138,7 @@ internal class CommentVoterTest {
}
@Test
fun `can not be delete your comment`() = listOf(CommentVoter()).run {
fun `can not be delete your comment`(): Unit = listOf(CommentVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -131,7 +147,7 @@ internal class CommentVoterTest {
}
@Test
fun `can be create a comment`() = listOf(CommentVoter(), ArticleVoter()).run {
fun `can be create a comment`(): Unit = listOf(CommentVoter(), ArticleVoter(repoArticle1)).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -140,7 +156,7 @@ internal class CommentVoterTest {
}
@Test
fun `can not be create a comment if target is deleted`() = listOf(CommentVoter(), ArticleVoter()).run {
fun `can not be create a comment if target is deleted`(): Unit = listOf(CommentVoter(), ArticleVoter(repoArticle1)).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -149,7 +165,7 @@ internal class CommentVoterTest {
}
@Test
fun `can not be create a comment if target has no user`() = listOf(CommentVoter(), ArticleVoter()).run {
fun `can not be create a comment if target has no user`(): Unit = listOf(CommentVoter(), ArticleVoter(repoArticle1)).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -158,7 +174,7 @@ internal class CommentVoterTest {
}
@Test
fun `can not be create a comment with other creator`() = listOf(CommentVoter()).run {
fun `can not be create a comment with other creator`(): Unit = listOf(CommentVoter()).run {
mockk<ApplicationCall> {
every { user } returns einstein.user
}.let {
@@ -167,7 +183,7 @@ internal class CommentVoterTest {
}
@Test
fun `can not be create a comment if is null`() = listOf(CommentVoter()).run {
fun `can not be create a comment if is null`(): Unit = listOf(CommentVoter()).run {
mockk<ApplicationCall> {
every { user } returns einstein.user
}.let {
@@ -176,7 +192,7 @@ internal class CommentVoterTest {
}
@Test
fun `can not be create a comment if not connected`() = listOf(CommentVoter()).run {
fun `can not be create a comment if not connected`(): Unit = listOf(CommentVoter()).run {
mockk<ApplicationCall> {
every { user } returns null
}.let {

View File

@@ -3,7 +3,9 @@ package fr.dcproject.security.voter
import fr.dcproject.entity.*
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.Vote
import fr.ktorVoter.can
import fr.ktorVoter.canAll
import io.ktor.application.ApplicationCall
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.mockk.every
@@ -63,19 +65,19 @@ internal class FollowVoterTest {
}
@Test
fun `support follow`() = FollowVoter().run {
fun `support follow`(): Unit = FollowVoter().run {
val p = object : ActionI {}
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
supports(FollowVoter.Action.VIEW, it, follow1) `should be` true
supports(FollowVoter.Action.VIEW, it, article1) `should be` false
supports(p, it, follow1) `should be` false
this(FollowVoter.Action.VIEW, it, follow1) `should be` Vote.GRANTED
this(FollowVoter.Action.VIEW, it, article1) `should be` Vote.ABSTAIN
this(p, it, follow1) `should be` Vote.ABSTAIN
}
}
@Test
fun `can be view the follow`() = listOf(FollowVoter()).run {
fun `can be view the follow`(): Unit = listOf(FollowVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -84,16 +86,16 @@ internal class FollowVoterTest {
}
@Test
fun `can be view the follow list`() = listOf(FollowVoter()).run {
fun `can be view the follow list`(): Unit = listOf(FollowVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
can(FollowVoter.Action.VIEW, it, listOf(follow1)) `should be` true
canAll(FollowVoter.Action.VIEW, it, listOf(follow1)) `should be` true
}
}
@Test
fun `can be view your anonymous follow`() = listOf(FollowVoter()).run {
fun `can be view your anonymous follow`(): Unit = listOf(FollowVoter()).run {
mockk<ApplicationCall> {
every { user } returns einstein.user
}.let {
@@ -102,7 +104,7 @@ internal class FollowVoterTest {
}
@Test
fun `can not be view the anonymous follow of other`() = listOf(FollowVoter()).run {
fun `can not be view the anonymous follow of other`(): Unit = listOf(FollowVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -111,7 +113,7 @@ internal class FollowVoterTest {
}
@Test
fun `can be follow article`() = listOf(FollowVoter()).run {
fun `can be follow article`(): Unit = listOf(FollowVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -120,7 +122,7 @@ internal class FollowVoterTest {
}
@Test
fun `can not be follow article if not connected`() = listOf(FollowVoter()).run {
fun `can not be follow article if not connected`(): Unit = listOf(FollowVoter()).run {
mockk<ApplicationCall> {
every { user } returns null
}.let {
@@ -129,7 +131,7 @@ internal class FollowVoterTest {
}
@Test
fun `can be unfollow article`() = listOf(FollowVoter()).run {
fun `can be unfollow article`(): Unit = listOf(FollowVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -138,7 +140,7 @@ internal class FollowVoterTest {
}
@Test
fun `can not be unfollow article if not connected`() = listOf(FollowVoter()).run {
fun `can not be unfollow article if not connected`(): Unit = listOf(FollowVoter()).run {
mockk<ApplicationCall> {
every { user } returns null
}.let {

View File

@@ -3,7 +3,9 @@ package fr.dcproject.security.voter
import fr.dcproject.entity.*
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.Vote
import fr.ktorVoter.can
import fr.ktorVoter.canAll
import io.ktor.application.ApplicationCall
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.mockk.every
@@ -47,19 +49,19 @@ internal class OpinionChoiceVoterTest {
}
@Test
fun `support opinion choice`() = OpinionChoiceVoter().run {
fun `support opinion choice`(): Unit = OpinionChoiceVoter().run {
val p = object : ActionI {}
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
supports(OpinionChoiceVoter.Action.VIEW, it, choice1) `should be` true
supports(OpinionChoiceVoter.Action.VIEW, it, article1) `should be` false
supports(p, it, choice1) `should be` false
this(OpinionChoiceVoter.Action.VIEW, it, choice1) `should be` Vote.GRANTED
this(OpinionChoiceVoter.Action.VIEW, it, article1) `should be` Vote.ABSTAIN
this(p, it, choice1) `should be` Vote.ABSTAIN
}
}
@Test
fun `can be view the opinion choice`() = listOf(OpinionChoiceVoter()).run {
fun `can be view the opinion choice`(): Unit = listOf(OpinionChoiceVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -68,11 +70,11 @@ internal class OpinionChoiceVoterTest {
}
@Test
fun `can be view the opinion choice list`() = listOf(OpinionChoiceVoter()).run {
fun `can be view the opinion choice list`(): Unit = listOf(OpinionChoiceVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
can(OpinionChoiceVoter.Action.VIEW, it, listOf(choice1)) `should be` true
canAll(OpinionChoiceVoter.Action.VIEW, it, listOf(choice1)) `should be` true
}
}
}

View File

@@ -3,7 +3,9 @@ package fr.dcproject.security.voter
import fr.dcproject.entity.*
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.Vote
import fr.ktorVoter.can
import fr.ktorVoter.canAll
import io.ktor.application.ApplicationCall
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.mockk.every
@@ -62,20 +64,20 @@ internal class OpinionVoterTest {
}
@Test
fun `support opinion`() = OpinionVoter().run {
fun `support opinion`(): Unit = OpinionVoter().run {
val p = object : ActionI {}
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
supports(OpinionVoter.Action.VIEW, it, opinion1) `should be` true
supports(OpinionVoter.Action.VIEW, it, article1) `should be` true
supports(OpinionVoter.Action.VIEW, it, einstein) `should be` false
supports(p, it, opinion1) `should be` false
this(OpinionVoter.Action.VIEW, it, opinion1) `should be` Vote.GRANTED
this(OpinionVoter.Action.VIEW, it, article1) `should be` Vote.GRANTED
this(OpinionVoter.Action.VIEW, it, einstein) `should be` Vote.ABSTAIN
this(p, it, opinion1) `should be` Vote.ABSTAIN
}
}
@Test
fun `can be view the opinion`() = listOf(OpinionVoter()).run {
fun `can be view the opinion`(): Unit = listOf(OpinionVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -84,7 +86,7 @@ internal class OpinionVoterTest {
}
@Test
fun `can be not view the opinion if is null`() = listOf(OpinionVoter()).run {
fun `can be not view the opinion if is null`(): Unit = listOf(OpinionVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -93,16 +95,16 @@ internal class OpinionVoterTest {
}
@Test
fun `can be view the opinion list`() = listOf(OpinionVoter()).run {
fun `can be view the opinion list`(): Unit = listOf(OpinionVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
can(OpinionVoter.Action.VIEW, it, listOf(opinion1)) `should be` true
canAll(OpinionVoter.Action.VIEW, it, listOf(opinion1)) `should be` true
}
}
@Test
fun `can be opinion an article`() = listOf(OpinionVoter()).run {
fun `can be opinion an article`(): Unit = listOf(OpinionVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -120,7 +122,7 @@ internal class OpinionVoterTest {
}
@Test
fun `can be remove opinion`() = listOf(OpinionVoter()).run {
fun `can be remove opinion`(): Unit = listOf(OpinionVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -129,7 +131,7 @@ internal class OpinionVoterTest {
}
@Test
fun `can not be remove opinion if not connected`() = listOf(OpinionVoter()).run {
fun `can not be remove opinion if not connected`(): Unit = listOf(OpinionVoter()).run {
mockk<ApplicationCall> {
every { user } returns null
}.let {
@@ -138,7 +140,7 @@ internal class OpinionVoterTest {
}
@Test
fun `can not be remove opinion of other user`() = listOf(OpinionVoter()).run {
fun `can not be remove opinion of other user`(): Unit = listOf(OpinionVoter()).run {
mockk<ApplicationCall> {
every { user } returns einstein.user
}.let {

View File

@@ -3,7 +3,10 @@ package fr.dcproject.security.voter
import fr.dcproject.entity.*
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.Vote
import fr.ktorVoter.can
import fr.ktorVoter.canAll
import fr.postgresjson.connexion.Paginated
import io.ktor.application.ApplicationCall
import io.ktor.locations.KtorExperimentalLocationsAPI
import io.mockk.every
@@ -77,19 +80,19 @@ internal class VoteVoterTest {
}
@Test
fun `support vote`() = VoteVoter().run {
fun `support vote`(): Unit = VoteVoter().run {
val p = object : ActionI {}
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
supports(VoteVoter.Action.VIEW, it, vote1) `should be` true
supports(VoteVoter.Action.VIEW, it, article1) `should be` false
supports(p, it, vote1) `should be` false
this(VoteVoter.Action.VIEW, it, vote1) `should be` Vote.GRANTED
this(VoteVoter.Action.VIEW, it, article1) `should be` Vote.ABSTAIN
this(p, it, vote1) `should be` Vote.ABSTAIN
}
}
@Test
fun `can be view your the vote`() = listOf(VoteVoter()).run {
fun `can be view your the vote`(): Unit = listOf(VoteVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -98,7 +101,7 @@ internal class VoteVoterTest {
}
@Test
fun `can not be view vote of other`() = listOf(VoteVoter()).run {
fun `can not be view vote of other`(): Unit = listOf(VoteVoter()).run {
mockk<ApplicationCall> {
every { user } returns einstein.user
}.let {
@@ -107,7 +110,7 @@ internal class VoteVoterTest {
}
@Test
fun `can be not view the vote if is null`() = listOf(VoteVoter()).run {
fun `can be not view the vote if is null`(): Unit = listOf(VoteVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -116,25 +119,27 @@ internal class VoteVoterTest {
}
@Test
fun `can be view your votes list`() = listOf(VoteVoter()).run {
fun `can be view your votes list`(): Unit = listOf(VoteVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
can(VoteVoter.Action.VIEW, it, listOf(vote1)) `should be` true
canAll(VoteVoter.Action.VIEW, it, listOf(vote1)) `should be` true
}
}
@Test
fun `can be vote an article`() = listOf(VoteVoter(), ArticleVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
can(VoteVoter.Action.CREATE, it, vote1) `should be` true
fun `can be vote an article`(): Unit {
listOf(VoteVoter(), ArticleVoter(mockk())).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
can(VoteVoter.Action.CREATE, it, vote1) `should be` true
}
}
}
@Test
fun `can not be vote if not connected`() = listOf(VoteVoter()).run {
fun `can not be vote if not connected`(): Unit = listOf(VoteVoter()).run {
mockk<ApplicationCall> {
every { user } returns null
}.let {
@@ -143,7 +148,7 @@ internal class VoteVoterTest {
}
@Test
fun `can not be vote an article if article is deleted`() = listOf(VoteVoter(), ArticleVoter()).run {
fun `can not be vote an article if article is deleted`(): Unit = listOf(VoteVoter(), ArticleVoter(mockk())).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -152,7 +157,7 @@ internal class VoteVoterTest {
}
@Test
fun `can not be vote an article if article have no user`() = listOf(VoteVoter(), ArticleVoter()).run {
fun `can not be vote an article if article have no user`(): Unit = listOf(VoteVoter(), ArticleVoter(mockk())).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -161,7 +166,7 @@ internal class VoteVoterTest {
}
@Test
fun `can not be comment an article if article is deleted`() = listOf(VoteVoter(), ArticleVoter()).run {
fun `can not be comment an article if article is deleted`(): Unit = listOf(VoteVoter(), ArticleVoter(mockk())).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {

View File

@@ -3,6 +3,7 @@ package fr.dcproject.security.voter
import fr.dcproject.entity.*
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.Vote
import fr.ktorVoter.VoterException
import fr.ktorVoter.can
import io.ktor.application.ApplicationCall
@@ -74,19 +75,19 @@ internal class WorkgroupVoterTest {
}
@Test
fun `support workgroup`() = WorkgroupVoter().run {
fun `support workgroup`(): Unit = WorkgroupVoter().run {
val p = object : ActionI {}
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
supports(WorkgroupVoter.Action.VIEW, it, workgroupPublic) `should be` true
supports(WorkgroupVoter.Action.VIEW, it, article1) `should be` false
supports(p, it, workgroupPublic) `should be` false
this(WorkgroupVoter.Action.VIEW, it, workgroupPublic) `should be` Vote.GRANTED
this(WorkgroupVoter.Action.VIEW, it, article1) `should be` Vote.ABSTAIN
this(p, it, workgroupPublic) `should be` Vote.ABSTAIN
}
}
@Test
fun `can be view your workgroup`() = listOf(WorkgroupVoter()).run {
fun `can be view your workgroup`(): Unit = listOf(WorkgroupVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -95,7 +96,7 @@ internal class WorkgroupVoterTest {
}
@Test
fun `can be view your workgroup if is not public`() = listOf(WorkgroupVoter()).run {
fun `can be view your workgroup if is not public`(): Unit = listOf(WorkgroupVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -104,7 +105,7 @@ internal class WorkgroupVoterTest {
}
@Test
fun `can be view workgroup of other if is public`() = listOf(WorkgroupVoter()).run {
fun `can be view workgroup of other if is public`(): Unit = listOf(WorkgroupVoter()).run {
mockk<ApplicationCall> {
every { user } returns einstein.user
}.let {
@@ -113,7 +114,7 @@ internal class WorkgroupVoterTest {
}
@Test
fun `can not be view workgroup of other if is not public`() = listOf(WorkgroupVoter()).run {
fun `can not be view workgroup of other if is not public`(): Unit = listOf(WorkgroupVoter()).run {
mockk<ApplicationCall> {
every { user } returns einstein.user
}.let {
@@ -122,7 +123,7 @@ internal class WorkgroupVoterTest {
}
@Test
fun `can be not view the workgroup if is null`() = listOf(WorkgroupVoter()).run {
fun `can be not view the workgroup if is null`(): Unit = listOf(WorkgroupVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -131,16 +132,18 @@ internal class WorkgroupVoterTest {
}
@Test
fun `can be view your workgroup list`() = listOf(WorkgroupVoter()).run {
fun `can be view your workgroup list`(): Unit = listOf(WorkgroupVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
can(WorkgroupVoter.Action.VIEW, it, listOf(workgroupPublic)) `should be` true
listOf(workgroupPublic).map { workgroup ->
can(WorkgroupVoter.Action.VIEW, it, workgroup)
}.all { it } `should be` true
}
}
@Test
fun `can be create workgroup`() = listOf(WorkgroupVoter()).run {
fun `can be create workgroup`(): Unit = listOf(WorkgroupVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -149,7 +152,7 @@ internal class WorkgroupVoterTest {
}
@Test
fun `can not be create workgroup if not connected`() = listOf(WorkgroupVoter()).run {
fun `can not be create workgroup if not connected`(): Unit = listOf(WorkgroupVoter()).run {
mockk<ApplicationCall> {
every { user } returns null
}.let {
@@ -158,7 +161,7 @@ internal class WorkgroupVoterTest {
}
@Test
fun `can be delete workgroup if owner`() = listOf(WorkgroupVoter()).run {
fun `can be delete workgroup if owner`(): Unit = listOf(WorkgroupVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -167,7 +170,7 @@ internal class WorkgroupVoterTest {
}
@Test
fun `can not be delete workgroup if not owner`() = listOf(WorkgroupVoter()).run {
fun `can not be delete workgroup if not owner`(): Unit = listOf(WorkgroupVoter()).run {
mockk<ApplicationCall> {
every { user } returns einstein.user
}.let {
@@ -176,7 +179,7 @@ internal class WorkgroupVoterTest {
}
@Test
fun `can be update workgroup if owner`() = listOf(WorkgroupVoter()).run {
fun `can be update workgroup if owner`(): Unit = listOf(WorkgroupVoter()).run {
mockk<ApplicationCall> {
every { user } returns tesla.user
}.let {
@@ -185,7 +188,7 @@ internal class WorkgroupVoterTest {
}
@Test
fun `can not be update workgroup if not owner`() = listOf(WorkgroupVoter()).run {
fun `can not be update workgroup if not owner`(): Unit = listOf(WorkgroupVoter()).run {
mockk<ApplicationCall> {
every { user } returns einstein.user
}.let {