diff --git a/src/main/kotlin/fr/dcproject/component/article/Article.kt b/src/main/kotlin/fr/dcproject/component/article/Article.kt index a041078..61c201b 100644 --- a/src/main/kotlin/fr/dcproject/component/article/Article.kt +++ b/src/main/kotlin/fr/dcproject/component/article/Article.kt @@ -19,7 +19,6 @@ import fr.dcproject.component.vote.entity.VotableImp import fr.dcproject.component.workgroup.WorkgroupCart import fr.dcproject.component.workgroup.WorkgroupCartI import fr.dcproject.component.workgroup.WorkgroupRef -import fr.dcproject.component.workgroup.WorkgroupSimple import org.joda.time.DateTime import java.util.UUID @@ -33,7 +32,7 @@ data class ArticleForView( override val createdBy: CitizenRef, override val versionNumber: Int = 0, override val versionId: UUID = UUID.randomUUID(), - val workgroup: WorkgroupSimple? = null, + val workgroup: WorkgroupCart? = null, override val opinions: Opinions = emptyMap(), override val draft: Boolean = false, override val deletedAt: DateTime? = null diff --git a/src/main/kotlin/fr/dcproject/component/article/routes/GetOneArticle.kt b/src/main/kotlin/fr/dcproject/component/article/routes/GetOneArticle.kt index 3889038..90ef2c4 100644 --- a/src/main/kotlin/fr/dcproject/component/article/routes/GetOneArticle.kt +++ b/src/main/kotlin/fr/dcproject/component/article/routes/GetOneArticle.kt @@ -47,7 +47,9 @@ object GetOneArticle { val draft = article.draft val lastVersion = article.lastVersion val createdBy = article.createdBy - val workgroup = article.workgroup // TODO change to workgroup DTO + val workgroup = article.workgroup?.let { Workgroup(article.workgroup.id, article.workgroup.name) } + + class Workgroup(val id: UUID, val name: String) } fun Route.getOneArticle(viewManager: ArticleViewManager, ac: ArticleAccessControl, repo: ArticleRepository) { diff --git a/src/main/kotlin/fr/dcproject/component/auth/User.kt b/src/main/kotlin/fr/dcproject/component/auth/User.kt index 96fa66e..22ef6c8 100644 --- a/src/main/kotlin/fr/dcproject/component/auth/User.kt +++ b/src/main/kotlin/fr/dcproject/component/auth/User.kt @@ -20,10 +20,11 @@ class UserForCreate( open class User( id: UUID = UUID.randomUUID(), - var username: String, + override var username: String, var blockedAt: DateTime? = null, var roles: List = emptyList() ) : UserRef(id), + UserWithUsername, CreatedAt by CreatedAt.Imp(), UpdatedAt by UpdatedAt.Imp() @@ -32,12 +33,11 @@ class UserCreator( override val username: String, ) : UserRef(id), UserWithUsername -interface UserWithUsername { +interface UserWithUsername : UserI { val username: String } -interface UserWithPasswordI { - val id: UUID +interface UserWithPasswordI : UserI { val password: String } diff --git a/src/main/kotlin/fr/dcproject/component/citizen/Citizen.kt b/src/main/kotlin/fr/dcproject/component/citizen/Citizen.kt index f2e71ac..9be68e4 100644 --- a/src/main/kotlin/fr/dcproject/component/citizen/Citizen.kt +++ b/src/main/kotlin/fr/dcproject/component/citizen/Citizen.kt @@ -9,8 +9,9 @@ import fr.dcproject.component.auth.UserCreator import fr.dcproject.component.auth.UserForCreate import fr.dcproject.component.auth.UserI import fr.dcproject.component.auth.UserRef +import fr.dcproject.component.auth.UserWithUsername import fr.dcproject.component.citizen.CitizenI.Name -import fr.dcproject.component.workgroup.WorkgroupSimple +import fr.dcproject.component.workgroup.WorkgroupRef import fr.postgresjson.entity.Serializable import org.joda.time.DateTime import java.util.UUID @@ -38,6 +39,7 @@ class Citizen( deletedAt: DateTime? = null ) : CitizenFull, CitizenBasicI, + CitizenCreatorI, CitizenWithUserI, CitizenRef(id), CitizenCartI, @@ -47,7 +49,7 @@ class Citizen( class WorkgroupAndRoles( val roles: List, - val workgroup: WorkgroupSimple + val workgroup: WorkgroupRef ) } @@ -69,7 +71,7 @@ interface CitizenCreatorI : CitizenWithUserI, CitizenWithEmail, CitizenCartI, De override val email: String val voteAnonymous: Boolean val followAnonymous: Boolean - override val user: UserCreator + override val user: UserWithUsername override val deletedAt: DateTime? } diff --git a/src/main/kotlin/fr/dcproject/component/workgroup/Workgroup.kt b/src/main/kotlin/fr/dcproject/component/workgroup/WorkgroupForView.kt similarity index 76% rename from src/main/kotlin/fr/dcproject/component/workgroup/Workgroup.kt rename to src/main/kotlin/fr/dcproject/component/workgroup/WorkgroupForView.kt index 44578df..641b678 100644 --- a/src/main/kotlin/fr/dcproject/component/workgroup/Workgroup.kt +++ b/src/main/kotlin/fr/dcproject/component/workgroup/WorkgroupForView.kt @@ -7,47 +7,47 @@ import fr.dcproject.common.entity.Entity import fr.dcproject.common.entity.EntityI import fr.dcproject.common.entity.UpdatedAt import fr.dcproject.component.auth.UserI -import fr.dcproject.component.citizen.CitizenBasicI +import fr.dcproject.component.citizen.CitizenCreatorI import fr.dcproject.component.citizen.CitizenI import fr.dcproject.component.citizen.CitizenWithUserI import fr.dcproject.component.workgroup.WorkgroupWithMembersI.Member import fr.dcproject.component.workgroup.WorkgroupWithMembersI.Member.Role -import fr.postgresjson.entity.Serializable +import org.joda.time.DateTime import java.util.UUID -@Deprecated("") -data class Workgroup ( +data class WorkgroupForView( override val id: UUID = UUID.randomUUID(), - override var name: String, - override var description: String, - override var logo: String? = null, + val name: String, + val description: String, + val logo: String? = null, override var anonymous: Boolean = true, override val createdBy: C, override var members: List> = emptyList() ) : WorkgroupWithAuthI, - WorkgroupSimple( - id, - name, - description, - logo, - anonymous, - createdBy - ), + WorkgroupRef(id), + CreatedBy by CreatedBy.Imp(createdBy), CreatedAt by CreatedAt.Imp(), - UpdatedAt by UpdatedAt.Imp() - -@Deprecated("") -open class WorkgroupSimple( - id: UUID? = null, - open var name: String, - open var description: String, - open var logo: String? = null, - open var anonymous: Boolean = true, - createdBy: Z -) : WorkgroupRef(id), - CreatedBy by CreatedBy.Imp(createdBy), + UpdatedAt by UpdatedAt.Imp(), DeletedAt by DeletedAt.Imp() +data class WorkgroupForUpdate( + override val id: UUID, + override val name: String, + override val description: String, + override val createdBy: C, + override val logo: String? = null, + override val anonymous: Boolean = true, + override val members: List> = listOf(), + override val deletedAt: DateTime? = null, +) : WorkgroupRef(id), + WorkgroupForUpdateI, + CreatedBy by CreatedBy.Imp(createdBy) + +interface WorkgroupForUpdateI : WorkgroupWithAuthI, WorkgroupCartI, CreatedBy { + val description: String + val logo: String? +} + class WorkgroupCart( override val id: UUID, override val name: String @@ -56,6 +56,7 @@ class WorkgroupCart( interface WorkgroupCartI : EntityI { val name: String } + open class WorkgroupRef( id: UUID? = null ) : Entity(id ?: UUID.randomUUID()), WorkgroupI @@ -74,9 +75,9 @@ interface WorkgroupWithAuthI : WorkgroupWithMembersI, C } interface WorkgroupWithMembersI : WorkgroupI { - var members: List> + val members: List> - class Member ( + class Member( val citizen: C, val roles: List = emptyList() ) : fr.postgresjson.entity.EntityI { diff --git a/src/main/kotlin/fr/dcproject/component/workgroup/WorkgroupRepository.kt b/src/main/kotlin/fr/dcproject/component/workgroup/WorkgroupRepository.kt index 051e927..d3e9236 100644 --- a/src/main/kotlin/fr/dcproject/component/workgroup/WorkgroupRepository.kt +++ b/src/main/kotlin/fr/dcproject/component/workgroup/WorkgroupRepository.kt @@ -1,7 +1,9 @@ package fr.dcproject.component.workgroup import fr.dcproject.component.citizen.CitizenBasic +import fr.dcproject.component.citizen.CitizenCreator import fr.dcproject.component.citizen.CitizenI +import fr.dcproject.component.citizen.CitizenRef import fr.dcproject.component.workgroup.WorkgroupWithMembersI.Member import fr.postgresjson.connexion.Paginated import fr.postgresjson.connexion.Requester @@ -11,10 +13,10 @@ import fr.postgresjson.repository.RepositoryI.Direction import fr.postgresjson.serializer.serialize import net.pearx.kasechange.toSnakeCase import java.util.UUID -import fr.dcproject.component.workgroup.Workgroup as WorkgroupEntity +import fr.dcproject.component.workgroup.WorkgroupForView as WorkgroupEntity class WorkgroupRepository(override var requester: Requester) : RepositoryI { - fun findById(id: UUID): WorkgroupEntity? { + fun findById(id: UUID): WorkgroupEntity? { val function = requester.getFunction("find_workgroup_by_id") return function.selectOne("id" to id) } @@ -26,7 +28,7 @@ class WorkgroupRepository(override var requester: Requester) : RepositoryI { direction: Direction? = null, search: String? = null, filter: Filter = Filter() - ): Paginated> { + ): Paginated> { return requester .getFunction("find_workgroups") .select( @@ -39,7 +41,7 @@ class WorkgroupRepository(override var requester: Requester) : RepositoryI { ) } - fun > upsert(workgroup: W): WorkgroupEntity = requester + fun > upsert(workgroup: W): WorkgroupEntity = requester .getFunction("upsert_workgroup") .selectOne("resource" to workgroup) ?: error("query 'upsert_workgroup' return null") @@ -47,10 +49,10 @@ class WorkgroupRepository(override var requester: Requester) : RepositoryI { .getFunction("delete_workgroup") .perform("id" to workgroup.id) - fun addMember(workgroup: WorkgroupI, member: Member): Member? = + fun addMember(workgroup: WorkgroupI, member: Member): Member? = addMember(workgroup, member.citizen, member.roles) - fun addMember(workgroup: WorkgroupI, citizen: CitizenI, roles: List): Member? = requester + fun addMember(workgroup: WorkgroupI, citizen: CitizenI, roles: List): Member? = requester .getFunction("add_workgroup_member") .selectOne( "id" to workgroup.id, @@ -81,14 +83,6 @@ class WorkgroupRepository(override var requester: Requester) : RepositoryI { "members" to members ) - fun , Z : CitizenI> updateMembers(workgroup: W): W { - updateMembers(workgroup, workgroup.members).let { - workgroup.members = it as List> - } - - return workgroup - } - class Filter( val createdById: String? = null, val members: List? = null diff --git a/src/main/kotlin/fr/dcproject/component/workgroup/routes/CreateWorkgroup.kt b/src/main/kotlin/fr/dcproject/component/workgroup/routes/CreateWorkgroup.kt index 49ce074..fe5465e 100644 --- a/src/main/kotlin/fr/dcproject/component/workgroup/routes/CreateWorkgroup.kt +++ b/src/main/kotlin/fr/dcproject/component/workgroup/routes/CreateWorkgroup.kt @@ -5,8 +5,8 @@ import fr.dcproject.common.utils.receiveOrBadRequest import fr.dcproject.component.auth.citizen import fr.dcproject.component.auth.citizenOrNull import fr.dcproject.component.workgroup.WorkgroupAccessControl +import fr.dcproject.component.workgroup.WorkgroupForUpdate import fr.dcproject.component.workgroup.WorkgroupRepository -import fr.dcproject.component.workgroup.WorkgroupSimple import fr.dcproject.component.workgroup.routes.CreateWorkgroup.PostWorkgroupRequest.Input import io.ktor.application.call import io.ktor.http.HttpStatusCode @@ -33,13 +33,13 @@ object CreateWorkgroup { fun Route.createWorkgroup(repo: WorkgroupRepository, ac: WorkgroupAccessControl) { post { call.receiveOrBadRequest().run { - WorkgroupSimple( + WorkgroupForUpdate( id ?: UUID.randomUUID(), name, description, + citizen, logo, anonymous ?: true, - citizen ) }.let { workgroup -> ac.assert { canCreate(workgroup, citizenOrNull) } diff --git a/src/main/kotlin/fr/dcproject/component/workgroup/routes/EditWorkgroup.kt b/src/main/kotlin/fr/dcproject/component/workgroup/routes/EditWorkgroup.kt index d604fc2..67901b0 100644 --- a/src/main/kotlin/fr/dcproject/component/workgroup/routes/EditWorkgroup.kt +++ b/src/main/kotlin/fr/dcproject/component/workgroup/routes/EditWorkgroup.kt @@ -4,6 +4,7 @@ import fr.dcproject.common.security.assert import fr.dcproject.common.utils.receiveOrBadRequest import fr.dcproject.component.auth.citizenOrNull import fr.dcproject.component.workgroup.WorkgroupAccessControl +import fr.dcproject.component.workgroup.WorkgroupForUpdate import fr.dcproject.component.workgroup.WorkgroupRepository import fr.dcproject.component.workgroup.routes.EditWorkgroup.PutWorkgroupRequest.Input import io.ktor.application.call @@ -32,11 +33,15 @@ object EditWorkgroup { put { repo.findById(it.workgroupId)?.let { old -> call.receiveOrBadRequest().run { - old.copy( + WorkgroupForUpdate( + id = old.id, name = name ?: old.name, description = description ?: old.description, + createdBy = old.createdBy, logo = logo ?: old.logo, - anonymous = anonymous ?: old.anonymous + anonymous = anonymous ?: old.anonymous, + deletedAt = old.deletedAt, + members = old.members, ).let { workgroup -> ac.assert { canUpdate(workgroup, citizenOrNull) } repo.upsert(workgroup) diff --git a/src/test/kotlin/integration/steps/given/Workgroup.kt b/src/test/kotlin/integration/steps/given/Workgroup.kt index 77c4f56..cfc3d08 100644 --- a/src/test/kotlin/integration/steps/given/Workgroup.kt +++ b/src/test/kotlin/integration/steps/given/Workgroup.kt @@ -3,11 +3,12 @@ package integration.steps.given import fr.dcproject.common.utils.toUUID import fr.dcproject.component.auth.UserForCreate import fr.dcproject.component.citizen.Citizen -import fr.dcproject.component.citizen.CitizenBasic +import fr.dcproject.component.citizen.CitizenCreator import fr.dcproject.component.citizen.CitizenForCreate import fr.dcproject.component.citizen.CitizenI import fr.dcproject.component.citizen.CitizenRepository -import fr.dcproject.component.workgroup.Workgroup +import fr.dcproject.component.workgroup.WorkgroupForUpdate +import fr.dcproject.component.workgroup.WorkgroupForView import fr.dcproject.component.workgroup.WorkgroupRepository import fr.dcproject.component.workgroup.WorkgroupWithMembersI.Member import fr.dcproject.component.workgroup.WorkgroupWithMembersI.Member.Role.MASTER @@ -22,18 +23,18 @@ fun TestApplicationEngine.`Given I have workgroup`( description: String? = null, anonymous: Boolean? = null, createdBy: CitizenI.Name? = null, - callback: Workgroup.() -> Unit = {}, + callback: WorkgroupForView.() -> Unit = {}, ) { - val workgroup: Workgroup = createWorkgroup(id?.toUUID(), name, description, anonymous, createdBy) + val workgroup: WorkgroupForView = createWorkgroup(id?.toUUID(), name, description, anonymous, createdBy) callback(workgroup) } -fun Workgroup.`With members`( +fun WorkgroupForView.`With members`( vararg member: CitizenI.Name ) { addMemberToWorkgroup(this, *member) } -fun addMemberToWorkgroup(workgroup: Workgroup, vararg membersNames: CitizenI.Name) { +fun addMemberToWorkgroup(workgroup: WorkgroupForView, vararg membersNames: CitizenI.Name) { val citizenRepository: CitizenRepository by lazy { GlobalContext.get().koin.get() } val workgroupRepository: WorkgroupRepository by lazy { GlobalContext.get().koin.get() } @@ -53,7 +54,7 @@ private fun createWorkgroup( description: String? = null, anonymous: Boolean? = null, createdBy: CitizenI.Name? = null, -): Workgroup { +): WorkgroupForView { val citizenRepository: CitizenRepository by lazy { GlobalContext.get().koin.get() } val workgroupRepository: WorkgroupRepository by lazy { GlobalContext.get().koin.get() } @@ -75,12 +76,12 @@ private fun createWorkgroup( } } - val workgroup = Workgroup( + val workgroup = WorkgroupForUpdate( id = id ?: UUID.randomUUID(), name = name ?: "Les Incoruptible", description = description ?: "La vie est notre jeux", createdBy = creator, - anonymous = (anonymous ?: false) == true, + anonymous = anonymous ?: false, members = listOf(Member(creator, listOf(MASTER))) ) diff --git a/src/test/kotlin/unit/security/Workgroup Access Control.kt b/src/test/kotlin/unit/security/Workgroup Access Control.kt index e6f2c03..f126964 100644 --- a/src/test/kotlin/unit/security/Workgroup Access Control.kt +++ b/src/test/kotlin/unit/security/Workgroup Access Control.kt @@ -3,9 +3,11 @@ package unit.security import fr.dcproject.common.security.AccessDecision.DENIED import fr.dcproject.common.security.AccessDecision.GRANTED import fr.dcproject.component.auth.User +import fr.dcproject.component.auth.UserCreator import fr.dcproject.component.auth.UserI import fr.dcproject.component.citizen.CitizenBasic import fr.dcproject.component.citizen.CitizenCart +import fr.dcproject.component.citizen.CitizenCreator import fr.dcproject.component.citizen.CitizenI import fr.dcproject.component.workgroup.WorkgroupAccessControl import fr.dcproject.component.workgroup.WorkgroupWithMembersI @@ -18,18 +20,16 @@ import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.parallel.Execution import org.junit.jupiter.api.parallel.ExecutionMode.CONCURRENT import java.util.UUID -import fr.dcproject.component.workgroup.Workgroup as WorkgroupEntity +import fr.dcproject.component.workgroup.WorkgroupForView as WorkgroupEntity @TestInstance(TestInstance.Lifecycle.PER_CLASS) @Execution(CONCURRENT) @Tags(Tag("security"), Tag("unit")) internal class `Workgroup Access Control` { - private val tesla = CitizenBasic( - user = User( + private val tesla = CitizenCreator( + user = UserCreator( username = "nicolas-tesla", - roles = listOf(UserI.Roles.ROLE_USER) ), - birthday = DateTime.now(), email = "tesla@best.com", name = CitizenI.Name("Nicolas", "Tesla"), followAnonymous = false