From aa7ca26b515495f5cfa365df2154bac239ea5d27 Mon Sep 17 00:00:00 2001 From: Fabrice Lecomte Date: Mon, 16 Mar 2020 02:42:20 +0100 Subject: [PATCH] Improve voter --- .../fr/dcproject/security/voter/CheckClass.kt | 20 +++++++++++++++++++ .../fr/dcproject/security/voter/Voter.kt | 11 ++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 src/main/kotlin/fr/dcproject/security/voter/CheckClass.kt diff --git a/src/main/kotlin/fr/dcproject/security/voter/CheckClass.kt b/src/main/kotlin/fr/dcproject/security/voter/CheckClass.kt new file mode 100644 index 0000000..f05463f --- /dev/null +++ b/src/main/kotlin/fr/dcproject/security/voter/CheckClass.kt @@ -0,0 +1,20 @@ +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) + } +} \ No newline at end of file diff --git a/src/main/kotlin/fr/dcproject/security/voter/Voter.kt b/src/main/kotlin/fr/dcproject/security/voter/Voter.kt index c49a8b8..1d3b7b1 100644 --- a/src/main/kotlin/fr/dcproject/security/voter/Voter.kt +++ b/src/main/kotlin/fr/dcproject/security/voter/Voter.kt @@ -19,10 +19,13 @@ interface Voter { } fun List.can(action: ActionI, call: ApplicationCall, subject: Any? = null): Boolean { - val votes = this - .filter { it.supports(action, call, subject) } - .ifEmpty { throw NoVoterException(action) } - .map { it.vote(action, call, subject) } + val listOfSubject: List = if (subject !is List<*>) listOf(subject) else subject + val votes: List = 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 } }