#68 Clean workgroup Entity

This commit is contained in:
2021-03-02 22:27:51 +01:00
parent bc772f168f
commit 4c00095118
10 changed files with 76 additions and 72 deletions

View File

@@ -19,7 +19,6 @@ import fr.dcproject.component.vote.entity.VotableImp
import fr.dcproject.component.workgroup.WorkgroupCart import fr.dcproject.component.workgroup.WorkgroupCart
import fr.dcproject.component.workgroup.WorkgroupCartI import fr.dcproject.component.workgroup.WorkgroupCartI
import fr.dcproject.component.workgroup.WorkgroupRef import fr.dcproject.component.workgroup.WorkgroupRef
import fr.dcproject.component.workgroup.WorkgroupSimple
import org.joda.time.DateTime import org.joda.time.DateTime
import java.util.UUID import java.util.UUID
@@ -33,7 +32,7 @@ data class ArticleForView(
override val createdBy: CitizenRef, override val createdBy: CitizenRef,
override val versionNumber: Int = 0, override val versionNumber: Int = 0,
override val versionId: UUID = UUID.randomUUID(), override val versionId: UUID = UUID.randomUUID(),
val workgroup: WorkgroupSimple<CitizenRef>? = null, val workgroup: WorkgroupCart? = null,
override val opinions: Opinions = emptyMap(), override val opinions: Opinions = emptyMap(),
override val draft: Boolean = false, override val draft: Boolean = false,
override val deletedAt: DateTime? = null override val deletedAt: DateTime? = null

View File

@@ -47,7 +47,9 @@ object GetOneArticle {
val draft = article.draft val draft = article.draft
val lastVersion = article.lastVersion val lastVersion = article.lastVersion
val createdBy = article.createdBy 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<ArticleForView>, ac: ArticleAccessControl, repo: ArticleRepository) { fun Route.getOneArticle(viewManager: ArticleViewManager<ArticleForView>, ac: ArticleAccessControl, repo: ArticleRepository) {

View File

@@ -20,10 +20,11 @@ class UserForCreate(
open class User( open class User(
id: UUID = UUID.randomUUID(), id: UUID = UUID.randomUUID(),
var username: String, override var username: String,
var blockedAt: DateTime? = null, var blockedAt: DateTime? = null,
var roles: List<Roles> = emptyList() var roles: List<Roles> = emptyList()
) : UserRef(id), ) : UserRef(id),
UserWithUsername,
CreatedAt by CreatedAt.Imp(), CreatedAt by CreatedAt.Imp(),
UpdatedAt by UpdatedAt.Imp() UpdatedAt by UpdatedAt.Imp()
@@ -32,12 +33,11 @@ class UserCreator(
override val username: String, override val username: String,
) : UserRef(id), UserWithUsername ) : UserRef(id), UserWithUsername
interface UserWithUsername { interface UserWithUsername : UserI {
val username: String val username: String
} }
interface UserWithPasswordI { interface UserWithPasswordI : UserI {
val id: UUID
val password: String val password: String
} }

View File

@@ -9,8 +9,9 @@ import fr.dcproject.component.auth.UserCreator
import fr.dcproject.component.auth.UserForCreate import fr.dcproject.component.auth.UserForCreate
import fr.dcproject.component.auth.UserI import fr.dcproject.component.auth.UserI
import fr.dcproject.component.auth.UserRef import fr.dcproject.component.auth.UserRef
import fr.dcproject.component.auth.UserWithUsername
import fr.dcproject.component.citizen.CitizenI.Name 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 fr.postgresjson.entity.Serializable
import org.joda.time.DateTime import org.joda.time.DateTime
import java.util.UUID import java.util.UUID
@@ -38,6 +39,7 @@ class Citizen(
deletedAt: DateTime? = null deletedAt: DateTime? = null
) : CitizenFull, ) : CitizenFull,
CitizenBasicI, CitizenBasicI,
CitizenCreatorI,
CitizenWithUserI, CitizenWithUserI,
CitizenRef(id), CitizenRef(id),
CitizenCartI, CitizenCartI,
@@ -47,7 +49,7 @@ class Citizen(
class WorkgroupAndRoles( class WorkgroupAndRoles(
val roles: List<String>, val roles: List<String>,
val workgroup: WorkgroupSimple<CitizenRef> val workgroup: WorkgroupRef
) )
} }
@@ -69,7 +71,7 @@ interface CitizenCreatorI : CitizenWithUserI, CitizenWithEmail, CitizenCartI, De
override val email: String override val email: String
val voteAnonymous: Boolean val voteAnonymous: Boolean
val followAnonymous: Boolean val followAnonymous: Boolean
override val user: UserCreator override val user: UserWithUsername
override val deletedAt: DateTime? override val deletedAt: DateTime?
} }

View File

@@ -7,47 +7,47 @@ import fr.dcproject.common.entity.Entity
import fr.dcproject.common.entity.EntityI import fr.dcproject.common.entity.EntityI
import fr.dcproject.common.entity.UpdatedAt import fr.dcproject.common.entity.UpdatedAt
import fr.dcproject.component.auth.UserI 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.CitizenI
import fr.dcproject.component.citizen.CitizenWithUserI import fr.dcproject.component.citizen.CitizenWithUserI
import fr.dcproject.component.workgroup.WorkgroupWithMembersI.Member import fr.dcproject.component.workgroup.WorkgroupWithMembersI.Member
import fr.dcproject.component.workgroup.WorkgroupWithMembersI.Member.Role import fr.dcproject.component.workgroup.WorkgroupWithMembersI.Member.Role
import fr.postgresjson.entity.Serializable import org.joda.time.DateTime
import java.util.UUID import java.util.UUID
@Deprecated("") data class WorkgroupForView<C : CitizenCreatorI>(
data class Workgroup <C : CitizenBasicI>(
override val id: UUID = UUID.randomUUID(), override val id: UUID = UUID.randomUUID(),
override var name: String, val name: String,
override var description: String, val description: String,
override var logo: String? = null, val logo: String? = null,
override var anonymous: Boolean = true, override var anonymous: Boolean = true,
override val createdBy: C, override val createdBy: C,
override var members: List<Member<C>> = emptyList() override var members: List<Member<C>> = emptyList()
) : WorkgroupWithAuthI<C>, ) : WorkgroupWithAuthI<C>,
WorkgroupSimple<C>( WorkgroupRef(id),
id, CreatedBy<C> by CreatedBy.Imp(createdBy),
name,
description,
logo,
anonymous,
createdBy
),
CreatedAt by CreatedAt.Imp(), CreatedAt by CreatedAt.Imp(),
UpdatedAt by UpdatedAt.Imp() UpdatedAt by UpdatedAt.Imp(),
@Deprecated("")
open class WorkgroupSimple<Z : CitizenI>(
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<Z> by CreatedBy.Imp(createdBy),
DeletedAt by DeletedAt.Imp() DeletedAt by DeletedAt.Imp()
data class WorkgroupForUpdate<C : CitizenWithUserI>(
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<Member<C>> = listOf(),
override val deletedAt: DateTime? = null,
) : WorkgroupRef(id),
WorkgroupForUpdateI<C>,
CreatedBy<C> by CreatedBy.Imp(createdBy)
interface WorkgroupForUpdateI<C : CitizenWithUserI> : WorkgroupWithAuthI<C>, WorkgroupCartI, CreatedBy<C> {
val description: String
val logo: String?
}
class WorkgroupCart( class WorkgroupCart(
override val id: UUID, override val id: UUID,
override val name: String override val name: String
@@ -56,6 +56,7 @@ class WorkgroupCart(
interface WorkgroupCartI : EntityI { interface WorkgroupCartI : EntityI {
val name: String val name: String
} }
open class WorkgroupRef( open class WorkgroupRef(
id: UUID? = null id: UUID? = null
) : Entity(id ?: UUID.randomUUID()), WorkgroupI ) : Entity(id ?: UUID.randomUUID()), WorkgroupI
@@ -74,9 +75,9 @@ interface WorkgroupWithAuthI<Z : CitizenWithUserI> : WorkgroupWithMembersI<Z>, C
} }
interface WorkgroupWithMembersI<Z : CitizenI> : WorkgroupI { interface WorkgroupWithMembersI<Z : CitizenI> : WorkgroupI {
var members: List<Member<Z>> val members: List<Member<Z>>
class Member<C : CitizenI> ( class Member<C : CitizenI>(
val citizen: C, val citizen: C,
val roles: List<Role> = emptyList() val roles: List<Role> = emptyList()
) : fr.postgresjson.entity.EntityI { ) : fr.postgresjson.entity.EntityI {

View File

@@ -1,7 +1,9 @@
package fr.dcproject.component.workgroup package fr.dcproject.component.workgroup
import fr.dcproject.component.citizen.CitizenBasic import fr.dcproject.component.citizen.CitizenBasic
import fr.dcproject.component.citizen.CitizenCreator
import fr.dcproject.component.citizen.CitizenI import fr.dcproject.component.citizen.CitizenI
import fr.dcproject.component.citizen.CitizenRef
import fr.dcproject.component.workgroup.WorkgroupWithMembersI.Member import fr.dcproject.component.workgroup.WorkgroupWithMembersI.Member
import fr.postgresjson.connexion.Paginated import fr.postgresjson.connexion.Paginated
import fr.postgresjson.connexion.Requester import fr.postgresjson.connexion.Requester
@@ -11,10 +13,10 @@ import fr.postgresjson.repository.RepositoryI.Direction
import fr.postgresjson.serializer.serialize import fr.postgresjson.serializer.serialize
import net.pearx.kasechange.toSnakeCase import net.pearx.kasechange.toSnakeCase
import java.util.UUID 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 { class WorkgroupRepository(override var requester: Requester) : RepositoryI {
fun findById(id: UUID): WorkgroupEntity<CitizenBasic>? { fun findById(id: UUID): WorkgroupEntity<CitizenCreator>? {
val function = requester.getFunction("find_workgroup_by_id") val function = requester.getFunction("find_workgroup_by_id")
return function.selectOne("id" to id) return function.selectOne("id" to id)
} }
@@ -26,7 +28,7 @@ class WorkgroupRepository(override var requester: Requester) : RepositoryI {
direction: Direction? = null, direction: Direction? = null,
search: String? = null, search: String? = null,
filter: Filter = Filter() filter: Filter = Filter()
): Paginated<WorkgroupEntity<CitizenBasic>> { ): Paginated<WorkgroupEntity<CitizenCreator>> {
return requester return requester
.getFunction("find_workgroups") .getFunction("find_workgroups")
.select( .select(
@@ -39,7 +41,7 @@ class WorkgroupRepository(override var requester: Requester) : RepositoryI {
) )
} }
fun <C : CitizenI, W : WorkgroupSimple<C>> upsert(workgroup: W): WorkgroupEntity<CitizenBasic> = requester fun <C : CitizenI, W : WorkgroupForUpdateI<C>> upsert(workgroup: W): WorkgroupEntity<CitizenCreator> = requester
.getFunction("upsert_workgroup") .getFunction("upsert_workgroup")
.selectOne("resource" to workgroup) ?: error("query 'upsert_workgroup' return null") .selectOne("resource" to workgroup) ?: error("query 'upsert_workgroup' return null")
@@ -47,10 +49,10 @@ class WorkgroupRepository(override var requester: Requester) : RepositoryI {
.getFunction("delete_workgroup") .getFunction("delete_workgroup")
.perform("id" to workgroup.id) .perform("id" to workgroup.id)
fun addMember(workgroup: WorkgroupI, member: Member<CitizenI>): Member<CitizenBasic>? = fun addMember(workgroup: WorkgroupI, member: Member<CitizenI>): Member<CitizenRef>? =
addMember(workgroup, member.citizen, member.roles) addMember(workgroup, member.citizen, member.roles)
fun addMember(workgroup: WorkgroupI, citizen: CitizenI, roles: List<Member.Role>): Member<CitizenBasic>? = requester fun addMember(workgroup: WorkgroupI, citizen: CitizenI, roles: List<Member.Role>): Member<CitizenRef>? = requester
.getFunction("add_workgroup_member") .getFunction("add_workgroup_member")
.selectOne( .selectOne(
"id" to workgroup.id, "id" to workgroup.id,
@@ -81,14 +83,6 @@ class WorkgroupRepository(override var requester: Requester) : RepositoryI {
"members" to members "members" to members
) )
fun <W : WorkgroupWithMembersI<Z>, Z : CitizenI> updateMembers(workgroup: W): W {
updateMembers(workgroup, workgroup.members).let {
workgroup.members = it as List<Member<Z>>
}
return workgroup
}
class Filter( class Filter(
val createdById: String? = null, val createdById: String? = null,
val members: List<UUID>? = null val members: List<UUID>? = null

View File

@@ -5,8 +5,8 @@ import fr.dcproject.common.utils.receiveOrBadRequest
import fr.dcproject.component.auth.citizen import fr.dcproject.component.auth.citizen
import fr.dcproject.component.auth.citizenOrNull import fr.dcproject.component.auth.citizenOrNull
import fr.dcproject.component.workgroup.WorkgroupAccessControl import fr.dcproject.component.workgroup.WorkgroupAccessControl
import fr.dcproject.component.workgroup.WorkgroupForUpdate
import fr.dcproject.component.workgroup.WorkgroupRepository import fr.dcproject.component.workgroup.WorkgroupRepository
import fr.dcproject.component.workgroup.WorkgroupSimple
import fr.dcproject.component.workgroup.routes.CreateWorkgroup.PostWorkgroupRequest.Input import fr.dcproject.component.workgroup.routes.CreateWorkgroup.PostWorkgroupRequest.Input
import io.ktor.application.call import io.ktor.application.call
import io.ktor.http.HttpStatusCode import io.ktor.http.HttpStatusCode
@@ -33,13 +33,13 @@ object CreateWorkgroup {
fun Route.createWorkgroup(repo: WorkgroupRepository, ac: WorkgroupAccessControl) { fun Route.createWorkgroup(repo: WorkgroupRepository, ac: WorkgroupAccessControl) {
post<PostWorkgroupRequest> { post<PostWorkgroupRequest> {
call.receiveOrBadRequest<Input>().run { call.receiveOrBadRequest<Input>().run {
WorkgroupSimple( WorkgroupForUpdate(
id ?: UUID.randomUUID(), id ?: UUID.randomUUID(),
name, name,
description, description,
citizen,
logo, logo,
anonymous ?: true, anonymous ?: true,
citizen
) )
}.let { workgroup -> }.let { workgroup ->
ac.assert { canCreate(workgroup, citizenOrNull) } ac.assert { canCreate(workgroup, citizenOrNull) }

View File

@@ -4,6 +4,7 @@ import fr.dcproject.common.security.assert
import fr.dcproject.common.utils.receiveOrBadRequest import fr.dcproject.common.utils.receiveOrBadRequest
import fr.dcproject.component.auth.citizenOrNull import fr.dcproject.component.auth.citizenOrNull
import fr.dcproject.component.workgroup.WorkgroupAccessControl import fr.dcproject.component.workgroup.WorkgroupAccessControl
import fr.dcproject.component.workgroup.WorkgroupForUpdate
import fr.dcproject.component.workgroup.WorkgroupRepository import fr.dcproject.component.workgroup.WorkgroupRepository
import fr.dcproject.component.workgroup.routes.EditWorkgroup.PutWorkgroupRequest.Input import fr.dcproject.component.workgroup.routes.EditWorkgroup.PutWorkgroupRequest.Input
import io.ktor.application.call import io.ktor.application.call
@@ -32,11 +33,15 @@ object EditWorkgroup {
put<PutWorkgroupRequest> { put<PutWorkgroupRequest> {
repo.findById(it.workgroupId)?.let { old -> repo.findById(it.workgroupId)?.let { old ->
call.receiveOrBadRequest<Input>().run { call.receiveOrBadRequest<Input>().run {
old.copy( WorkgroupForUpdate(
id = old.id,
name = name ?: old.name, name = name ?: old.name,
description = description ?: old.description, description = description ?: old.description,
createdBy = old.createdBy,
logo = logo ?: old.logo, logo = logo ?: old.logo,
anonymous = anonymous ?: old.anonymous anonymous = anonymous ?: old.anonymous,
deletedAt = old.deletedAt,
members = old.members,
).let { workgroup -> ).let { workgroup ->
ac.assert { canUpdate(workgroup, citizenOrNull) } ac.assert { canUpdate(workgroup, citizenOrNull) }
repo.upsert(workgroup) repo.upsert(workgroup)

View File

@@ -3,11 +3,12 @@ package integration.steps.given
import fr.dcproject.common.utils.toUUID import fr.dcproject.common.utils.toUUID
import fr.dcproject.component.auth.UserForCreate import fr.dcproject.component.auth.UserForCreate
import fr.dcproject.component.citizen.Citizen 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.CitizenForCreate
import fr.dcproject.component.citizen.CitizenI import fr.dcproject.component.citizen.CitizenI
import fr.dcproject.component.citizen.CitizenRepository 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.WorkgroupRepository
import fr.dcproject.component.workgroup.WorkgroupWithMembersI.Member import fr.dcproject.component.workgroup.WorkgroupWithMembersI.Member
import fr.dcproject.component.workgroup.WorkgroupWithMembersI.Member.Role.MASTER import fr.dcproject.component.workgroup.WorkgroupWithMembersI.Member.Role.MASTER
@@ -22,18 +23,18 @@ fun TestApplicationEngine.`Given I have workgroup`(
description: String? = null, description: String? = null,
anonymous: Boolean? = null, anonymous: Boolean? = null,
createdBy: CitizenI.Name? = null, createdBy: CitizenI.Name? = null,
callback: Workgroup<CitizenBasic>.() -> Unit = {}, callback: WorkgroupForView<CitizenCreator>.() -> Unit = {},
) { ) {
val workgroup: Workgroup<CitizenBasic> = createWorkgroup(id?.toUUID(), name, description, anonymous, createdBy) val workgroup: WorkgroupForView<CitizenCreator> = createWorkgroup(id?.toUUID(), name, description, anonymous, createdBy)
callback(workgroup) callback(workgroup)
} }
fun Workgroup<CitizenBasic>.`With members`( fun WorkgroupForView<CitizenCreator>.`With members`(
vararg member: CitizenI.Name vararg member: CitizenI.Name
) { ) {
addMemberToWorkgroup(this, *member) addMemberToWorkgroup(this, *member)
} }
fun addMemberToWorkgroup(workgroup: Workgroup<CitizenBasic>, vararg membersNames: CitizenI.Name) { fun addMemberToWorkgroup(workgroup: WorkgroupForView<CitizenCreator>, vararg membersNames: CitizenI.Name) {
val citizenRepository: CitizenRepository by lazy { GlobalContext.get().koin.get() } val citizenRepository: CitizenRepository by lazy { GlobalContext.get().koin.get() }
val workgroupRepository: WorkgroupRepository 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, description: String? = null,
anonymous: Boolean? = null, anonymous: Boolean? = null,
createdBy: CitizenI.Name? = null, createdBy: CitizenI.Name? = null,
): Workgroup<CitizenBasic> { ): WorkgroupForView<CitizenCreator> {
val citizenRepository: CitizenRepository by lazy { GlobalContext.get().koin.get() } val citizenRepository: CitizenRepository by lazy { GlobalContext.get().koin.get() }
val workgroupRepository: WorkgroupRepository 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(), id = id ?: UUID.randomUUID(),
name = name ?: "Les Incoruptible", name = name ?: "Les Incoruptible",
description = description ?: "La vie est notre jeux", description = description ?: "La vie est notre jeux",
createdBy = creator, createdBy = creator,
anonymous = (anonymous ?: false) == true, anonymous = anonymous ?: false,
members = listOf(Member(creator, listOf(MASTER))) members = listOf(Member(creator, listOf(MASTER)))
) )

View File

@@ -3,9 +3,11 @@ package unit.security
import fr.dcproject.common.security.AccessDecision.DENIED import fr.dcproject.common.security.AccessDecision.DENIED
import fr.dcproject.common.security.AccessDecision.GRANTED import fr.dcproject.common.security.AccessDecision.GRANTED
import fr.dcproject.component.auth.User import fr.dcproject.component.auth.User
import fr.dcproject.component.auth.UserCreator
import fr.dcproject.component.auth.UserI import fr.dcproject.component.auth.UserI
import fr.dcproject.component.citizen.CitizenBasic import fr.dcproject.component.citizen.CitizenBasic
import fr.dcproject.component.citizen.CitizenCart import fr.dcproject.component.citizen.CitizenCart
import fr.dcproject.component.citizen.CitizenCreator
import fr.dcproject.component.citizen.CitizenI import fr.dcproject.component.citizen.CitizenI
import fr.dcproject.component.workgroup.WorkgroupAccessControl import fr.dcproject.component.workgroup.WorkgroupAccessControl
import fr.dcproject.component.workgroup.WorkgroupWithMembersI 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.Execution
import org.junit.jupiter.api.parallel.ExecutionMode.CONCURRENT import org.junit.jupiter.api.parallel.ExecutionMode.CONCURRENT
import java.util.UUID 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) @TestInstance(TestInstance.Lifecycle.PER_CLASS)
@Execution(CONCURRENT) @Execution(CONCURRENT)
@Tags(Tag("security"), Tag("unit")) @Tags(Tag("security"), Tag("unit"))
internal class `Workgroup Access Control` { internal class `Workgroup Access Control` {
private val tesla = CitizenBasic( private val tesla = CitizenCreator(
user = User( user = UserCreator(
username = "nicolas-tesla", username = "nicolas-tesla",
roles = listOf(UserI.Roles.ROLE_USER)
), ),
birthday = DateTime.now(),
email = "tesla@best.com", email = "tesla@best.com",
name = CitizenI.Name("Nicolas", "Tesla"), name = CitizenI.Name("Nicolas", "Tesla"),
followAnonymous = false followAnonymous = false