From 64fa0912b83bd038ed431fea4bc71c6ffb5dddd2 Mon Sep 17 00:00:00 2001 From: Fabrice Lecomte Date: Mon, 18 Jan 2021 13:03:01 +0100 Subject: [PATCH] Refactoring of OpinionChoiceVoter --- src/main/kotlin/application/Application.kt | 14 ++----- src/main/kotlin/application/KoinModule.kt | 6 +-- src/main/kotlin/routes/OpinionChoice.kt | 16 ++++---- src/main/kotlin/voter/OpinionChoiceVoter.kt | 27 ++++-------- .../unit/voter/OpinionChoiceVoterTest.kt | 41 ++++--------------- 5 files changed, 30 insertions(+), 74 deletions(-) diff --git a/src/main/kotlin/application/Application.kt b/src/main/kotlin/application/Application.kt index 52a0e35..d126ce6 100644 --- a/src/main/kotlin/application/Application.kt +++ b/src/main/kotlin/application/Application.kt @@ -41,9 +41,7 @@ import fr.dcproject.component.workgroup.routes.members.UpdateMemberOfWorkgroup.u import fr.dcproject.event.EventNotification import fr.dcproject.event.EventSubscriber import fr.dcproject.routes.* -import fr.dcproject.security.voter.OpinionChoiceVoter -import fr.ktorVoter.AuthorizationVoter -import fr.ktorVoter.VoterException +import fr.dcproject.voter.VoterDeniedException import fr.postgresjson.migration.Migrations import io.ktor.application.* import io.ktor.auth.* @@ -89,12 +87,6 @@ fun Application.module(env: Env = PROD) { install(Locations) - install(AuthorizationVoter) { - voters = listOf( - OpinionChoiceVoter() - ) - } - HttpClient(Jetty) { engine { } @@ -176,7 +168,7 @@ fun Application.module(env: Env = PROD) { voteArticle(get(), get(), get(), get()) voteConstitution(get(), get()) opinionArticle(get(), get()) - opinionChoice(get()) + opinionChoice(get(), get()) definition() } @@ -198,7 +190,7 @@ fun Application.module(env: Env = PROD) { exception { e -> call.respond(HttpStatusCode.NotFound, e.message!!) } - exception { + exception { if (call.user == null) call.respond(HttpStatusCode.Unauthorized) else call.respond(HttpStatusCode.Forbidden) } diff --git a/src/main/kotlin/application/KoinModule.kt b/src/main/kotlin/application/KoinModule.kt index 705cbb4..1bb7bb9 100644 --- a/src/main/kotlin/application/KoinModule.kt +++ b/src/main/kotlin/application/KoinModule.kt @@ -23,10 +23,7 @@ import fr.dcproject.event.publisher.Publisher import fr.dcproject.messages.Mailer import fr.dcproject.messages.NotificationEmailSender import fr.dcproject.repository.CommentConstitutionRepository -import fr.dcproject.security.voter.ConstitutionVoter -import fr.dcproject.security.voter.FollowVoter -import fr.dcproject.security.voter.OpinionVoter -import fr.dcproject.security.voter.VoteVoter +import fr.dcproject.security.voter.* import fr.postgresjson.connexion.Connection import fr.postgresjson.connexion.Requester import fr.postgresjson.migration.Migrations @@ -131,6 +128,7 @@ val KoinModule = module { single { VoteVoter() } single { FollowVoter() } single { OpinionVoter() } + single { OpinionChoiceVoter() } // Elasticsearch Client single { diff --git a/src/main/kotlin/routes/OpinionChoice.kt b/src/main/kotlin/routes/OpinionChoice.kt index a80ce97..8fb622d 100644 --- a/src/main/kotlin/routes/OpinionChoice.kt +++ b/src/main/kotlin/routes/OpinionChoice.kt @@ -1,9 +1,9 @@ package fr.dcproject.routes +import fr.dcproject.component.auth.citizenOrNull import fr.dcproject.entity.OpinionChoice -import fr.dcproject.security.voter.OpinionChoiceVoter.Action.VIEW -import fr.ktorVoter.assertCan -import fr.ktorVoter.assertCanAll +import fr.dcproject.security.voter.OpinionChoiceVoter +import fr.dcproject.voter.assert import io.ktor.application.* import io.ktor.locations.* import io.ktor.response.* @@ -20,17 +20,17 @@ object OpinionChoicePaths { } @KtorExperimentalLocationsAPI -fun Route.opinionChoice(repo: OpinionChoiceRepository) { +fun Route.opinionChoice(repo: OpinionChoiceRepository, voter: OpinionChoiceVoter) { get { - assertCan(VIEW, it.opinionChoice) + voter.assert { canView(it.opinionChoice, citizenOrNull) } call.respond(it.opinionChoice) } get { - val opinions = repo.findOpinionsChoices(it.targets) - assertCanAll(VIEW, opinions) + val opinionChoices = repo.findOpinionsChoices(it.targets) + voter.assert { canView(opinionChoices, citizenOrNull) } - call.respond(opinions) + call.respond(opinionChoices) } } \ No newline at end of file diff --git a/src/main/kotlin/voter/OpinionChoiceVoter.kt b/src/main/kotlin/voter/OpinionChoiceVoter.kt index ac292ad..b2eedf7 100644 --- a/src/main/kotlin/voter/OpinionChoiceVoter.kt +++ b/src/main/kotlin/voter/OpinionChoiceVoter.kt @@ -1,26 +1,15 @@ package fr.dcproject.security.voter +import fr.dcproject.component.citizen.CitizenI import fr.dcproject.entity.OpinionChoice -import fr.dcproject.voter.NoSubjectDefinedException -import fr.ktorVoter.* -import io.ktor.application.* +import fr.dcproject.voter.Voter +import fr.dcproject.voter.VoterResponse -class OpinionChoiceVoter : Voter { - enum class Action : ActionI { - VIEW - } +class OpinionChoiceVoter : Voter() { + fun canView(subjects: List, citizen: CitizenI?): VoterResponse = + canAll(subjects) { canView(it, citizen) } - override fun invoke(action: Any, context: ApplicationCall, subject: Any?): VoterResponseI { - if (!((action is Action) && - (subject is OpinionChoice?))) return abstain() - - if (action == Action.VIEW) { - if (subject is OpinionChoice) { - return granted() - } - throw NoSubjectDefinedException(action) - } - - return abstain() + fun canView(subject: OpinionChoice, citizen: CitizenI?): VoterResponse { + return granted() } } diff --git a/src/test/kotlin/unit/voter/OpinionChoiceVoterTest.kt b/src/test/kotlin/unit/voter/OpinionChoiceVoterTest.kt index d6dcd20..cea2dc4 100644 --- a/src/test/kotlin/unit/voter/OpinionChoiceVoterTest.kt +++ b/src/test/kotlin/unit/voter/OpinionChoiceVoterTest.kt @@ -3,19 +3,12 @@ package unit.voter import fr.dcproject.component.article.ArticleForView import fr.dcproject.component.auth.User import fr.dcproject.component.auth.UserI -import fr.dcproject.component.auth.user import fr.dcproject.component.citizen.CitizenBasic import fr.dcproject.component.citizen.CitizenCart import fr.dcproject.component.citizen.CitizenI import fr.dcproject.entity.OpinionChoice import fr.dcproject.security.voter.OpinionChoiceVoter -import fr.ktorVoter.ActionI -import fr.ktorVoter.Vote -import fr.ktorVoter.can -import fr.ktorVoter.canAll -import io.ktor.application.* -import io.mockk.every -import io.mockk.mockk +import fr.dcproject.voter.Vote.GRANTED import io.mockk.mockkStatic import org.amshove.kluent.`should be` import org.joda.time.DateTime @@ -68,32 +61,16 @@ internal class OpinionChoiceVoterTest { } @Test - fun `support opinion choice`(): Unit = OpinionChoiceVoter().run { - val p = object : ActionI {} - mockk { - every { user } returns tesla.user - }.let { - this(OpinionChoiceVoter.Action.VIEW, it, choice1).vote `should be` Vote.GRANTED - this(OpinionChoiceVoter.Action.VIEW, it, article1).vote `should be` Vote.ABSTAIN - this(p, it, choice1).vote `should be` Vote.ABSTAIN - } + fun `can be view the opinion choice`() { + OpinionChoiceVoter() + .canView(choice1, tesla) + .vote `should be` GRANTED } @Test - fun `can be view the opinion choice`(): Unit = listOf(OpinionChoiceVoter()).run { - mockk { - every { user } returns tesla.user - }.let { - can(OpinionChoiceVoter.Action.VIEW, it, choice1) `should be` true - } - } - - @Test - fun `can be view the opinion choice list`(): Unit = listOf(OpinionChoiceVoter()).run { - mockk { - every { user } returns tesla.user - }.let { - canAll(OpinionChoiceVoter.Action.VIEW, it, listOf(choice1)) `should be` true - } + fun `can be view the opinion choice list`() { + OpinionChoiceVoter() + .canView(listOf(choice1), tesla) + .vote `should be` GRANTED } } \ No newline at end of file