From f380231e1ecc21bfe78adf71229a41623eb05514 Mon Sep 17 00:00:00 2001 From: Fabrice Date: Thu, 3 Mar 2022 19:42:18 +0100 Subject: [PATCH] Multiple minors fix and improve use data class for entity Add sealed on entity interfaces Replace listOf() by setOf() instead of deduplicate use interface instead of EntityRef replace .toLowerCase() to .lowercase() fix test.sh --- .../component/article/database/Article.kt | 22 +++--- .../component/article/routes/UpsertArticle.kt | 2 +- .../dcproject/component/auth/database/User.kt | 46 ++++++++----- .../component/auth/routes/Register.kt | 2 +- .../component/citizen/database/Citizen.kt | 33 ++++----- .../comment/generic/database/Comment.kt | 20 +++--- .../generic/database/CommentRepository.kt | 69 ++++++++----------- .../component/follow/database/Follow.kt | 15 ++-- .../notification/NotificationMessage.kt | 6 +- .../ArticleNotificationEmailContent.kt | 2 +- .../CitizenNotificationEmailContent.kt | 2 +- .../component/opinion/database/Opinion.kt | 6 +- .../component/opinion/entity/Opinionable.kt | 4 +- .../component/views/dto/ViewAggregation.kt | 2 +- .../component/views/entity/ViewAggregation.kt | 2 +- .../dcproject/component/vote/database/Vote.kt | 6 +- .../component/vote/dto/VoteAggregation.kt | 20 ++++-- .../component/vote/entity/Votable.kt | 4 +- .../component/workgroup/database/Workgroup.kt | 28 ++++---- src/test/kotlin/functional/ViewTest.kt | 4 +- .../integration/Check auth on all routes.kt | 2 +- .../kotlin/integration/steps/given/Auth.kt | 2 +- .../kotlin/integration/steps/given/Citizen.kt | 4 +- .../integration/steps/given/Workgroup.kt | 2 +- .../kotlin/integration/steps/then/schema.kt | 8 +-- .../kotlin/integration/steps/when/request.kt | 18 ++--- .../unit/security/Article Access Control.kt | 2 +- .../unit/security/Citizen Access Control.kt | 6 +- .../unit/security/Comment Access Control.kt | 4 +- .../unit/security/Follow Access Control.kt | 4 +- .../unit/security/Vote Access Control.kt | 4 +- src/test/resources/sql/test.sh | 8 +-- 32 files changed, 180 insertions(+), 179 deletions(-) diff --git a/src/main/kotlin/fr/dcproject/component/article/database/Article.kt b/src/main/kotlin/fr/dcproject/component/article/database/Article.kt index d758c16..b0d1596 100644 --- a/src/main/kotlin/fr/dcproject/component/article/database/Article.kt +++ b/src/main/kotlin/fr/dcproject/component/article/database/Article.kt @@ -48,7 +48,7 @@ data class ArticleForView( val lastVersion: Boolean = false } -interface ArticleForUpdateI : ArticleI, ArticleWithTitleI, VersionableId, TargetI, CreatedBy { +sealed interface ArticleForUpdateI : ArticleI, ArticleWithTitleI, VersionableId, TargetI, CreatedBy { val anonymous: Boolean val content: String val description: String @@ -56,13 +56,13 @@ interface ArticleForUpdateI : ArticleI, ArticleWithTitleI, Versi val workgroup: WorkgroupRef? } -class ArticleForUpdate( +data class ArticleForUpdate( override val id: UUID = UUID.randomUUID(), override val title: String, override val anonymous: Boolean = true, override val content: String, override val description: String, - tags: List = emptyList(), + val tags: Set = emptySet(), override val draft: Boolean = false, override val createdBy: CitizenRef, override val workgroup: WorkgroupRef? = null, @@ -71,12 +71,10 @@ class ArticleForUpdate( ) : ArticleRef(id), ArticleForUpdateI, ArticleAuthI, - VersionableId { - val tags: List = tags.distinct() -} + VersionableId -class ArticleForListing( - id: UUID? = null, +data class ArticleForListing( + override val id: UUID = UUID.randomUUID(), override val title: String, override val createdBy: CitizenCreator, override val workgroup: WorkgroupCart? = null, @@ -90,7 +88,7 @@ class ArticleForListing( CreatedAt by CreatedAt.Imp(), CreatedBy -interface ArticleForListingI : ArticleWithTitleI, CreatedBy { +sealed interface ArticleForListingI : ArticleWithTitleI, CreatedBy { val workgroup: WorkgroupCartI? } @@ -98,13 +96,13 @@ open class ArticleRef( id: UUID? = null ) : ArticleI, TargetRef(id) -interface ArticleI : EntityI, TargetI +sealed interface ArticleI : EntityI, TargetI -interface ArticleWithTitleI : ArticleI { +sealed interface ArticleWithTitleI : ArticleI { val title: String } -interface ArticleAuthI : +sealed interface ArticleAuthI : ArticleI, CreatedBy, DeletedAt { diff --git a/src/main/kotlin/fr/dcproject/component/article/routes/UpsertArticle.kt b/src/main/kotlin/fr/dcproject/component/article/routes/UpsertArticle.kt index 8f018f1..82ddb83 100644 --- a/src/main/kotlin/fr/dcproject/component/article/routes/UpsertArticle.kt +++ b/src/main/kotlin/fr/dcproject/component/article/routes/UpsertArticle.kt @@ -37,7 +37,7 @@ object UpsertArticle { val anonymous: Boolean = true, val content: String, val description: String, - val tags: List = emptyList(), + val tags: Set = emptySet(), val draft: Boolean = false, val versionId: UUID, val workgroup: WorkgroupRef? = null, diff --git a/src/main/kotlin/fr/dcproject/component/auth/database/User.kt b/src/main/kotlin/fr/dcproject/component/auth/database/User.kt index fe43d14..c25d40d 100644 --- a/src/main/kotlin/fr/dcproject/component/auth/database/User.kt +++ b/src/main/kotlin/fr/dcproject/component/auth/database/User.kt @@ -9,35 +9,45 @@ import io.ktor.auth.Principal import org.joda.time.DateTime import java.util.UUID -class UserForCreate( - id: UUID = UUID.randomUUID(), - username: String, +data class UserForCreate( + override val id: UUID = UUID.randomUUID(), + override val username: String, override val password: String, - blockedAt: DateTime? = null, - roles: List = emptyList() -) : User(id, username, blockedAt, roles), - UserWithPasswordI + override val blockedAt: DateTime? = null, + override val roles: Set = emptySet() +) : UserForViewI, + UserWithPasswordI, + CreatedAt by CreatedAt.Imp(), + UpdatedAt by UpdatedAt.Imp() -open class User( - id: UUID = UUID.randomUUID(), - override var username: String, - var blockedAt: DateTime? = null, - var roles: List = emptyList() +data class User( + override val id: UUID = UUID.randomUUID(), + override val username: String, + override val blockedAt: DateTime? = null, + override val roles: Set = emptySet() ) : UserRef(id), + UserForViewI, UserWithUsername, CreatedAt by CreatedAt.Imp(), UpdatedAt by UpdatedAt.Imp() +sealed interface UserForViewI : + UserI, + UserWithUsername, + UserForAuthI, + CreatedAt, + UpdatedAt + class UserCreator( id: UUID = UUID.randomUUID(), override val username: String, ) : UserRef(id), UserWithUsername -interface UserWithUsername : UserI { +sealed interface UserWithUsername : UserI { val username: String } -interface UserWithPasswordI : UserI { +sealed interface UserWithPasswordI : UserI { val password: String } @@ -51,11 +61,11 @@ open class UserRef( id: UUID = UUID.randomUUID() ) : UserI, Entity(id) -interface UserI : EntityI, Principal { +sealed interface UserI : EntityI, Principal { enum class Roles { ROLE_USER, ROLE_ADMIN } } -interface UserForAuthI : UserI { - var roles: List - var blockedAt: DateTime? +sealed interface UserForAuthI : UserI { + val roles: Set + val blockedAt: DateTime? } diff --git a/src/main/kotlin/fr/dcproject/component/auth/routes/Register.kt b/src/main/kotlin/fr/dcproject/component/auth/routes/Register.kt index 0daa29a..d3f6fe0 100644 --- a/src/main/kotlin/fr/dcproject/component/auth/routes/Register.kt +++ b/src/main/kotlin/fr/dcproject/component/auth/routes/Register.kt @@ -91,7 +91,7 @@ object Register { user = UserForCreate( username = user.username, password = user.password, - roles = listOf(UserI.Roles.ROLE_USER) + roles = setOf(UserI.Roles.ROLE_USER) ) ) diff --git a/src/main/kotlin/fr/dcproject/component/citizen/database/Citizen.kt b/src/main/kotlin/fr/dcproject/component/citizen/database/Citizen.kt index 14d0597..6fef54e 100644 --- a/src/main/kotlin/fr/dcproject/component/citizen/database/Citizen.kt +++ b/src/main/kotlin/fr/dcproject/component/citizen/database/Citizen.kt @@ -17,19 +17,19 @@ import fr.postgresjson.entity.Serializable import org.joda.time.DateTime import java.util.UUID -class CitizenForCreate( +data class CitizenForCreate( val name: Name, val email: String, val birthday: DateTime, val voteAnonymous: Boolean = true, val followAnonymous: Boolean = true, override val user: UserForCreate, - id: UUID = UUID.randomUUID(), + override val id: UUID = UUID.randomUUID(), ) : CitizenI, - CitizenRefWithUser(id, user), + CitizenWithUserI by CitizenRefWithUser(id, user), CreatedAt by CreatedAt.Imp() -class Citizen( +data class Citizen( override val id: UUID = UUID.randomUUID(), override val name: Name, override val email: String, @@ -37,7 +37,7 @@ class Citizen( override val voteAnonymous: Boolean = true, override val followAnonymous: Boolean = true, override val user: User, - deletedAt: DateTime? = null + override val deletedAt: DateTime? = null ) : CitizenWithEmail, CitizenCreatorI, CitizenWithUserI, @@ -62,10 +62,11 @@ data class CitizenCreator( override val user: UserCreator, override val deletedAt: DateTime? = null ) : CitizenCreatorI, - CitizenRefWithUser(id, user), + CitizenI, + CitizenWithUserI by CitizenRefWithUser(id, user), DeletedAt by DeletedAt.Imp(deletedAt) -interface CitizenCreatorI : CitizenWithUserI, CitizenWithEmail, CitizenCartI, DeletedAt { +sealed interface CitizenCreatorI : CitizenWithUserI, CitizenWithEmail, CitizenCartI, DeletedAt { override val id: UUID override val name: Name override val email: String @@ -75,8 +76,8 @@ interface CitizenCreatorI : CitizenWithUserI, CitizenWithEmail, CitizenCartI, De override val deletedAt: DateTime? } -class CitizenCart( - id: UUID = UUID.randomUUID(), +data class CitizenCart( + override val id: UUID = UUID.randomUUID(), override val name: Name, override val user: UserRef, override val deletedAt: DateTime? = null, @@ -84,13 +85,13 @@ class CitizenCart( CitizenCartI, DeletedAt by DeletedAt.Imp(deletedAt) -interface CitizenCartI : CitizenI, CitizenWithUserI { +sealed interface CitizenCartI : CitizenI, CitizenWithUserI { val name: Name } -open class CitizenRefWithUser( - id: UUID = UUID.randomUUID(), - override val user: UserRef +data class CitizenRefWithUser( + override val id: UUID = UUID.randomUUID(), + override val user: UserI ) : CitizenWithUserI, CitizenRef(id) @@ -99,7 +100,7 @@ open class CitizenRef( ) : TargetRef(id), CitizenI -interface CitizenI : EntityI, TargetI { +sealed interface CitizenI : EntityI, TargetI { data class Name( override val firstName: String, override val lastName: String, @@ -114,10 +115,10 @@ interface CitizenI : EntityI, TargetI { } } -interface CitizenWithUserI : CitizenI { +sealed interface CitizenWithUserI : CitizenI { val user: UserI } -interface CitizenWithEmail : CitizenI { +sealed interface CitizenWithEmail : CitizenI { val email: String } diff --git a/src/main/kotlin/fr/dcproject/component/comment/generic/database/Comment.kt b/src/main/kotlin/fr/dcproject/component/comment/generic/database/Comment.kt index fdb95f0..e2f30cd 100644 --- a/src/main/kotlin/fr/dcproject/component/comment/generic/database/Comment.kt +++ b/src/main/kotlin/fr/dcproject/component/comment/generic/database/Comment.kt @@ -16,8 +16,8 @@ import fr.dcproject.component.vote.entity.VotableImp import org.joda.time.DateTime import java.util.UUID -class CommentForView( - id: UUID = UUID.randomUUID(), +data class CommentForView( + override val id: UUID = UUID.randomUUID(), override val createdBy: C, override val target: T, override var content: String, @@ -30,7 +30,7 @@ class CommentForView( CommentWithTargetI, CreatedBy by CreatedBy.Imp(createdBy), UpdatedAt by UpdatedAt.Imp(), - DeletedAt by DeletedAt.Imp(), + DeletedAt, Votable by VotableImp(), TargetI { constructor( @@ -50,9 +50,9 @@ open class CommentForUpdate( override val createdBy: C, override val target: T, open var content: String, - override val parent: CommentParent? = null, + override val parent: CommentParentI? = null, override val deletedAt: DateTime? = null -) : CommentParent(id, deletedAt, target), +) : CommentParentI by CommentParent(id, deletedAt, target), CommentWithParentI, ExtraI, CommentWithTargetI, @@ -62,7 +62,7 @@ open class CommentForUpdate( TargetI { constructor( createdBy: C, - parent: CommentParent, + parent: CommentParentI, content: String, id: UUID? = null, ) : this( @@ -74,21 +74,21 @@ open class CommentForUpdate( ) } -open class CommentParent( +data class CommentParent( override val id: UUID, override val deletedAt: DateTime?, override val target: T ) : CommentRef(id), CommentParentI -interface CommentParentI : CommentI, DeletedAt, CommentWithTargetI +sealed interface CommentParentI : CommentI, DeletedAt, CommentWithTargetI interface CommentWithTargetI : CommentI, TargetI, HasTarget interface CommentWithParentI { - val parent: CommentParent? + val parent: CommentParentI? } open class CommentRef(id: UUID = UUID.randomUUID()) : CommentI, TargetRef(id) -interface CommentI : EntityI +sealed interface CommentI : EntityI diff --git a/src/main/kotlin/fr/dcproject/component/comment/generic/database/CommentRepository.kt b/src/main/kotlin/fr/dcproject/component/comment/generic/database/CommentRepository.kt index 8a86a7b..1f140eb 100644 --- a/src/main/kotlin/fr/dcproject/component/comment/generic/database/CommentRepository.kt +++ b/src/main/kotlin/fr/dcproject/component/comment/generic/database/CommentRepository.kt @@ -32,26 +32,21 @@ abstract class CommentRepositoryAbs(override var requester: Request parentId: UUID, page: Int = 1, limit: Int = 50 - ): Paginated> { - return requester.run { - getFunction("find_comments_by_parent") - .select>( - page, - limit, - "parent_id" to parentId - ) - as Paginated> - } - } + ): Paginated> = requester + .getFunction("find_comments_by_parent") + .select>( + page, + limit, + "parent_id" to parentId + ) + as Paginated> open fun findByTarget( target: EntityI, page: Int = 1, limit: Int = 50, sort: String = "createdAt" - ): Paginated> { - return findByTarget(target.id, page, limit, sort) - } + ): Paginated> = findByTarget(target.id, page, limit, sort) open fun findByTarget( targetId: UUID, @@ -85,41 +80,33 @@ abstract class CommentRepositoryAbs(override var requester: Request } class CommentRepository(requester: Requester) : CommentRepositoryAbs(requester) { - override fun findById(id: UUID): CommentForView? { - return requester - .getFunction("find_comment_by_id") - .selectOne>(mapOf("id" to id)) - as CommentForView? - } + override fun findById(id: UUID): CommentForView? = requester + .getFunction("find_comment_by_id") + .selectOne>(mapOf("id" to id)) + as CommentForView? override fun findByCitizen( citizen: CitizenI, page: Int, limit: Int - ): Paginated> { - return requester.run { - getFunction("find_comments_by_citizen") - .select>( - page, - limit, - "created_by_id" to citizen.id - ) as Paginated> - } - } + ): Paginated> = requester + .getFunction("find_comments_by_citizen") + .select>( + page, + limit, + "created_by_id" to citizen.id + ) as Paginated> override fun findByParent( parentId: UUID, page: Int, limit: Int - ): Paginated> { - return requester.run { - getFunction("find_comments_by_parent") - .select>( - page, - limit, - "parent_id" to parentId - ) - as Paginated> - } - } + ): Paginated> = requester + .getFunction("find_comments_by_parent") + .select>( + page, + limit, + "parent_id" to parentId + ) + as Paginated> } diff --git a/src/main/kotlin/fr/dcproject/component/follow/database/Follow.kt b/src/main/kotlin/fr/dcproject/component/follow/database/Follow.kt index aeafd6c..78ed7c7 100644 --- a/src/main/kotlin/fr/dcproject/component/follow/database/Follow.kt +++ b/src/main/kotlin/fr/dcproject/component/follow/database/Follow.kt @@ -8,19 +8,18 @@ import fr.dcproject.common.entity.HasTarget import fr.dcproject.common.entity.TargetI import fr.dcproject.component.citizen.database.CitizenCreator import fr.dcproject.component.citizen.database.CitizenI -import fr.dcproject.component.citizen.database.CitizenRef import java.util.UUID -open class FollowForView( - id: UUID = UUID.randomUUID(), +data class FollowForView( + override val id: UUID = UUID.randomUUID(), override val createdBy: CitizenCreator, override var target: T -) : ExtraI, +) : ExtraI, FollowRef(id), - Created by Created.Imp(createdBy) + Created by Created.Imp(createdBy) -class FollowForUpdate( - id: UUID = UUID.randomUUID(), +data class FollowForUpdate( + override val id: UUID = UUID.randomUUID(), override val target: T, override val createdBy: C ) : FollowRef(id), @@ -31,4 +30,4 @@ open class FollowRef( override val id: UUID ) : FollowI -interface FollowI : EntityI +sealed interface FollowI : EntityI diff --git a/src/main/kotlin/fr/dcproject/component/notification/NotificationMessage.kt b/src/main/kotlin/fr/dcproject/component/notification/NotificationMessage.kt index 0b7c985..611713f 100644 --- a/src/main/kotlin/fr/dcproject/component/notification/NotificationMessage.kt +++ b/src/main/kotlin/fr/dcproject/component/notification/NotificationMessage.kt @@ -53,11 +53,11 @@ open class NotificationMessage( } open class EntityNotificationMessage ( - val target: E, + open val target: E, type: String, val action: String ) : NotificationMessage(type) -class ArticleUpdateNotificationMessage( - target: ArticleForView +data class ArticleUpdateNotificationMessage( + override val target: ArticleForView ) : EntityNotificationMessage(target, "article", "update") diff --git a/src/main/kotlin/fr/dcproject/component/notification/email/content/ArticleNotificationEmailContent.kt b/src/main/kotlin/fr/dcproject/component/notification/email/content/ArticleNotificationEmailContent.kt index 2d634ca..0d61b82 100644 --- a/src/main/kotlin/fr/dcproject/component/notification/email/content/ArticleNotificationEmailContent.kt +++ b/src/main/kotlin/fr/dcproject/component/notification/email/content/ArticleNotificationEmailContent.kt @@ -3,7 +3,7 @@ package fr.dcproject.component.notification.email.content import fr.dcproject.component.article.database.ArticleWithTitleI import fr.dcproject.component.citizen.database.Citizen -class ArticleNotificationEmailContent( +data class ArticleNotificationEmailContent( private val citizen: Citizen, private val target: ArticleWithTitleI, private val domain: String, diff --git a/src/main/kotlin/fr/dcproject/component/notification/email/content/CitizenNotificationEmailContent.kt b/src/main/kotlin/fr/dcproject/component/notification/email/content/CitizenNotificationEmailContent.kt index af1a5dc..2d259a3 100644 --- a/src/main/kotlin/fr/dcproject/component/notification/email/content/CitizenNotificationEmailContent.kt +++ b/src/main/kotlin/fr/dcproject/component/notification/email/content/CitizenNotificationEmailContent.kt @@ -2,7 +2,7 @@ package fr.dcproject.component.notification.email.content import fr.dcproject.component.citizen.database.Citizen -class CitizenNotificationEmailContent( +data class CitizenNotificationEmailContent( private val citizen: Citizen, private val target: Citizen, private val domain: String, diff --git a/src/main/kotlin/fr/dcproject/component/opinion/database/Opinion.kt b/src/main/kotlin/fr/dcproject/component/opinion/database/Opinion.kt index 56864a7..cf761e8 100644 --- a/src/main/kotlin/fr/dcproject/component/opinion/database/Opinion.kt +++ b/src/main/kotlin/fr/dcproject/component/opinion/database/Opinion.kt @@ -13,8 +13,8 @@ import fr.dcproject.component.citizen.database.CitizenI import fr.dcproject.component.citizen.database.CitizenRef import java.util.UUID -open class Opinion( - id: UUID = UUID.randomUUID(), +data class Opinion( + override val id: UUID = UUID.randomUUID(), override val createdBy: CitizenCreator, override val target: T, val choice: OpinionChoice @@ -39,4 +39,4 @@ open class OpinionRef( override val id: UUID ) : OpinionI, TargetRef(id) -interface OpinionI : EntityI +sealed interface OpinionI : EntityI diff --git a/src/main/kotlin/fr/dcproject/component/opinion/entity/Opinionable.kt b/src/main/kotlin/fr/dcproject/component/opinion/entity/Opinionable.kt index 61a2684..d3a983f 100644 --- a/src/main/kotlin/fr/dcproject/component/opinion/entity/Opinionable.kt +++ b/src/main/kotlin/fr/dcproject/component/opinion/entity/Opinionable.kt @@ -7,6 +7,4 @@ interface Opinionable { val opinions: Opinions } -class OpinionableImp : Opinionable { - override var opinions: OpinionsMutable = mutableMapOf() -} +data class OpinionableImp(override var opinions: OpinionsMutable = mutableMapOf()) : Opinionable diff --git a/src/main/kotlin/fr/dcproject/component/views/dto/ViewAggregation.kt b/src/main/kotlin/fr/dcproject/component/views/dto/ViewAggregation.kt index 41b1b93..5336ac6 100644 --- a/src/main/kotlin/fr/dcproject/component/views/dto/ViewAggregation.kt +++ b/src/main/kotlin/fr/dcproject/component/views/dto/ViewAggregation.kt @@ -2,7 +2,7 @@ package fr.dcproject.component.views.dto import fr.dcproject.component.views.entity.ViewAggregation -class ViewAggregation( +data class ViewAggregation( val total: Int, val unique: Int ) { diff --git a/src/main/kotlin/fr/dcproject/component/views/entity/ViewAggregation.kt b/src/main/kotlin/fr/dcproject/component/views/entity/ViewAggregation.kt index f9e5f95..ffdfb6f 100644 --- a/src/main/kotlin/fr/dcproject/component/views/entity/ViewAggregation.kt +++ b/src/main/kotlin/fr/dcproject/component/views/entity/ViewAggregation.kt @@ -3,7 +3,7 @@ package fr.dcproject.component.views.entity import fr.dcproject.common.entity.UpdatedAt import fr.postgresjson.entity.EntityI -class ViewAggregation( +data class ViewAggregation( val total: Int, val unique: Int ) : EntityI, diff --git a/src/main/kotlin/fr/dcproject/component/vote/database/Vote.kt b/src/main/kotlin/fr/dcproject/component/vote/database/Vote.kt index 0fc6af0..648e165 100644 --- a/src/main/kotlin/fr/dcproject/component/vote/database/Vote.kt +++ b/src/main/kotlin/fr/dcproject/component/vote/database/Vote.kt @@ -12,8 +12,8 @@ import fr.dcproject.component.citizen.database.CitizenCreatorI import fr.dcproject.component.citizen.database.CitizenI import java.util.UUID -class VoteForView( - id: UUID = UUID.randomUUID(), +data class VoteForView( + override val id: UUID = UUID.randomUUID(), override val createdBy: CitizenCreator, override val target: T, val note: Int, @@ -30,7 +30,7 @@ class VoteForView( } } -class VoteForUpdate( +data class VoteForUpdate( override val id: UUID = UUID.randomUUID(), override val note: Int, override val target: T, diff --git a/src/main/kotlin/fr/dcproject/component/vote/dto/VoteAggregation.kt b/src/main/kotlin/fr/dcproject/component/vote/dto/VoteAggregation.kt index b109cb7..bb8da12 100644 --- a/src/main/kotlin/fr/dcproject/component/vote/dto/VoteAggregation.kt +++ b/src/main/kotlin/fr/dcproject/component/vote/dto/VoteAggregation.kt @@ -2,10 +2,18 @@ package fr.dcproject.component.vote.dto import fr.dcproject.component.vote.entity.Votable -class VoteAggregation(parent: Votable) { - val up: Int = parent.votes.up - val neutral: Int = parent.votes.neutral - val down: Int = parent.votes.down - val total: Int = parent.votes.total - val score: Int = parent.votes.score +data class VoteAggregation( + val up: Int, + val neutral: Int, + val down: Int, + val total: Int, + val score: Int +) { + constructor(parent: Votable) : this( + up = parent.votes.up, + neutral = parent.votes.neutral, + down = parent.votes.down, + total = parent.votes.total, + score = parent.votes.score + ) } diff --git a/src/main/kotlin/fr/dcproject/component/vote/entity/Votable.kt b/src/main/kotlin/fr/dcproject/component/vote/entity/Votable.kt index 6971e80..82fb028 100644 --- a/src/main/kotlin/fr/dcproject/component/vote/entity/Votable.kt +++ b/src/main/kotlin/fr/dcproject/component/vote/entity/Votable.kt @@ -4,6 +4,6 @@ interface Votable { val votes: VoteAggregation } -class VotableImp : Votable { +data class VotableImp( override val votes: VoteAggregation = VoteAggregation() -} +) : Votable diff --git a/src/main/kotlin/fr/dcproject/component/workgroup/database/Workgroup.kt b/src/main/kotlin/fr/dcproject/component/workgroup/database/Workgroup.kt index 9e3a4ed..13979a5 100644 --- a/src/main/kotlin/fr/dcproject/component/workgroup/database/Workgroup.kt +++ b/src/main/kotlin/fr/dcproject/component/workgroup/database/Workgroup.kt @@ -43,17 +43,17 @@ data class WorkgroupForUpdate( WorkgroupForUpdateI, CreatedBy by CreatedBy.Imp(createdBy) -interface WorkgroupForUpdateI : WorkgroupWithAuthI, WorkgroupCartI, CreatedBy { +sealed interface WorkgroupForUpdateI : WorkgroupWithAuthI, WorkgroupCartI, CreatedBy { val description: String val logo: String? } -class WorkgroupCart( +data class WorkgroupCart( override val id: UUID, override val name: String ) : WorkgroupCartI -interface WorkgroupCartI : EntityI { +sealed interface WorkgroupCartI : EntityI { val name: String } @@ -61,7 +61,7 @@ open class WorkgroupRef( id: UUID? = null ) : Entity(id ?: UUID.randomUUID()), WorkgroupI -interface WorkgroupWithAuthI : WorkgroupWithMembersI, CreatedBy, DeletedAt { +sealed interface WorkgroupWithAuthI : WorkgroupWithMembersI, CreatedBy, DeletedAt { val anonymous: Boolean fun isMember(user: UserI): Boolean = members.isMember(user) @@ -70,11 +70,11 @@ interface WorkgroupWithAuthI : WorkgroupWithMembersI, C fun hasRole(expectedRole: Role, user: UserI): Boolean = members.hasRole(expectedRole, user) fun hasRole(expectedRole: Role, citizen: CitizenI): Boolean = members.hasRole(expectedRole, citizen) - fun getRoles(user: UserI): List = members.getRoles(user) - fun getRoles(citizen: CitizenI): List = members.getRoles(citizen) + fun getRoles(user: UserI): Collection = members.getRoles(user) + fun getRoles(citizen: CitizenI): Collection = members.getRoles(citizen) } -interface WorkgroupWithMembersI : WorkgroupI { +sealed interface WorkgroupWithMembersI : WorkgroupI { val members: List> class Member( @@ -90,24 +90,24 @@ interface WorkgroupWithMembersI : WorkgroupI { } } -fun List.hasCitizen(citizen: CitizenI): Boolean = this.map { it.id }.contains(citizen.id) +fun Collection.hasCitizen(citizen: CitizenI): Boolean = this.map { it.id }.contains(citizen.id) -fun List>.isMember(user: UserI): Boolean = +fun Collection>.isMember(user: UserI): Boolean = map { it.citizen.user.id }.contains(user.id) -fun List>.isMember(citizen: CitizenI): Boolean = +fun Collection>.isMember(citizen: CitizenI): Boolean = map { it.citizen.id }.contains(citizen.id) -fun List>.hasRole(expectedRole: Role, citizen: CitizenI): Boolean = +fun Collection>.hasRole(expectedRole: Role, citizen: CitizenI): Boolean = any { member -> member.citizen.id == citizen.id && member.roles.any { it == expectedRole } } -fun List>.hasRole(expectedRole: Role, user: UserI): Boolean = +fun Collection>.hasRole(expectedRole: Role, user: UserI): Boolean = any { member -> member.citizen.user.id == user.id && member.roles.any { it == expectedRole } } -fun List>.getRoles(user: UserI): List = +fun Collection>.getRoles(user: UserI): Collection = firstOrNull { it.citizen.user.id == user.id }?.roles ?: emptyList() -fun List>.getRoles(citizen: CitizenI): List = +fun Collection>.getRoles(citizen: CitizenI): Collection = firstOrNull { it.citizen.id == citizen.id }?.roles ?: emptyList() interface WorkgroupI : EntityI diff --git a/src/test/kotlin/functional/ViewTest.kt b/src/test/kotlin/functional/ViewTest.kt index 92795ff..5a89c8d 100644 --- a/src/test/kotlin/functional/ViewTest.kt +++ b/src/test/kotlin/functional/ViewTest.kt @@ -20,8 +20,8 @@ import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS import org.koin.ktor.ext.get import java.util.UUID +import kotlin.time.Duration.Companion.seconds import kotlin.time.ExperimentalTime -import kotlin.time.seconds @KtorExperimentalLocationsAPI @ExperimentalCoroutinesApi @@ -78,7 +78,7 @@ class ViewTest { ) /* Retry because ES is not sync ! */ - retry(10, 0.3.seconds) { + retry(10, seconds(0.3)) { /* Get view */ val afterView = viewRepository.getViewsCount(article) diff --git a/src/test/kotlin/integration/Check auth on all routes.kt b/src/test/kotlin/integration/Check auth on all routes.kt index a148b1e..702c48e 100644 --- a/src/test/kotlin/integration/Check auth on all routes.kt +++ b/src/test/kotlin/integration/Check auth on all routes.kt @@ -35,7 +35,7 @@ class `Check auth on all routes` : BaseTest() { /* Send request to check security */ sendRequest( path.buildUrl(pathName, methodName, api.context), /* Replace route to real URL */ - HttpMethod.parse(methodName.toUpperCase()) /* Convert http method name to enum */ + HttpMethod.parse(methodName.lowercase()) /* Convert http method name to enum */ ) } }.let { requests -> diff --git a/src/test/kotlin/integration/steps/given/Auth.kt b/src/test/kotlin/integration/steps/given/Auth.kt index 7401d3b..6cb4d05 100644 --- a/src/test/kotlin/integration/steps/given/Auth.kt +++ b/src/test/kotlin/integration/steps/given/Auth.kt @@ -13,7 +13,7 @@ fun TestApplicationRequest.`authenticated as`( firstName: String, lastName: String, ): Citizen { - val username = "$firstName-$lastName".toLowerCase() + val username = "$firstName-$lastName".lowercase() val repo: CitizenRepository by lazy { GlobalContext.get().get() } val citizen = repo.findByUsername(username) ?: error("Citizen not exist with username $username") val algorithm = GlobalContext.get().get().algorithm diff --git a/src/test/kotlin/integration/steps/given/Citizen.kt b/src/test/kotlin/integration/steps/given/Citizen.kt index cb763c6..8bdb138 100644 --- a/src/test/kotlin/integration/steps/given/Citizen.kt +++ b/src/test/kotlin/integration/steps/given/Citizen.kt @@ -14,7 +14,7 @@ import java.util.UUID fun TestApplicationEngine.`Given I have citizen`( firstName: String, lastName: String, - email: String = ("$firstName-$lastName".toLowerCase()) + "@dc-project.fr", + email: String = ("$firstName-$lastName".lowercase()) + "@dc-project.fr", id: String = UUID.randomUUID().toString(), callback: Citizen.() -> Unit = {} ): Citizen? { @@ -22,7 +22,7 @@ fun TestApplicationEngine.`Given I have citizen`( val user = UserForCreate( id = id.toUUID(), - username = "$firstName-$lastName".toLowerCase(), + username = "$firstName-$lastName".lowercase(), password = "Azerty123!", ) val citizen = CitizenForCreate( diff --git a/src/test/kotlin/integration/steps/given/Workgroup.kt b/src/test/kotlin/integration/steps/given/Workgroup.kt index b6aac03..b433551 100644 --- a/src/test/kotlin/integration/steps/given/Workgroup.kt +++ b/src/test/kotlin/integration/steps/given/Workgroup.kt @@ -62,7 +62,7 @@ private fun createWorkgroup( val creatorName = createdBy ?: CitizenI.Name("Paul", "Langevin") val creator = citizenRepository.findByName(creatorName) ?: run { val username = ("username" + UUID.randomUUID().toString()) - .toLowerCase().replace(' ', '-') + .lowercase().replace(' ', '-') val user = UserForCreate( username = username, password = "Azerty123!", diff --git a/src/test/kotlin/integration/steps/then/schema.kt b/src/test/kotlin/integration/steps/then/schema.kt index fe04cf0..85cc9f1 100644 --- a/src/test/kotlin/integration/steps/then/schema.kt +++ b/src/test/kotlin/integration/steps/then/schema.kt @@ -46,7 +46,7 @@ fun TestApplicationResponse.operation(route: String? = null, callback: Operation .firstOrNull { uri.matches(it.replace("""\{[^{}]+}""".toRegex(), "[^/]+").toRegex()) } api.getPath(path) - ?.getOperation(httpMethod.value.toLowerCase()) + ?.getOperation(httpMethod.value.lowercase()) ?.apply { this.callback(api, uri) } @@ -59,7 +59,7 @@ fun TestApplicationResponse.`And the schema response body must be valid`(content /* Validate Response */ this.apply { val status = call.response.status() - val httpMethod = call.request.httpMethod.value.toUpperCase() + val httpMethod = call.request.httpMethod.value.lowercase() val responseContent: JsonNode = if (content != null) ObjectMapper().readTree(content) else TextNode("") @@ -79,7 +79,7 @@ fun TestApplicationResponse.`And the schema parameters must be valid`() { operation { api, uri -> /* Validate Request URL */ this.apply { - val methodName = call.request.httpMethod.value.toUpperCase() + val methodName = call.request.httpMethod.value.lowercase() Url(call.request.uri).parameters.forEach { parameter: String, values: List -> val schema = getParametersIn(api.context, "query") ?.firstOrNull { it.name == parameter }?.schema @@ -103,7 +103,7 @@ fun TestApplicationResponse.`And the schema parameters must be valid`() { * Validate request body */ fun TestApplicationResponse.`And the schema request body must be valid`(body: String) { - operation { api, uri -> + operation { api, _ -> requestBody .getContentMediaType(call.request.contentType().toString()) .schema diff --git a/src/test/kotlin/integration/steps/when/request.kt b/src/test/kotlin/integration/steps/when/request.kt index fe71e72..ee2ec46 100644 --- a/src/test/kotlin/integration/steps/when/request.kt +++ b/src/test/kotlin/integration/steps/when/request.kt @@ -15,15 +15,15 @@ import io.ktor.server.testing.TestApplicationRequest import io.ktor.server.testing.setBody enum class Validate(override val bit: Long) : BitMaskI { - NONE(0), - REQUEST_BODY(1), - REQUEST_PARAM(2), - REQUEST_HEADER(4), - REQUEST(1 + 2 + 4), - RESPONSE_BODY(8), - RESPONSE_HEADER(16), - RESPONSE(8 + 16), - ALL((1 + 2 + 4) + (8 + 16)); + NONE(0L), + REQUEST_BODY(1L), + REQUEST_PARAM(2L), + REQUEST_HEADER(4L), + REQUEST(1L + 2L + 4L), + RESPONSE_BODY(8L), + RESPONSE_HEADER(16L), + RESPONSE(8L + 16L), + ALL((1L + 2L + 4L) + (8L + 16L)); operator fun unaryMinus(): BitMaskI = ALL - BitMask(this.bit) } diff --git a/src/test/kotlin/unit/security/Article Access Control.kt b/src/test/kotlin/unit/security/Article Access Control.kt index 9f9389b..df859b7 100644 --- a/src/test/kotlin/unit/security/Article Access Control.kt +++ b/src/test/kotlin/unit/security/Article Access Control.kt @@ -41,7 +41,7 @@ internal class `Article Access Control` { private val einstein = CitizenCart( user = User( username = "albert-einstein", - roles = listOf(UserI.Roles.ROLE_USER) + roles = setOf(UserI.Roles.ROLE_USER) ), name = CitizenI.Name("Albert", "Einstein") ) diff --git a/src/test/kotlin/unit/security/Citizen Access Control.kt b/src/test/kotlin/unit/security/Citizen Access Control.kt index 153356c..715c897 100644 --- a/src/test/kotlin/unit/security/Citizen Access Control.kt +++ b/src/test/kotlin/unit/security/Citizen Access Control.kt @@ -23,14 +23,14 @@ internal class `Citizen Access Control` { private val tesla = CitizenCart( user = User( username = "nicolas-tesla", - roles = listOf(UserI.Roles.ROLE_USER) + roles = setOf(UserI.Roles.ROLE_USER) ), name = CitizenI.Name("Nicolas", "Tesla") ) private val einstein = CitizenCart( user = User( username = "albert-einstein", - roles = listOf(UserI.Roles.ROLE_USER) + roles = setOf(UserI.Roles.ROLE_USER) ), name = CitizenI.Name("Albert", "Einstein") ) @@ -38,7 +38,7 @@ internal class `Citizen Access Control` { private val curie = CitizenCart( user = User( username = "marie-curie", - roles = listOf(UserI.Roles.ROLE_USER) + roles = setOf(UserI.Roles.ROLE_USER) ), name = CitizenI.Name("Marie", "Curie"), deletedAt = DateTime.now() diff --git a/src/test/kotlin/unit/security/Comment Access Control.kt b/src/test/kotlin/unit/security/Comment Access Control.kt index e2d9260..f380292 100644 --- a/src/test/kotlin/unit/security/Comment Access Control.kt +++ b/src/test/kotlin/unit/security/Comment Access Control.kt @@ -30,7 +30,7 @@ internal class `Comment Access Control` { private val tesla = Citizen( user = User( username = "nicolas-tesla", - roles = listOf(UserI.Roles.ROLE_USER) + roles = setOf(UserI.Roles.ROLE_USER) ), birthday = DateTime.now(), email = "tesla@best.com", @@ -40,7 +40,7 @@ internal class `Comment Access Control` { id = UUID.fromString("319f1226-8f47-4df3-babd-2c7671ad0fbc"), user = User( username = "albert-einstein", - roles = listOf(UserI.Roles.ROLE_USER) + roles = setOf(UserI.Roles.ROLE_USER) ), birthday = DateTime.now(), email = "einstein@best.com", diff --git a/src/test/kotlin/unit/security/Follow Access Control.kt b/src/test/kotlin/unit/security/Follow Access Control.kt index c093a7e..c644869 100644 --- a/src/test/kotlin/unit/security/Follow Access Control.kt +++ b/src/test/kotlin/unit/security/Follow Access Control.kt @@ -36,7 +36,7 @@ internal class `Follow Access Control` { private val tesla2 = Citizen( user = User( username = "nicolas-tesla", - roles = listOf(UserI.Roles.ROLE_USER) + roles = setOf(UserI.Roles.ROLE_USER) ), birthday = DateTime.now(), email = "tesla@best.com", @@ -67,7 +67,7 @@ internal class `Follow Access Control` { id = UUID.fromString("319f1226-8f47-4df3-babd-2c7671ad0fbc"), user = User( username = "albert-einstein", - roles = listOf(UserI.Roles.ROLE_USER) + roles = setOf(UserI.Roles.ROLE_USER) ), birthday = DateTime.now(), email = "einstein@best.com", diff --git a/src/test/kotlin/unit/security/Vote Access Control.kt b/src/test/kotlin/unit/security/Vote Access Control.kt index e10f69a..5bf784a 100644 --- a/src/test/kotlin/unit/security/Vote Access Control.kt +++ b/src/test/kotlin/unit/security/Vote Access Control.kt @@ -30,7 +30,7 @@ internal class `Vote Access Control` { id = UUID.fromString("a1e35c99-9d33-4fb4-9201-58d7071243bb"), user = User( username = "nicolas-tesla", - roles = listOf(UserI.Roles.ROLE_USER) + roles = setOf(UserI.Roles.ROLE_USER) ), birthday = DateTime.now(), email = "tesla@best.com", @@ -51,7 +51,7 @@ internal class `Vote Access Control` { id = UUID.fromString("319f1226-8f47-4df3-babd-2c7671ad0fbc"), user = User( username = "albert-einstein", - roles = listOf(UserI.Roles.ROLE_USER) + roles = setOf(UserI.Roles.ROLE_USER) ), birthday = DateTime.now(), email = "einstein@best.com", diff --git a/src/test/resources/sql/test.sh b/src/test/resources/sql/test.sh index 83767dd..2b17577 100644 --- a/src/test/resources/sql/test.sh +++ b/src/test/resources/sql/test.sh @@ -15,15 +15,15 @@ fi case $opt in "RESET DB") awk 'FNR==1{print "--------------------"}1' \ - ../../main/resources/sql/migrations/*.down.sql \ - ../../main/resources/sql/migrations/*.up.sql > ./allSQL.sql + ../../../main/resources/sql/migrations/*.down.sql \ + ../../../main/resources/sql/migrations/*.up.sql > ./allSQL.sql docker exec -i dc-project_postgresql_test psql test test -q -b -v "ON_ERROR_STOP=1" < ./allSQL.sql rm ./allSQL.sql ;; "All") echo "Start ALL tests" awk 'FNR==1{print "--------------------"}1' \ - ../../main/resources/sql/functions/*/*.sql \ + ../../../main/resources/sql/functions/*/*.sql \ ./fixtures/*.sql \ ./*.sql > ./allSQL.sql docker exec -i dc-project_postgresql_test psql test test -q -b -v "ON_ERROR_STOP=1" < ./allSQL.sql @@ -34,7 +34,7 @@ case $opt in *) echo "Start tests $opt" awk 'FNR==1{print "--------------------"}1' \ - ../../main/resources/sql/functions/*/*.sql \ + ../../../main/resources/sql/functions/*/*.sql \ ./fixtures/*.sql \ ./"$opt".sql > ./allSQL.sql docker exec -i dc-project_postgresql_test psql test test -q -b -v "ON_ERROR_STOP=1" < ./allSQL.sql