#24 Move voter code to an external library

This commit is contained in:
2020-03-25 02:08:31 +01:00
parent 575752cdc7
commit e572ca0024
35 changed files with 95 additions and 154 deletions

View File

@@ -87,6 +87,7 @@ dependencies {
implementation("com.auth0:java-jwt:3.8.2") implementation("com.auth0:java-jwt:3.8.2")
implementation("com.github.jasync-sql:jasync-postgresql:1.0.7") implementation("com.github.jasync-sql:jasync-postgresql:1.0.7")
implementation("fr.postgresjson:postgresjson:$postgresjson_version") implementation("fr.postgresjson:postgresjson:$postgresjson_version")
implementation("fr.ktor-voter:ktor-voter:1.0.0")
implementation("com.sendgrid:sendgrid-java:4.4.1") implementation("com.sendgrid:sendgrid-java:4.4.1")
implementation("io.lettuce:lettuce-core:5.2.2.RELEASE") implementation("io.lettuce:lettuce-core:5.2.2.RELEASE")
implementation("com.rabbitmq:amqp-client:5.8.0") implementation("com.rabbitmq:amqp-client:5.8.0")

View File

@@ -13,6 +13,8 @@ import fr.dcproject.event.EventSubscriber
import fr.dcproject.event.configEvent import fr.dcproject.event.configEvent
import fr.dcproject.routes.* import fr.dcproject.routes.*
import fr.dcproject.security.voter.* import fr.dcproject.security.voter.*
import fr.ktorVoter.AuthorizationVoter
import fr.ktorVoter.ForbiddenException
import fr.postgresjson.migration.Migrations import fr.postgresjson.migration.Migrations
import io.ktor.application.Application import io.ktor.application.Application
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall

View File

@@ -1,7 +1,8 @@
package fr.dcproject package fr.dcproject
import fr.dcproject.entity.User
import fr.dcproject.entity.UserI import fr.dcproject.entity.UserI
import fr.dcproject.security.voter.ForbiddenException import fr.ktorVoter.ForbiddenException
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
import io.ktor.auth.authentication import io.ktor.auth.authentication
import io.ktor.util.AttributeKey import io.ktor.util.AttributeKey
@@ -26,3 +27,5 @@ val ApplicationCall.citizenOrNull: CitizenEntity?
val PipelineContext<Unit, ApplicationCall>.citizen get() = context.citizen val PipelineContext<Unit, ApplicationCall>.citizen get() = context.citizen
val PipelineContext<Unit, ApplicationCall>.citizenOrNull get() = context.citizenOrNull val PipelineContext<Unit, ApplicationCall>.citizenOrNull get() = context.citizenOrNull
val ApplicationCall.user get() = authentication.principal<User>()

View File

@@ -6,7 +6,7 @@ import fr.dcproject.event.ArticleUpdate
import fr.dcproject.repository.Article.Filter import fr.dcproject.repository.Article.Filter
import fr.dcproject.security.voter.ArticleVoter.Action.CREATE import fr.dcproject.security.voter.ArticleVoter.Action.CREATE
import fr.dcproject.security.voter.ArticleVoter.Action.VIEW import fr.dcproject.security.voter.ArticleVoter.Action.VIEW
import fr.dcproject.security.voter.assertCan import fr.ktorVoter.assertCan
import fr.dcproject.views.ArticleViewManager import fr.dcproject.views.ArticleViewManager
import fr.postgresjson.repository.RepositoryI import fr.postgresjson.repository.RepositoryI
import io.ktor.application.application import io.ktor.application.application

View File

@@ -9,7 +9,7 @@ import fr.dcproject.routes.CitizenPaths.CitizensRequest
import fr.dcproject.routes.CitizenPaths.CurrentCitizenRequest import fr.dcproject.routes.CitizenPaths.CurrentCitizenRequest
import fr.dcproject.security.voter.CitizenVoter.Action.CHANGE_PASSWORD import fr.dcproject.security.voter.CitizenVoter.Action.CHANGE_PASSWORD
import fr.dcproject.security.voter.CitizenVoter.Action.VIEW import fr.dcproject.security.voter.CitizenVoter.Action.VIEW
import fr.dcproject.security.voter.assertCan import fr.ktorVoter.assertCan
import fr.postgresjson.repository.RepositoryI.Direction import fr.postgresjson.repository.RepositoryI.Direction
import io.ktor.application.call import io.ktor.application.call
import io.ktor.auth.UserPasswordCredential import io.ktor.auth.UserPasswordCredential

View File

@@ -5,7 +5,7 @@ import fr.dcproject.entity.Comment
import fr.dcproject.entity.CommentRef import fr.dcproject.entity.CommentRef
import fr.dcproject.routes.CommentPaths.CreateCommentRequest.Content import fr.dcproject.routes.CommentPaths.CreateCommentRequest.Content
import fr.dcproject.security.voter.CommentVoter.Action.* import fr.dcproject.security.voter.CommentVoter.Action.*
import fr.dcproject.security.voter.assertCan import fr.ktorVoter.assertCan
import io.ktor.application.call import io.ktor.application.call
import io.ktor.features.NotFoundException import io.ktor.features.NotFoundException
import io.ktor.http.HttpStatusCode import io.ktor.http.HttpStatusCode

View File

@@ -6,7 +6,7 @@ import fr.dcproject.entity.Citizen
import fr.dcproject.repository.CommentArticle.Sort import fr.dcproject.repository.CommentArticle.Sort
import fr.dcproject.security.voter.CommentVoter.Action.CREATE import fr.dcproject.security.voter.CommentVoter.Action.CREATE
import fr.dcproject.security.voter.CommentVoter.Action.VIEW import fr.dcproject.security.voter.CommentVoter.Action.VIEW
import fr.dcproject.security.voter.assertCan import fr.ktorVoter.assertCan
import io.ktor.application.call import io.ktor.application.call
import io.ktor.http.HttpStatusCode import io.ktor.http.HttpStatusCode
import io.ktor.locations.KtorExperimentalLocationsAPI import io.ktor.locations.KtorExperimentalLocationsAPI

View File

@@ -5,7 +5,7 @@ import fr.dcproject.entity.Citizen
import fr.dcproject.entity.ConstitutionRef import fr.dcproject.entity.ConstitutionRef
import fr.dcproject.security.voter.CommentVoter.Action.CREATE import fr.dcproject.security.voter.CommentVoter.Action.CREATE
import fr.dcproject.security.voter.CommentVoter.Action.VIEW import fr.dcproject.security.voter.CommentVoter.Action.VIEW
import fr.dcproject.security.voter.assertCan import fr.ktorVoter.assertCan
import io.ktor.application.call import io.ktor.application.call
import io.ktor.http.HttpStatusCode import io.ktor.http.HttpStatusCode
import io.ktor.locations.KtorExperimentalLocationsAPI import io.ktor.locations.KtorExperimentalLocationsAPI

View File

@@ -4,7 +4,7 @@ import fr.dcproject.citizen
import fr.dcproject.entity.request.Constitution import fr.dcproject.entity.request.Constitution
import fr.dcproject.security.voter.ConstitutionVoter.Action.CREATE import fr.dcproject.security.voter.ConstitutionVoter.Action.CREATE
import fr.dcproject.security.voter.ConstitutionVoter.Action.VIEW import fr.dcproject.security.voter.ConstitutionVoter.Action.VIEW
import fr.dcproject.security.voter.assertCan import fr.ktorVoter.assertCan
import fr.postgresjson.repository.RepositoryI import fr.postgresjson.repository.RepositoryI
import io.ktor.application.call import io.ktor.application.call
import io.ktor.locations.KtorExperimentalLocationsAPI import io.ktor.locations.KtorExperimentalLocationsAPI

View File

@@ -4,7 +4,7 @@ import fr.dcproject.citizen
import fr.dcproject.entity.ArticleRef import fr.dcproject.entity.ArticleRef
import fr.dcproject.entity.Citizen import fr.dcproject.entity.Citizen
import fr.dcproject.security.voter.FollowVoter.Action.* import fr.dcproject.security.voter.FollowVoter.Action.*
import fr.dcproject.security.voter.assertCan import fr.ktorVoter.assertCan
import io.ktor.application.call import io.ktor.application.call
import io.ktor.http.HttpStatusCode import io.ktor.http.HttpStatusCode
import io.ktor.locations.* import io.ktor.locations.*

View File

@@ -4,7 +4,7 @@ import fr.dcproject.citizen
import fr.dcproject.entity.CitizenRef import fr.dcproject.entity.CitizenRef
import fr.dcproject.entity.ConstitutionRef import fr.dcproject.entity.ConstitutionRef
import fr.dcproject.security.voter.FollowVoter.Action.* import fr.dcproject.security.voter.FollowVoter.Action.*
import fr.dcproject.security.voter.assertCan import fr.ktorVoter.assertCan
import io.ktor.application.call import io.ktor.application.call
import io.ktor.http.HttpStatusCode import io.ktor.http.HttpStatusCode
import io.ktor.locations.* import io.ktor.locations.*

View File

@@ -7,7 +7,7 @@ import fr.dcproject.entity.request.RequestBuilder
import fr.dcproject.entity.request.getContent import fr.dcproject.entity.request.getContent
import fr.dcproject.security.voter.OpinionVoter.Action.CREATE import fr.dcproject.security.voter.OpinionVoter.Action.CREATE
import fr.dcproject.security.voter.OpinionVoter.Action.VIEW import fr.dcproject.security.voter.OpinionVoter.Action.VIEW
import fr.dcproject.security.voter.assertCan import fr.ktorVoter.assertCan
import fr.dcproject.utils.toUUID import fr.dcproject.utils.toUUID
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
import io.ktor.application.call import io.ktor.application.call

View File

@@ -2,7 +2,7 @@ package fr.dcproject.routes
import fr.dcproject.entity.OpinionChoice import fr.dcproject.entity.OpinionChoice
import fr.dcproject.security.voter.OpinionChoiceVoter.Action.VIEW import fr.dcproject.security.voter.OpinionChoiceVoter.Action.VIEW
import fr.dcproject.security.voter.assertCan import fr.ktorVoter.assertCan
import io.ktor.application.call import io.ktor.application.call
import io.ktor.locations.KtorExperimentalLocationsAPI import io.ktor.locations.KtorExperimentalLocationsAPI
import io.ktor.locations.Location import io.ktor.locations.Location

View File

@@ -8,7 +8,7 @@ import fr.dcproject.routes.VoteArticlePaths.ArticleVoteRequest
import fr.dcproject.routes.VoteArticlePaths.CommentVoteRequest import fr.dcproject.routes.VoteArticlePaths.CommentVoteRequest
import fr.dcproject.security.voter.VoteVoter.Action.CREATE import fr.dcproject.security.voter.VoteVoter.Action.CREATE
import fr.dcproject.security.voter.VoteVoter.Action.VIEW import fr.dcproject.security.voter.VoteVoter.Action.VIEW
import fr.dcproject.security.voter.assertCan import fr.ktorVoter.assertCan
import fr.dcproject.utils.toUUID import fr.dcproject.utils.toUUID
import io.ktor.application.call import io.ktor.application.call
import io.ktor.http.HttpStatusCode import io.ktor.http.HttpStatusCode

View File

@@ -4,7 +4,7 @@ import fr.dcproject.citizen
import fr.dcproject.entity.Citizen import fr.dcproject.entity.Citizen
import fr.dcproject.routes.VoteConstitutionPaths.ConstitutionVoteRequest.Content import fr.dcproject.routes.VoteConstitutionPaths.ConstitutionVoteRequest.Content
import fr.dcproject.security.voter.VoteVoter.Action.CREATE import fr.dcproject.security.voter.VoteVoter.Action.CREATE
import fr.dcproject.security.voter.assertCan import fr.ktorVoter.assertCan
import io.ktor.application.call import io.ktor.application.call
import io.ktor.http.HttpStatusCode import io.ktor.http.HttpStatusCode
import io.ktor.locations.KtorExperimentalLocationsAPI import io.ktor.locations.KtorExperimentalLocationsAPI

View File

@@ -12,7 +12,7 @@ import fr.dcproject.security.voter.WorkgroupVoter.Action.UPDATE
import fr.dcproject.security.voter.WorkgroupVoter.ActionMembers.ADD as ADD_MEMBERS import fr.dcproject.security.voter.WorkgroupVoter.ActionMembers.ADD as ADD_MEMBERS
import fr.dcproject.security.voter.WorkgroupVoter.ActionMembers.UPDATE as UPDATE_MEMBERS import fr.dcproject.security.voter.WorkgroupVoter.ActionMembers.UPDATE as UPDATE_MEMBERS
import fr.dcproject.security.voter.WorkgroupVoter.ActionMembers.REMOVE as REMOVE_MEMBERS import fr.dcproject.security.voter.WorkgroupVoter.ActionMembers.REMOVE as REMOVE_MEMBERS
import fr.dcproject.security.voter.assertCan import fr.ktorVoter.assertCan
import fr.dcproject.utils.toUUID import fr.dcproject.utils.toUUID
import fr.postgresjson.repository.RepositoryI import fr.postgresjson.repository.RepositoryI
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall

View File

@@ -3,6 +3,11 @@ package fr.dcproject.security.voter
import fr.dcproject.entity.ArticleAuthI import fr.dcproject.entity.ArticleAuthI
import fr.dcproject.entity.ArticleI import fr.dcproject.entity.ArticleI
import fr.dcproject.entity.UserI import fr.dcproject.entity.UserI
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.Vote
import fr.ktorVoter.Voter
import fr.ktorVoter.checkClass
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
import fr.dcproject.entity.Comment as CommentEntity import fr.dcproject.entity.Comment as CommentEntity
import fr.dcproject.entity.Vote as VoteEntity import fr.dcproject.entity.Vote as VoteEntity

View File

@@ -1,20 +0,0 @@
package fr.dcproject.security.voter
import kotlin.reflect.KClass
import kotlin.reflect.full.isSubclassOf
class WrongClassException(
expected: KClass<*>,
current: KClass<*>?
) : VoterException("Can not define authorization with class $current. Need $expected")
fun Voter.checkClass(
expected: KClass<*>,
subject: Any?
) {
if (subject != null && !subject::class.isSubclassOf(expected)) {
throw WrongClassException(expected, subject::class)
} else if (subject == null) {
throw WrongClassException(expected, null)
}
}

View File

@@ -2,6 +2,10 @@ package fr.dcproject.security.voter
import fr.dcproject.entity.CitizenBasicI import fr.dcproject.entity.CitizenBasicI
import fr.dcproject.entity.UserI import fr.dcproject.entity.UserI
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.Vote
import fr.ktorVoter.Voter
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
import io.ktor.locations.KtorExperimentalLocationsAPI import io.ktor.locations.KtorExperimentalLocationsAPI

View File

@@ -1,6 +1,10 @@
package fr.dcproject.security.voter package fr.dcproject.security.voter
import fr.dcproject.entity.Comment import fr.dcproject.entity.Comment
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.Vote
import fr.ktorVoter.Voter
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
class CommentVoter : Voter { class CommentVoter : Voter {

View File

@@ -3,6 +3,10 @@ package fr.dcproject.security.voter
import fr.dcproject.entity.Comment import fr.dcproject.entity.Comment
import fr.dcproject.entity.ConstitutionSimple import fr.dcproject.entity.ConstitutionSimple
import fr.dcproject.entity.UserI import fr.dcproject.entity.UserI
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.Vote
import fr.ktorVoter.Voter
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
import fr.dcproject.entity.Vote as VoteEntity import fr.dcproject.entity.Vote as VoteEntity

View File

@@ -1,5 +1,9 @@
package fr.dcproject.security.voter package fr.dcproject.security.voter
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.Vote
import fr.ktorVoter.Voter
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
import fr.dcproject.entity.Follow as FollowEntity import fr.dcproject.entity.Follow as FollowEntity
import fr.dcproject.entity.User as UserEntity import fr.dcproject.entity.User as UserEntity

View File

@@ -1,6 +1,9 @@
package fr.dcproject.security.voter package fr.dcproject.security.voter
import fr.dcproject.entity.OpinionChoice import fr.dcproject.entity.OpinionChoice
import fr.ktorVoter.ActionI
import fr.ktorVoter.Vote
import fr.ktorVoter.Voter
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
class OpinionChoiceVoter : Voter { class OpinionChoiceVoter : Voter {

View File

@@ -2,6 +2,10 @@ package fr.dcproject.security.voter
import fr.dcproject.entity.ArticleAuthI import fr.dcproject.entity.ArticleAuthI
import fr.dcproject.entity.Opinion import fr.dcproject.entity.Opinion
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.Vote
import fr.ktorVoter.Voter
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
class OpinionVoter : Voter { class OpinionVoter : Voter {

View File

@@ -1,5 +1,9 @@
package fr.dcproject.security.voter package fr.dcproject.security.voter
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.Vote
import fr.ktorVoter.Voter
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
import fr.dcproject.entity.Vote as VoteEntity import fr.dcproject.entity.Vote as VoteEntity

View File

@@ -1,110 +0,0 @@
package fr.dcproject.security.voter
import fr.dcproject.entity.User
import io.ktor.application.ApplicationCall
import io.ktor.application.ApplicationCallPipeline
import io.ktor.application.ApplicationFeature
import io.ktor.auth.authentication
import io.ktor.http.HttpStatusCode
import io.ktor.response.respond
import io.ktor.util.AttributeKey
import io.ktor.util.KtorExperimentalAPI
import io.ktor.util.pipeline.PipelineContext
interface ActionI
interface Voter {
fun supports(action: ActionI, call: ApplicationCall, subject: Any? = null): Boolean
fun vote(action: ActionI, call: ApplicationCall, subject: Any? = null): Vote
}
fun List<Voter>.can(action: ActionI, call: ApplicationCall, subject: Any? = null): Boolean {
val listOfSubject: List<Any?> = if (subject !is List<*>) listOf(subject) else subject
val votes: List<Vote> = listOfSubject.flatMap { subject ->
this
.filter { it.supports(action, call, subject) }
.ifEmpty { throw NoVoterException(action) }
.map { it.vote(action, call, subject) }
}
return votes.all { it in listOf(Vote.GRANTED, Vote.ABSTAIN) } and votes.any { it == Vote.GRANTED }
}
enum class Vote {
GRANTED,
ABSTAIN,
DENIED;
companion object {
fun isGranted(lambda: () -> Boolean): Vote {
return if (lambda()) GRANTED else DENIED
}
}
}
private val votersAttributeKey = AttributeKey<List<Voter>>("voters")
fun ApplicationCall.assertCan(action: ActionI, subject: Any? = null, agreeIfNullOrEmpty: Boolean = true) {
val isNullOrEmpty = (subject == null || (subject is Collection<*> && subject.isNullOrEmpty()))
if (!can(action, subject) && !agreeIfNullOrEmpty && isNullOrEmpty) {
throw UnauthorizedException(action)
}
}
fun PipelineContext<Unit, ApplicationCall>.assertCan(action: ActionI, subject: Any? = null, agreeIfNullOrEmpty: Boolean = true) =
context.assertCan(action, subject, agreeIfNullOrEmpty)
fun PipelineContext<Unit, ApplicationCall>.can(action: ActionI, subject: Any? = null) =
context.can(action, subject)
fun ApplicationCall.can(action: ActionI, subject: Any? = null): Boolean {
val voters = attributes[votersAttributeKey]
return voters.can(action, this, subject)
}
abstract class VoterException(message: String) : Throwable(message)
class NoVoterException(action: ActionI) : VoterException("No voter found for action '$action'")
class UnauthorizedException(action: ActionI) : VoterException("Unauthorized for action '$action'")
class ForbiddenException(message: String? = null) : Throwable(message)
val ApplicationCall.user get() = authentication.principal<User>()
class AuthorizationVoter {
/**
* Configuration for [AuthorizationVoter] feature.
*/
class Configuration {
var voters = mutableListOf<Voter>()
fun voter(voter: Voter) = voters.add(voter)
}
/**
* Object for installing feature
*/
companion object Feature : ApplicationFeature<ApplicationCallPipeline, Configuration, AuthorizationVoter> {
override val key = AttributeKey<AuthorizationVoter>("Voter")
@KtorExperimentalAPI
override fun install(
pipeline: ApplicationCallPipeline,
configure: Configuration.() -> Unit
): AuthorizationVoter {
val configuration = Configuration().apply(configure)
pipeline.intercept(ApplicationCallPipeline.Features) {
context.attributes.put(votersAttributeKey, configuration.voters)
try {
proceed()
} catch (e: VoterException) {
context.respond(HttpStatusCode.Forbidden)
}
}
return AuthorizationVoter()
}
}
}

View File

@@ -2,6 +2,11 @@ package fr.dcproject.security.voter
import fr.dcproject.citizenOrNull import fr.dcproject.citizenOrNull
import fr.dcproject.entity.* import fr.dcproject.entity.*
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.Vote
import fr.ktorVoter.Voter
import fr.ktorVoter.VoterException
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
class WorkgroupVoter : Voter { class WorkgroupVoter : Voter {

View File

@@ -1,6 +1,9 @@
package fr.dcproject.security.voter package fr.dcproject.security.voter
import fr.dcproject.entity.* import fr.dcproject.entity.*
import fr.dcproject.user
import fr.ktorVoter.Vote
import fr.ktorVoter.can
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
import io.mockk.every import io.mockk.every
import io.mockk.mockk import io.mockk.mockk
@@ -34,7 +37,7 @@ internal class ArticleVoterTest {
) )
init { init {
mockkStatic("fr.dcproject.security.voter.VoterKt") mockkStatic("fr.dcproject.ApplicationContextKt")
} }
@Test @Test

View File

@@ -1,6 +1,12 @@
package fr.dcproject.security.voter package fr.dcproject.security.voter
import fr.dcproject.entity.* import fr.dcproject.entity.CitizenBasic
import fr.dcproject.entity.CitizenI
import fr.dcproject.entity.User
import fr.dcproject.entity.UserI
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.can
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
import io.ktor.locations.KtorExperimentalLocationsAPI import io.ktor.locations.KtorExperimentalLocationsAPI
import io.mockk.every import io.mockk.every
@@ -46,7 +52,7 @@ internal class CitizenVoterTest {
).apply { deletedAt = DateTime.now() } ).apply { deletedAt = DateTime.now() }
init { init {
mockkStatic("fr.dcproject.security.voter.VoterKt") mockkStatic("fr.dcproject.ApplicationContextKt")
} }
@Test @Test

View File

@@ -1,6 +1,9 @@
package fr.dcproject.security.voter package fr.dcproject.security.voter
import fr.dcproject.entity.* import fr.dcproject.entity.*
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.can
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
import io.ktor.locations.KtorExperimentalLocationsAPI import io.ktor.locations.KtorExperimentalLocationsAPI
import io.mockk.every import io.mockk.every
@@ -66,7 +69,7 @@ internal class CommentVoterTest {
) )
init { init {
mockkStatic("fr.dcproject.security.voter.VoterKt") mockkStatic("fr.dcproject.ApplicationContextKt")
} }
@Test @Test

View File

@@ -1,6 +1,9 @@
package fr.dcproject.security.voter package fr.dcproject.security.voter
import fr.dcproject.entity.* import fr.dcproject.entity.*
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.can
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
import io.ktor.locations.KtorExperimentalLocationsAPI import io.ktor.locations.KtorExperimentalLocationsAPI
import io.mockk.every import io.mockk.every
@@ -56,7 +59,7 @@ internal class FollowVoterTest {
) )
init { init {
mockkStatic("fr.dcproject.security.voter.VoterKt") mockkStatic("fr.dcproject.ApplicationContextKt")
} }
@Test @Test

View File

@@ -1,6 +1,9 @@
package fr.dcproject.security.voter package fr.dcproject.security.voter
import fr.dcproject.entity.* import fr.dcproject.entity.*
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.can
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
import io.ktor.locations.KtorExperimentalLocationsAPI import io.ktor.locations.KtorExperimentalLocationsAPI
import io.mockk.every import io.mockk.every
@@ -40,7 +43,7 @@ internal class OpinionChoiceVoterTest {
) )
init { init {
mockkStatic("fr.dcproject.security.voter.VoterKt") mockkStatic("fr.dcproject.ApplicationContextKt")
} }
@Test @Test

View File

@@ -1,6 +1,9 @@
package fr.dcproject.security.voter package fr.dcproject.security.voter
import fr.dcproject.entity.* import fr.dcproject.entity.*
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.can
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
import io.ktor.locations.KtorExperimentalLocationsAPI import io.ktor.locations.KtorExperimentalLocationsAPI
import io.mockk.every import io.mockk.every
@@ -55,7 +58,7 @@ internal class OpinionVoterTest {
) )
init { init {
mockkStatic("fr.dcproject.security.voter.VoterKt") mockkStatic("fr.dcproject.ApplicationContextKt")
} }
@Test @Test

View File

@@ -1,7 +1,9 @@
package fr.dcproject.security.voter package fr.dcproject.security.voter
import fr.dcproject.entity.* import fr.dcproject.entity.*
import fr.dcproject.entity.Vote as VoteEntity import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.can
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
import io.ktor.locations.KtorExperimentalLocationsAPI import io.ktor.locations.KtorExperimentalLocationsAPI
import io.mockk.every import io.mockk.every
@@ -12,6 +14,7 @@ import org.joda.time.DateTime
import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.TestInstance
import fr.dcproject.entity.Vote as VoteEntity
@KtorExperimentalLocationsAPI @KtorExperimentalLocationsAPI
@TestInstance(TestInstance.Lifecycle.PER_CLASS) @TestInstance(TestInstance.Lifecycle.PER_CLASS)
@@ -70,7 +73,7 @@ internal class VoteVoterTest {
) )
init { init {
mockkStatic("fr.dcproject.security.voter.VoterKt") mockkStatic("fr.dcproject.ApplicationContextKt")
} }
@Test @Test

View File

@@ -1,6 +1,10 @@
package fr.dcproject.security.voter package fr.dcproject.security.voter
import fr.dcproject.entity.* import fr.dcproject.entity.*
import fr.dcproject.user
import fr.ktorVoter.ActionI
import fr.ktorVoter.VoterException
import fr.ktorVoter.can
import io.ktor.application.ApplicationCall import io.ktor.application.ApplicationCall
import io.ktor.locations.KtorExperimentalLocationsAPI import io.ktor.locations.KtorExperimentalLocationsAPI
import io.mockk.every import io.mockk.every
@@ -66,7 +70,7 @@ internal class WorkgroupVoterTest {
private val workgroupref = WorkgroupRef() private val workgroupref = WorkgroupRef()
init { init {
mockkStatic("fr.dcproject.security.voter.VoterKt") mockkStatic("fr.dcproject.ApplicationContextKt")
} }
@Test @Test