diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 0dfa848..6f95118 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -18,6 +18,8 @@
+
+
@@ -25,6 +27,7 @@
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
index ad1f18e..1746d8a 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -10,4 +10,7 @@
+
+
+
\ No newline at end of file
diff --git a/src/main/kotlin/entity/Article.kt b/src/main/kotlin/entity/Article.kt
index 335ec1a..b468868 100644
--- a/src/main/kotlin/entity/Article.kt
+++ b/src/main/kotlin/entity/Article.kt
@@ -36,9 +36,11 @@ class ArticleForUpdate(
tags: List = emptyList(),
val draft: Boolean = false,
val createdBy: CitizenRef,
- val workgroup: WorkgroupRef? = null
-) : ArticleRefVersioning(id) {
+ val workgroup: WorkgroupRef? = null,
+ versionId: UUID?
+) : ArticleRefVersioning(id, versionId = versionId ?: UUID.randomUUID()) {
val tags: List = tags.distinct()
+ val isNew = versionId == null
}
open class ArticleSimple(
diff --git a/src/main/kotlin/routes/Article.kt b/src/main/kotlin/routes/Article.kt
index 4a26a0d..8dc5a3b 100644
--- a/src/main/kotlin/routes/Article.kt
+++ b/src/main/kotlin/routes/Article.kt
@@ -11,6 +11,7 @@ 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
@@ -81,18 +82,17 @@ object ArticlesPaths {
suspend fun getNewArticle(call: ApplicationCall): ArticleForUpdate = call.receive().run {
ArticleForUpdate(
- id ?: UUID.randomUUID(),
- title,
- anonymous,
- content,
- description,
- tags,
- draft,
+ id = id ?: UUID.randomUUID(),
+ title = title,
+ anonymous = anonymous,
+ content = content,
+ description = description,
+ tags = tags,
+ draft = draft,
createdBy = call.citizen,
- workgroup = if (workgroup != null) workgroupRepository.findById(workgroup.id) as WorkgroupSimple else null
- ).also {
- it.versionId = versionId ?: UUID.randomUUID()
- }
+ workgroup = if (workgroup != null) workgroupRepository.findById(workgroup.id) as WorkgroupSimple else null,
+ versionId = versionId
+ )
}
}
}
@@ -134,7 +134,11 @@ fun Route.article(repo: ArticleRepository, viewManager: ArticleViewManager) {
post {
it.getNewArticle(call).also { article ->
- assertCan(CREATE, article)
+ if(article.isNew) {
+ assertCan(CREATE, article)
+ } else {
+ assertCan(UPDATE, article)
+ }
val newArticle = repo.upsert(article) ?: error("Article not updated")
call.respond(article)
raiseEvent(ArticleUpdate.event, ArticleUpdate(newArticle))
diff --git a/src/main/kotlin/voter/ArticleVoter.kt b/src/main/kotlin/voter/ArticleVoter.kt
index eae16bd..db65314 100644
--- a/src/main/kotlin/voter/ArticleVoter.kt
+++ b/src/main/kotlin/voter/ArticleVoter.kt
@@ -1,18 +1,26 @@
package fr.dcproject.security.voter
+import fr.dcproject.citizenOrNull
import fr.dcproject.entity.ArticleAuthI
+import fr.dcproject.entity.ArticleForUpdate
import fr.dcproject.entity.ArticleI
+import fr.dcproject.entity.Citizen as CitizenEntity
+import fr.dcproject.entity.CitizenI
import fr.dcproject.entity.UserI
+import fr.dcproject.repository.Article as ArticleRepo
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 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 {
+class ArticleVoter : Voter, KoinComponent {
+ private val articleRepo: ArticleRepo by inject()
enum class Action : ActionI {
CREATE,
UPDATE,
@@ -30,7 +38,7 @@ class ArticleVoter : Voter {
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, user)
+ if (action == Action.UPDATE) return update(subject, call.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
@@ -58,11 +66,16 @@ class ArticleVoter : Voter {
return Vote.DENIED
}
- private fun update(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
+ 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
}
}
return Vote.DENIED
diff --git a/src/test/kotlin/feature/ArticleSteps.kt b/src/test/kotlin/feature/ArticleSteps.kt
index 744c4bf..5a2c367 100644
--- a/src/test/kotlin/feature/ArticleSteps.kt
+++ b/src/test/kotlin/feature/ArticleSteps.kt
@@ -73,7 +73,8 @@ class ArticleSteps : En, KoinTest {
content = "bla bla bla",
description = "A super article",
createdBy = createdBy,
- workgroup = workgroup
+ workgroup = workgroup,
+ versionId = UUID.randomUUID()
)
get().upsert(article)
}