diff --git a/.idea/runConfigurations/All_Tests.xml b/.idea/runConfigurations/All_Tests___Lint.xml
similarity index 77%
rename from .idea/runConfigurations/All_Tests.xml
rename to .idea/runConfigurations/All_Tests___Lint.xml
index cf6510d..cf179d2 100644
--- a/.idea/runConfigurations/All_Tests.xml
+++ b/.idea/runConfigurations/All_Tests___Lint.xml
@@ -1,5 +1,5 @@
-
+
@@ -19,6 +19,7 @@
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/Cucumber_Tests.xml b/.idea/runConfigurations/Cucumber_Tests.xml
index b536641..a55a69e 100644
--- a/.idea/runConfigurations/Cucumber_Tests.xml
+++ b/.idea/runConfigurations/Cucumber_Tests.xml
@@ -1,10 +1,10 @@
-
+
-
+
diff --git a/.idea/runConfigurations/Lint.xml b/.idea/runConfigurations/Lint.xml
new file mode 100644
index 0000000..e320150
--- /dev/null
+++ b/.idea/runConfigurations/Lint.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
\ No newline at end of file
diff --git a/src/main/kotlin/fr/dcproject/Application.kt b/src/main/kotlin/fr/dcproject/Application.kt
index 38f9e50..6ed335d 100644
--- a/src/main/kotlin/fr/dcproject/Application.kt
+++ b/src/main/kotlin/fr/dcproject/Application.kt
@@ -8,10 +8,7 @@ import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.datatype.joda.JodaModule
import com.github.jasync.sql.db.postgresql.exceptions.GenericDatabaseException
import fr.dcproject.Env.PROD
-import fr.dcproject.entity.Article
-import fr.dcproject.entity.Citizen
-import fr.dcproject.entity.Constitution
-import fr.dcproject.entity.User
+import fr.dcproject.entity.*
import fr.dcproject.routes.*
import fr.dcproject.security.voter.*
import fr.postgresjson.migration.Migrations
@@ -80,9 +77,16 @@ fun Application.module(env: Env = PROD) {
// TODO: create generic convert for entityI
convert {
decode { values, _ ->
- val id = values.singleOrNull()?.let { UUID.fromString(it) }
- ?: throw InternalError("Cannot convert $values to UUID")
- get().findById(id) ?: throw InternalError("Article $values not found")
+ values.singleOrNull()?.let {
+ get().findById(UUID.fromString(it)) ?: throw InternalError("Article $values not found")
+ } ?: throw NotFoundException("Article $values not found")
+ }
+ }
+ convert {
+ decode { values, _ ->
+ values.singleOrNull()?.let {
+ ArticleRef(UUID.fromString(it))
+ } ?: throw NotFoundException("Article $values not found")
}
}
@@ -90,7 +94,7 @@ fun Application.module(env: Env = PROD) {
decode { values, _ ->
val id = values.singleOrNull()?.let { UUID.fromString(it) }
?: throw InternalError("Cannot convert $values to UUID")
- get().findById(id) ?: throw InternalError("Constitution $values not found")
+ get().findById(id) ?: throw NotFoundException("Constitution $values not found")
}
}
@@ -98,7 +102,7 @@ fun Application.module(env: Env = PROD) {
decode { values, _ ->
val id = values.singleOrNull()?.let { UUID.fromString(it) }
?: throw InternalError("Cannot convert $values to UUID")
- get().findById(id, true) ?: throw InternalError("Citizen $values not found")
+ get().findById(id, true) ?: throw NotFoundException("Citizen $values not found")
}
}
}
@@ -179,6 +183,9 @@ fun Application.module(env: Env = PROD) {
throw e
}
}
+ exception { e ->
+ call.respond(HttpStatusCode.BadRequest, e.message!!)
+ }
}
install(CORS) {
diff --git a/src/main/kotlin/fr/dcproject/ApplicationContext.kt b/src/main/kotlin/fr/dcproject/ApplicationContext.kt
index 66163c5..8d10d1c 100644
--- a/src/main/kotlin/fr/dcproject/ApplicationContext.kt
+++ b/src/main/kotlin/fr/dcproject/ApplicationContext.kt
@@ -1,5 +1,6 @@
package fr.dcproject
+import fr.dcproject.entity.UserI
import fr.dcproject.security.voter.ForbiddenException
import io.ktor.application.ApplicationCall
import io.ktor.auth.authentication
@@ -8,7 +9,6 @@ import io.ktor.util.pipeline.PipelineContext
import kotlinx.coroutines.runBlocking
import org.koin.core.context.GlobalContext
import fr.dcproject.entity.Citizen as CitizenEntity
-import fr.dcproject.entity.User as UserEntity
import fr.dcproject.repository.Citizen as CitizenRepository
private val citizenAttributeKey = AttributeKey("CitizenContext")
@@ -16,7 +16,7 @@ private val citizenAttributeKey = AttributeKey("CitizenContext")
val ApplicationCall.citizen: CitizenEntity
get() = attributes.computeIfAbsent(citizenAttributeKey) {
runBlocking {
- val user = authentication.principal() ?: throw ForbiddenException()
+ val user = authentication.principal() ?: throw ForbiddenException()
GlobalContext.get().koin.get().findByUser(user) ?: throw ForbiddenException("Citizen not found for this user id \"${user.id}\"")
}
}
diff --git a/src/main/kotlin/fr/dcproject/Configuration.kt b/src/main/kotlin/fr/dcproject/Configuration.kt
index 77641f5..7592600 100644
--- a/src/main/kotlin/fr/dcproject/Configuration.kt
+++ b/src/main/kotlin/fr/dcproject/Configuration.kt
@@ -4,7 +4,7 @@ import com.auth0.jwt.JWT
import com.auth0.jwt.JWTVerifier
import com.auth0.jwt.algorithms.Algorithm
import com.typesafe.config.ConfigFactory
-import fr.dcproject.entity.User
+import fr.dcproject.entity.UserI
import org.eclipse.jetty.util.resource.JarResource
import java.io.File
import java.util.*
@@ -46,7 +46,7 @@ object JwtConfig {
/**
* Produce a token for this combination of User and Account
*/
- fun makeToken(user: User): String = JWT.create()
+ fun makeToken(user: UserI): String = JWT.create()
.withSubject("Authentication")
.withIssuer(issuer)
.withClaim("id", user.id.toString())
diff --git a/src/main/kotlin/fr/dcproject/entity/Article.kt b/src/main/kotlin/fr/dcproject/entity/Article.kt
index b6e6183..ca8346b 100644
--- a/src/main/kotlin/fr/dcproject/entity/Article.kt
+++ b/src/main/kotlin/fr/dcproject/entity/Article.kt
@@ -1,26 +1,77 @@
package fr.dcproject.entity
-import fr.postgresjson.entity.mutable.*
+import fr.postgresjson.entity.immutable.*
+import fr.postgresjson.entity.mutable.EntityDeletedAt
+import fr.postgresjson.entity.mutable.EntityDeletedAtImp
+import fr.postgresjson.entity.mutable.EntityVersioning
+import fr.postgresjson.entity.mutable.UuidEntityVersioning
import java.util.*
class Article(
id: UUID = UUID.randomUUID(),
- var title: String?,
- var anonymous: Boolean? = true,
- var content: String?,
- var description: String?,
- var tags: List = emptyList(),
- var draft: Boolean = false,
- var lastVersion: Boolean = false,
- createdBy: Citizen?
-) :
- UuidEntity(id),
- EntityVersioning by UuidEntityVersioning(),
- EntityCreatedAt by EntityCreatedAtImp(),
- EntityCreatedBy by EntityCreatedByImp(createdBy),
- EntityDeletedAt by EntityDeletedAtImp(),
- Votable by VotableImp() {
+ title: String,
+ anonymous: Boolean = true,
+ content: String,
+ description: String,
+ tags: List = emptyList(),
+ override var draft: Boolean = false,
+ override var lastVersion: Boolean = false,
+ createdBy: CitizenBasic
+) : ArticleFull,
+ ArticleBasic(id, title, anonymous, content, description, tags, createdBy)
+
+open class ArticleBasic(
+ id: UUID = UUID.randomUUID(),
+ title: String,
+ override var anonymous: Boolean = true,
+ override var content: String,
+ override var description: String,
+ override var tags: List = emptyList(),
+ override val createdBy: CitizenBasic
+) : ArticleBasicI,
+ ArticleSimple(id, title, createdBy) {
init {
tags = tags.distinct()
}
-}
\ No newline at end of file
+}
+
+open class ArticleSimple(
+ id: UUID = UUID.randomUUID(),
+ override var title: String,
+ override val createdBy: CitizenBasic
+) : ArticleSimpleI,
+ ArticleRef(id),
+ EntityCreatedAt by EntityCreatedAtImp(),
+ EntityCreatedBy by EntityCreatedByImp(createdBy),
+ EntityDeletedAt by EntityDeletedAtImp(),
+ EntityVersioning by UuidEntityVersioning(),
+ Votable by VotableImp()
+
+open class ArticleRef(
+ id: UUID = UUID.randomUUID()
+) : ArticleI, TargetRef(id)
+
+interface ArticleI : UuidEntityI, TargetI
+
+interface ArticleSimpleI :
+ ArticleI,
+ EntityVersioning,
+ EntityCreatedBy,
+ EntityCreatedAt,
+ EntityDeletedAt,
+ Votable {
+ var title: String
+}
+interface ArticleBasicI :
+ ArticleSimpleI {
+ var anonymous: Boolean
+ var content: String
+ var description: String
+ var tags: List
+}
+
+interface ArticleFull :
+ ArticleBasicI {
+ var draft: Boolean
+ var lastVersion: Boolean
+}
diff --git a/src/main/kotlin/fr/dcproject/entity/Citizen.kt b/src/main/kotlin/fr/dcproject/entity/Citizen.kt
index bd21788..e60adab 100644
--- a/src/main/kotlin/fr/dcproject/entity/Citizen.kt
+++ b/src/main/kotlin/fr/dcproject/entity/Citizen.kt
@@ -1,24 +1,68 @@
package fr.dcproject.entity
-import fr.postgresjson.entity.mutable.*
+import fr.dcproject.entity.CitizenI.Name
+import fr.postgresjson.entity.immutable.EntityCreatedAt
+import fr.postgresjson.entity.immutable.EntityCreatedAtImp
+import fr.postgresjson.entity.immutable.UuidEntity
+import fr.postgresjson.entity.immutable.UuidEntityI
+import fr.postgresjson.entity.mutable.EntityDeletedAt
+import fr.postgresjson.entity.mutable.EntityDeletedAtImp
import org.joda.time.DateTime
import java.util.*
class Citizen(
id: UUID = UUID.randomUUID(),
- var name: Name?,
- var email: String?,
- var birthday: DateTime?,
- var userId: UUID? = null,
- var voteAnonymous: Boolean = true,
- var followAnonymous: Boolean = true,
- var user: User?
+ name: Name,
+ email: String,
+ birthday: DateTime,
+ voteAnonymous: Boolean = true,
+ followAnonymous: Boolean = true,
+ override val user: User
+) : CitizenFull,
+ CitizenBasic(id, name, email, birthday, voteAnonymous, followAnonymous, user),
+ EntityCreatedAt by EntityCreatedAtImp()
+
+open class CitizenBasic(
+ id: UUID = UUID.randomUUID(),
+ name: Name,
+ override var email: String,
+ override var birthday: DateTime,
+ override var voteAnonymous: Boolean = true,
+ override var followAnonymous: Boolean = true,
+ user: UserRef
+) : CitizenBasicI,
+ CitizenSimple(id, name, user)
+
+open class CitizenSimple(
+ id: UUID = UUID.randomUUID(),
+ var name: Name,
+ user: UserRef
+) : CitizenRef(id, user)
+
+open class CitizenRef(
+ id: UUID = UUID.randomUUID(),
+ open val user: UserRef
) : UuidEntity(id),
- EntityCreatedAt by EntityCreatedAtImp(),
- EntityDeletedAt by EntityDeletedAtImp() {
+ CitizenI,
+ EntityDeletedAt by EntityDeletedAtImp()
+
+interface CitizenI : UuidEntityI {
data class Name(
- var firstName: String?,
- var lastName: String?,
+ var firstName: String,
+ var lastName: String,
var civility: String? = null
)
-}
\ No newline at end of file
+}
+
+interface CitizenBasicI : CitizenI, EntityDeletedAt {
+ var name: Name
+ var email: String
+ var birthday: DateTime
+ var voteAnonymous: Boolean
+ var followAnonymous: Boolean
+ val user: UserI
+}
+
+interface CitizenFull : CitizenBasicI {
+ override val user: User
+}
diff --git a/src/main/kotlin/fr/dcproject/entity/Comment.kt b/src/main/kotlin/fr/dcproject/entity/Comment.kt
index 38cad45..f53dc1a 100644
--- a/src/main/kotlin/fr/dcproject/entity/Comment.kt
+++ b/src/main/kotlin/fr/dcproject/entity/Comment.kt
@@ -1,13 +1,15 @@
package fr.dcproject.entity
-import fr.postgresjson.entity.mutable.*
+import fr.postgresjson.entity.immutable.EntityUpdatedAt
+import fr.postgresjson.entity.immutable.EntityUpdatedAtImp
+import fr.postgresjson.entity.mutable.EntityDeletedAt
+import fr.postgresjson.entity.mutable.EntityDeletedAtImp
import java.util.*
-open class Comment (
+open class Comment(
id: UUID = UUID.randomUUID(),
- createdBy: Citizen,
+ override val createdBy: CitizenBasic,
target: T,
- override var targetReference: String = target::class.simpleName!!.toLowerCase(),
var content: String,
val responses: List>? = null,
var parent: Comment? = null,
@@ -16,17 +18,18 @@ open class Comment (
) : Extra(id, createdBy, target),
EntityUpdatedAt by EntityUpdatedAtImp(),
EntityDeletedAt by EntityDeletedAtImp(),
- Votable by VotableImp()
-{
+ Votable by VotableImp(),
+ TargetI {
constructor(
- createdBy: Citizen,
+ createdBy: CitizenBasic,
parent: Comment,
content: String
) : this(
createdBy = createdBy,
parent = parent,
target = parent.target,
- targetReference = parent.targetReference,
content = content
)
+
+ override val reference get() = TargetI.getReference(this)
}
diff --git a/src/main/kotlin/fr/dcproject/entity/Constitution.kt b/src/main/kotlin/fr/dcproject/entity/Constitution.kt
index cd1bf34..1f51674 100644
--- a/src/main/kotlin/fr/dcproject/entity/Constitution.kt
+++ b/src/main/kotlin/fr/dcproject/entity/Constitution.kt
@@ -1,36 +1,69 @@
package fr.dcproject.entity
-import fr.postgresjson.entity.mutable.*
+import fr.postgresjson.entity.immutable.*
+import fr.postgresjson.entity.mutable.EntityDeletedAt
+import fr.postgresjson.entity.mutable.EntityDeletedAtImp
import java.util.*
class Constitution(
id: UUID = UUID.randomUUID(),
- var title: String?,
- var anonymous: Boolean? = true,
- var titles: List = listOf(),
+ title: String,
+ anonymous: Boolean = true,
+ titles: MutableList> = mutableListOf(),
+ draft: Boolean = false,
+ lastVersion: Boolean = false,
+ override val createdBy: CitizenSimple
+) : ConstitutionSimple>(
+ id,
+ title = title,
+ anonymous = anonymous,
+ titles = titles,
+ draft = draft,
+ lastVersion = lastVersion,
+ createdBy = createdBy
+) {
+
+ class Title(
+ id: UUID = UUID.randomUUID(),
+ name: String,
+ rank: Int? = null,
+ override val articles: MutableList = mutableListOf()
+ ) : ConstitutionSimple.TitleSimple(id, name, rank)
+}
+
+open class ConstitutionSimple>(
+ id: UUID = UUID.randomUUID(),
+ var title: String,
+ var anonymous: Boolean = true,
+ open var titles: MutableList = mutableListOf(),
var draft: Boolean = false,
var lastVersion: Boolean = false,
- createdBy: Citizen?
-) : UuidEntity(id),
- EntityVersioning by UuidEntityVersioning(),
+ override val createdBy: Cr,
+ versionId: UUID = UUID.randomUUID()
+) : ConstitutionRef(id),
+ EntityVersioning by UuidEntityVersioning(versionId = versionId),
EntityCreatedAt by EntityCreatedAtImp(),
- EntityCreatedBy by EntityCreatedByImp(createdBy),
+ EntityCreatedBy by EntityCreatedByImp(createdBy),
EntityDeletedAt by EntityDeletedAtImp() {
init {
titles.forEachIndexed { index, title ->
- title.createdBy = this.createdBy
title.rank = index
}
}
- class Title(
+ open class TitleSimple(
id: UUID = UUID.randomUUID(),
- var name: String?,
+ var name: String,
var rank: Int? = null,
- var articles: List = listOf(),
- createdBy: Citizen? = null
- ) : UuidEntity(id),
- EntityCreatedAt by EntityCreatedAtImp(),
- EntityCreatedBy by EntityCreatedByImp(createdBy)
+ open val articles: MutableList = mutableListOf()
+ ) : TitleRef(id)
}
+
+open class ConstitutionRef(id: UUID = UUID.randomUUID()) : ConstitutionS(id) {
+ open class TitleRef(
+ id: UUID = UUID.randomUUID()
+ ) : UuidEntity(id)
+}
+
+sealed class ConstitutionS(id: UUID = UUID.randomUUID()) : TargetRef(id), TargetI
\ No newline at end of file
diff --git a/src/main/kotlin/fr/dcproject/entity/Extra.kt b/src/main/kotlin/fr/dcproject/entity/Extra.kt
index 11b67b2..1c69c43 100644
--- a/src/main/kotlin/fr/dcproject/entity/Extra.kt
+++ b/src/main/kotlin/fr/dcproject/entity/Extra.kt
@@ -1,24 +1,62 @@
package fr.dcproject.entity
-import fr.postgresjson.entity.EntityI
-import fr.postgresjson.entity.mutable.*
+import fr.postgresjson.entity.immutable.*
import java.util.*
+import kotlin.reflect.KClass
+import kotlin.reflect.full.isSuperclassOf
-interface ExtraI :
- EntityI,
+interface ExtraI :
+ UuidEntityI,
EntityCreatedAt,
- EntityCreatedBy {
+ EntityCreatedBy {
var target: T
- var targetReference: String
}
-abstract class Extra(
- id: UUID? = UUID.randomUUID(),
- createdBy: Citizen,
- override var target: T,
- override var targetReference: String = target::class.simpleName!!.toLowerCase()
+abstract class Extra(
+ id: UUID = UUID.randomUUID(),
+ override val createdBy: CitizenBasic,
+ override var target: T
) :
ExtraI,
UuidEntity(id),
EntityCreatedAt by EntityCreatedAtImp(),
- EntityCreatedBy by EntityCreatedByImp(createdBy)
\ No newline at end of file
+ EntityCreatedBy by EntityCreatedByImp(createdBy)
+
+open class TargetRef(id: UUID = UUID.randomUUID()) : TargetI, UuidEntity(id) {
+ override val reference: String = ""
+ get() {
+ return if (field != "") field else TargetI.getReference(this)
+ }
+}
+
+interface TargetI : UuidEntityI {
+ enum class TargetName(val targetReference: String) {
+ Article("article"),
+ Constitution("constitution"),
+ Comment("comment")
+ }
+
+ companion object {
+ fun getReference(t: KClass): String {
+ return when {
+ t.isSuperclassOf(Article::class) -> TargetName.Article.targetReference
+ t.isSuperclassOf(Constitution::class) -> TargetName.Constitution.targetReference
+ t.isSuperclassOf(Comment::class) -> TargetName.Comment.targetReference
+ else -> throw error("target not implemented")
+ }
+ }
+
+ fun getReference(t: TargetI): String {
+ val ref = this.getReference(t::class)
+ return if (t is ExtraI<*>) {
+ ref +
+ "_on_" +
+ t.target.reference
+ } else {
+ ref
+ }
+ }
+ }
+
+ val reference: String
+}
\ No newline at end of file
diff --git a/src/main/kotlin/fr/dcproject/entity/Follow.kt b/src/main/kotlin/fr/dcproject/entity/Follow.kt
index 993aa1d..e2d88a6 100644
--- a/src/main/kotlin/fr/dcproject/entity/Follow.kt
+++ b/src/main/kotlin/fr/dcproject/entity/Follow.kt
@@ -1,9 +1,8 @@
package fr.dcproject.entity
-import fr.postgresjson.entity.mutable.UuidEntity
import java.util.*
-class Follow (
+class Follow (
id: UUID = UUID.randomUUID(),
- createdBy: Citizen,
+ override val createdBy: CitizenBasic,
target: T
) : Extra(id, createdBy, target)
diff --git a/src/main/kotlin/fr/dcproject/entity/User.kt b/src/main/kotlin/fr/dcproject/entity/User.kt
index 7727b3f..6e1beba 100644
--- a/src/main/kotlin/fr/dcproject/entity/User.kt
+++ b/src/main/kotlin/fr/dcproject/entity/User.kt
@@ -1,19 +1,41 @@
package fr.dcproject.entity
-import fr.postgresjson.entity.mutable.*
+import fr.dcproject.entity.UserI.Roles
+import fr.postgresjson.entity.immutable.*
import io.ktor.auth.Principal
import org.joda.time.DateTime
import java.util.*
class User(
- id: UUID? = UUID.randomUUID(),
- var username: String?,
- var blockedAt: DateTime? = null,
- var plainPassword: String?,
- var roles: List = emptyList()
-) : UuidEntity(id),
+ id: UUID = UUID.randomUUID(),
+ username: String,
+ blockedAt: DateTime? = null,
+ override var plainPassword: String?,
+ override var roles: List = emptyList()
+) : UserFull, UserBasic(id, username, blockedAt),
EntityCreatedAt by EntityCreatedAtImp(),
- EntityUpdatedAt by EntityUpdatedAtImp(),
- Principal {
+ EntityUpdatedAt by EntityUpdatedAtImp()
+
+open class UserBasic(
+ id: UUID = UUID.randomUUID(),
+ override var username: String,
+ override var blockedAt: DateTime? = null
+) : UserBasicI, UserRef(id)
+
+open class UserRef(
+ id: UUID = UUID.randomUUID()
+) : UserI, UuidEntity(id)
+
+interface UserI : UuidEntityI, Principal {
enum class Roles { ROLE_USER, ROLE_ADMIN }
}
+
+interface UserBasicI : UserI {
+ var username: String
+ var blockedAt: DateTime?
+}
+
+interface UserFull : UserBasicI, EntityCreatedAt, EntityUpdatedAt {
+ var plainPassword: String?
+ var roles: List
+}
diff --git a/src/main/kotlin/fr/dcproject/entity/Vote.kt b/src/main/kotlin/fr/dcproject/entity/Vote.kt
index ee5e245..8b952c8 100644
--- a/src/main/kotlin/fr/dcproject/entity/Vote.kt
+++ b/src/main/kotlin/fr/dcproject/entity/Vote.kt
@@ -1,13 +1,12 @@
package fr.dcproject.entity
-import fr.postgresjson.entity.mutable.EntityUpdatedAt
-import fr.postgresjson.entity.mutable.EntityUpdatedAtImp
-import fr.postgresjson.entity.mutable.UuidEntity
+import fr.postgresjson.entity.immutable.EntityUpdatedAt
+import fr.postgresjson.entity.immutable.EntityUpdatedAtImp
import java.util.*
-open class Vote (
+open class Vote (
id: UUID = UUID.randomUUID(),
- createdBy: Citizen,
+ override val createdBy: CitizenBasic,
target: T,
var note: Int,
var anonymous: Boolean = true
diff --git a/src/main/kotlin/fr/dcproject/entity/request/Article.kt b/src/main/kotlin/fr/dcproject/entity/request/Article.kt
index 7d98903..aab01ab 100644
--- a/src/main/kotlin/fr/dcproject/entity/request/Article.kt
+++ b/src/main/kotlin/fr/dcproject/entity/request/Article.kt
@@ -1,5 +1,6 @@
package fr.dcproject.entity.request
+import fr.dcproject.entity.ArticleFull
import fr.dcproject.entity.Citizen
import java.util.*
import fr.dcproject.entity.Article as ArticleEntity
@@ -7,7 +8,7 @@ import fr.dcproject.entity.Article as ArticleEntity
class Article(
val id: UUID?,
val title: String,
- val anonymous: Boolean? = true,
+ val anonymous: Boolean = true,
val content: String,
val description: String,
val tags: List = emptyList(),
@@ -16,7 +17,7 @@ class Article(
) :
Request {
- fun merge(article: ArticleEntity) {
+ fun merge(article: ArticleFull) {
article.title = this.title
article.content = this.content
article.description = this.description
diff --git a/src/main/kotlin/fr/dcproject/entity/request/Constitution.kt b/src/main/kotlin/fr/dcproject/entity/request/Constitution.kt
new file mode 100644
index 0000000..81c176d
--- /dev/null
+++ b/src/main/kotlin/fr/dcproject/entity/request/Constitution.kt
@@ -0,0 +1,48 @@
+package fr.dcproject.entity.request
+
+import fr.dcproject.entity.ArticleRef
+import fr.dcproject.entity.Citizen
+import fr.dcproject.entity.CitizenSimple
+import fr.dcproject.entity.ConstitutionSimple
+import fr.postgresjson.entity.immutable.UuidEntity
+import java.util.*
+
+class Constitution(
+ var title: String,
+ var anonymous: Boolean = true,
+ var titles: MutableList = mutableListOf(),
+ var draft: Boolean = false,
+ var lastVersion: Boolean = false,
+ var versionId: UUID = UUID.randomUUID()
+) {
+ init {
+ titles.forEachIndexed { index, title ->
+ title.rank = index
+ }
+ }
+
+ class Title(
+ id: UUID = UUID.randomUUID(),
+ var name: String,
+ var rank: Int? = null,
+ var articles: MutableList = mutableListOf()
+ ) : UuidEntity(id) {
+ fun create(): ConstitutionSimple.TitleSimple {
+ return ConstitutionSimple.TitleSimple(
+ id, name, rank, articles
+ )
+ }
+ }
+
+ fun create(createdBy: Citizen): ConstitutionSimple> {
+ return ConstitutionSimple(
+ title = title,
+ titles = titles.create(),
+ createdBy = createdBy,
+ versionId = versionId
+ )
+ }
+}
+
+fun List.create(): MutableList> =
+ map { it.create() }.toMutableList()
\ No newline at end of file
diff --git a/src/main/kotlin/fr/dcproject/messages/SsoManager.kt b/src/main/kotlin/fr/dcproject/messages/SsoManager.kt
index a02c959..c950a2b 100644
--- a/src/main/kotlin/fr/dcproject/messages/SsoManager.kt
+++ b/src/main/kotlin/fr/dcproject/messages/SsoManager.kt
@@ -4,8 +4,8 @@ import com.sendgrid.helpers.mail.Mail
import com.sendgrid.helpers.mail.objects.Content
import com.sendgrid.helpers.mail.objects.Email
import fr.dcproject.JwtConfig
+import fr.dcproject.entity.CitizenBasicI
import io.ktor.http.URLBuilder
-import fr.dcproject.entity.Citizen as CitizenEntity
import fr.dcproject.repository.Citizen as CitizenRepository
class SsoManager(
@@ -15,11 +15,15 @@ class SsoManager(
) {
fun sendMail(email: String, url: String) {
val citizen = citizenRepo.findByEmail(email) ?: noEmail(email)
+ sendMail(citizen, url)
+ }
+
+ fun sendMail(citizen: CitizenBasicI, url: String) {
mailer.sendEmail {
Mail(
Email("sso@$domain"),
"Connection",
- Email(email),
+ Email(citizen.email),
Content("text/plain", generateContent(citizen, url))
).apply {
addContent(Content("text/html", generateHtmlContent(citizen, url)))
@@ -27,15 +31,15 @@ class SsoManager(
}
}
- private fun generateHtmlContent(citizen: CitizenEntity, url: String): String? {
+ private fun generateHtmlContent(citizen: CitizenBasicI, url: String): String? {
val urlObject = URLBuilder(url)
- urlObject.parameters.append("token", JwtConfig.makeToken(citizen.user ?: error("Citizen must have User")))
+ urlObject.parameters.append("token", JwtConfig.makeToken(citizen.user))
return "Click here for connect to $domain"
}
- private fun generateContent(citizen: CitizenEntity, url: String): String {
+ private fun generateContent(citizen: CitizenBasicI, url: String): String {
val urlObject = URLBuilder(url)
- urlObject.parameters.append("token", JwtConfig.makeToken(citizen.user ?: error("Citizen must have User")))
+ urlObject.parameters.append("token", JwtConfig.makeToken(citizen.user))
return "Copy this link into your browser for connect to $domain: \n${urlObject.buildString()}"
}
diff --git a/src/main/kotlin/fr/dcproject/repository/Article.kt b/src/main/kotlin/fr/dcproject/repository/Article.kt
index 315d6a4..b405cff 100644
--- a/src/main/kotlin/fr/dcproject/repository/Article.kt
+++ b/src/main/kotlin/fr/dcproject/repository/Article.kt
@@ -1,5 +1,7 @@
package fr.dcproject.repository
+import fr.dcproject.entity.ArticleFull
+import fr.dcproject.entity.ArticleSimple
import fr.postgresjson.connexion.Paginated
import fr.postgresjson.connexion.Requester
import fr.postgresjson.entity.Parameter
@@ -28,7 +30,7 @@ class Article(override var requester: Requester) : RepositoryI {
direction: Direction? = null,
search: String? = null,
filter: Filter = Filter()
- ): Paginated {
+ ): Paginated {
return requester
.getFunction("find_articles")
.select(
@@ -40,7 +42,7 @@ class Article(override var requester: Requester) : RepositoryI {
)
}
- fun upsert(article: ArticleEntity): ArticleEntity? {
+ fun upsert(article: ArticleFull): ArticleEntity? {
return requester
.getFunction("upsert_article")
.selectOne("resource" to article)
diff --git a/src/main/kotlin/fr/dcproject/repository/Citizen.kt b/src/main/kotlin/fr/dcproject/repository/Citizen.kt
index f8d0452..22d5485 100644
--- a/src/main/kotlin/fr/dcproject/repository/Citizen.kt
+++ b/src/main/kotlin/fr/dcproject/repository/Citizen.kt
@@ -1,5 +1,8 @@
package fr.dcproject.repository
+import fr.dcproject.entity.CitizenBasic
+import fr.dcproject.entity.CitizenFull
+import fr.dcproject.entity.UserI
import fr.postgresjson.connexion.Paginated
import fr.postgresjson.connexion.Requester
import fr.postgresjson.repository.RepositoryI
@@ -7,7 +10,6 @@ import fr.postgresjson.repository.RepositoryI.Direction
import net.pearx.kasechange.toSnakeCase
import java.util.*
import fr.dcproject.entity.Citizen as CitizenEntity
-import fr.dcproject.entity.User as UserEntity
class Citizen(override var requester: Requester) : RepositoryI {
fun findById(id: UUID, withUser: Boolean = false): CitizenEntity? {
@@ -16,7 +18,7 @@ class Citizen(override var requester: Requester) : RepositoryI {
.selectOne("id" to id)
}
- fun findByUser(user: UserEntity): CitizenEntity? {
+ fun findByUser(user: UserI): CitizenEntity? {
return requester
.getFunction("find_citizen_by_user_id")
.selectOne("user_id" to user.id)
@@ -40,7 +42,7 @@ class Citizen(override var requester: Requester) : RepositoryI {
sort: String? = null,
direction: Direction? = null,
search: String? = null
- ): Paginated {
+ ): Paginated {
return requester
.getFunction("find_citizens")
.select(
@@ -51,13 +53,13 @@ class Citizen(override var requester: Requester) : RepositoryI {
)
}
- fun upsert(citizen: CitizenEntity): CitizenEntity? {
+ fun upsert(citizen: CitizenFull): CitizenEntity? {
return requester
.getFunction("upsert_citizen")
.selectOne("resource" to citizen)
}
- fun insertWithUser(citizen: CitizenEntity): CitizenEntity? {
+ fun insertWithUser(citizen: CitizenFull): CitizenEntity? {
return requester
.getFunction("insert_citizen_with_user")
.selectOne("resource" to citizen)
diff --git a/src/main/kotlin/fr/dcproject/repository/Comment.kt b/src/main/kotlin/fr/dcproject/repository/Comment.kt
index 60650aa..f5b6b5b 100644
--- a/src/main/kotlin/fr/dcproject/repository/Comment.kt
+++ b/src/main/kotlin/fr/dcproject/repository/Comment.kt
@@ -1,16 +1,18 @@
package fr.dcproject.repository
+import fr.dcproject.entity.ArticleRef
+import fr.dcproject.entity.TargetI
+import fr.dcproject.entity.TargetRef
import fr.postgresjson.connexion.Paginated
import fr.postgresjson.connexion.Requester
-import fr.postgresjson.entity.mutable.UuidEntity
+import fr.postgresjson.entity.immutable.UuidEntityI
import fr.postgresjson.repository.RepositoryI
import java.util.*
-import fr.dcproject.entity.Article as ArticleEntity
import fr.dcproject.entity.Citizen as CitizenEntity
import fr.dcproject.entity.Comment as CommentEntity
import fr.dcproject.entity.Constitution as ConstitutionEntity
-abstract class Comment (override var requester: Requester) : RepositoryI {
+abstract class Comment (override var requester: Requester) : RepositoryI {
abstract fun findById(id: UUID): CommentEntity?
abstract fun findByCitizen(
@@ -24,7 +26,7 @@ abstract class Comment (override var requester: Requester) : Rep
page: Int = 1,
limit: Int = 50
): Paginated> {
- return findByParent(parent.id ?: error("comment must have an ID"), page, limit)
+ return findByParent(parent.id, page, limit)
}
open fun findByParent(
@@ -41,11 +43,11 @@ abstract class Comment (override var requester: Requester) : Rep
}
open fun findByTarget(
- target: UuidEntity,
+ target: UuidEntityI,
page: Int = 1,
limit: Int = 50
): Paginated> {
- return findByTarget(target.id ?: error("comment must have an ID"), page, limit)
+ return findByTarget(target.id, page, limit)
}
open fun findByTarget(
@@ -65,7 +67,7 @@ abstract class Comment (override var requester: Requester) : Rep
requester
.getFunction("comment")
.sendQuery(
- "reference" to comment.targetReference,
+ "reference" to comment.target.reference,
"resource" to comment
)
}
@@ -80,8 +82,8 @@ abstract class Comment (override var requester: Requester) : Rep
}
}
-class CommentGeneric(requester: Requester) : Comment(requester) {
- override fun findById(id: UUID): CommentEntity? {
+class CommentGeneric(requester: Requester) : Comment(requester) {
+ override fun findById(id: UUID): CommentEntity? {
return requester
.getFunction("find_comment_by_id")
.selectOne(mapOf("id" to id))
@@ -91,7 +93,7 @@ class CommentGeneric(requester: Requester) : Comment(requester) {
citizen: CitizenEntity,
page: Int,
limit: Int
- ): Paginated> {
+ ): Paginated> {
return requester.run {
getFunction("find_comments_by_citizen")
.select(page, limit,
@@ -101,8 +103,8 @@ class CommentGeneric(requester: Requester) : Comment(requester) {
}
}
-class CommentArticle(requester: Requester) : Comment(requester) {
- override fun findById(id: UUID): CommentEntity? {
+class CommentArticle(requester: Requester) : Comment(requester) {
+ override fun findById(id: UUID): CommentEntity? {
return requester
.getFunction("find_comment_by_id")
.selectOne(mapOf("id" to id))
@@ -112,13 +114,12 @@ class CommentArticle(requester: Requester) : Comment(requester) {
citizen: CitizenEntity,
page: Int,
limit: Int
- ): Paginated> {
- val reference = ArticleEntity::class.simpleName!!.toLowerCase()
+ ): Paginated> {
return requester.run {
getFunction("find_comments_by_citizen")
.select(page, limit,
"created_by_id" to citizen.id,
- "reference" to reference
+ "reference" to TargetI.getReference(ArticleRef::class)
)
}
}
@@ -136,12 +137,11 @@ class CommentConstitution(requester: Requester) : Comment(re
page: Int,
limit: Int
): Paginated> {
- val reference = ConstitutionEntity::class.simpleName!!.toLowerCase()
return requester.run {
getFunction("find_comments_by_citizen")
.select(page, limit,
"created_by_id" to citizen.id,
- "reference" to reference
+ "reference" to TargetI.getReference(ConstitutionEntity::class)
)
}
}
diff --git a/src/main/kotlin/fr/dcproject/repository/Constitution.kt b/src/main/kotlin/fr/dcproject/repository/Constitution.kt
index 3bdecae..8cf812c 100644
--- a/src/main/kotlin/fr/dcproject/repository/Constitution.kt
+++ b/src/main/kotlin/fr/dcproject/repository/Constitution.kt
@@ -1,5 +1,8 @@
package fr.dcproject.repository
+import fr.dcproject.entity.ArticleRef
+import fr.dcproject.entity.CitizenSimple
+import fr.dcproject.entity.ConstitutionSimple
import fr.postgresjson.connexion.Paginated
import fr.postgresjson.connexion.Requester
import fr.postgresjson.repository.RepositoryI
@@ -31,7 +34,7 @@ class Constitution(override var requester: Requester) : RepositoryI {
)
}
- fun upsert(constitution: ConstitutionEntity): ConstitutionEntity? {
+ fun upsert(constitution: ConstitutionSimple>): ConstitutionEntity? {
return requester
.getFunction("upsert_constitution")
.selectOne("resource" to constitution)
diff --git a/src/main/kotlin/fr/dcproject/repository/Follow.kt b/src/main/kotlin/fr/dcproject/repository/Follow.kt
index 8badf33..7b6a0b1 100644
--- a/src/main/kotlin/fr/dcproject/repository/Follow.kt
+++ b/src/main/kotlin/fr/dcproject/repository/Follow.kt
@@ -1,22 +1,22 @@
package fr.dcproject.repository
+import fr.dcproject.entity.CitizenI
+import fr.dcproject.entity.TargetI
import fr.postgresjson.connexion.Paginated
import fr.postgresjson.connexion.Requester
-import fr.postgresjson.entity.mutable.UuidEntity
import fr.postgresjson.repository.RepositoryI
import java.util.*
import fr.dcproject.entity.Article as ArticleEntity
-import fr.dcproject.entity.Citizen as CitizenEntity
import fr.dcproject.entity.Constitution as ConstitutionEntity
import fr.dcproject.entity.Follow as FollowEntity
-open class Follow (override var requester: Requester) : RepositoryI {
+open class Follow (override var requester: Requester) : RepositoryI {
open fun findByCitizen(
- citizen: CitizenEntity,
+ citizen: CitizenI,
page: Int = 1,
limit: Int = 50
): Paginated> =
- findByCitizen(citizen.id ?: error("The citizen must have an id"), page, limit)
+ findByCitizen(citizen.id, page, limit)
open fun findByCitizen(
citizenId: UUID,
@@ -32,24 +32,22 @@ open class Follow (override var requester: Requester) : Reposito
}
fun follow(follow: FollowEntity) {
- val reference = follow.target::class.simpleName!!.toLowerCase()
requester
.getFunction("follow")
.sendQuery(
- "reference" to reference,
+ "reference" to follow.target.reference,
"target_id" to follow.target.id,
- "created_by_id" to follow.createdBy?.id
+ "created_by_id" to follow.createdBy.id
)
}
fun unfollow(follow: FollowEntity) {
- val reference = follow.target::class.simpleName!!.toLowerCase()
requester
.getFunction("unfollow")
.sendQuery(
- "reference" to reference,
+ "reference" to follow.target.reference,
"target_id" to follow.target.id,
- "created_by_id" to follow.createdBy?.id
+ "created_by_id" to follow.createdBy.id
)
}
}
diff --git a/src/main/kotlin/fr/dcproject/repository/User.kt b/src/main/kotlin/fr/dcproject/repository/User.kt
index 388e2ef..b76129d 100644
--- a/src/main/kotlin/fr/dcproject/repository/User.kt
+++ b/src/main/kotlin/fr/dcproject/repository/User.kt
@@ -1,5 +1,6 @@
package fr.dcproject.repository
+import fr.dcproject.entity.UserFull
import fr.postgresjson.connexion.Requester
import fr.postgresjson.repository.RepositoryI
import io.ktor.auth.UserPasswordCredential
@@ -30,7 +31,7 @@ class User(override var requester: Requester) : RepositoryI {
.selectOne("resource" to user)
}
- fun changePassword(user: UserEntity) {
+ fun changePassword(user: UserFull) {
requester
.getFunction("change_user_password")
.sendQuery("resource" to user)
diff --git a/src/main/kotlin/fr/dcproject/repository/Vote.kt b/src/main/kotlin/fr/dcproject/repository/Vote.kt
index bf67523..7307cbd 100644
--- a/src/main/kotlin/fr/dcproject/repository/Vote.kt
+++ b/src/main/kotlin/fr/dcproject/repository/Vote.kt
@@ -1,34 +1,25 @@
package fr.dcproject.repository
import com.fasterxml.jackson.core.type.TypeReference
+import fr.dcproject.entity.*
import fr.dcproject.entity.Article
import fr.dcproject.entity.Comment
import fr.dcproject.entity.Constitution
-import fr.dcproject.entity.VoteAggregation
import fr.postgresjson.connexion.Paginated
import fr.postgresjson.connexion.Requester
-import fr.postgresjson.entity.mutable.UuidEntity
import fr.postgresjson.repository.RepositoryI
import java.util.*
import fr.dcproject.entity.Citizen as CitizenEntity
import fr.dcproject.entity.Vote as VoteEntity
-open class Vote (override var requester: Requester) : RepositoryI {
+open class Vote (override var requester: Requester) : RepositoryI {
fun vote(vote: VoteEntity): VoteAggregation {
- val target = vote.target
- val reference = if (target is Comment<*>) {
- target::class.simpleName!!.toLowerCase() +
- "_on_" +
- target.targetReference
- } else {
- target::class.simpleName!!.toLowerCase()
- }
- val author = vote.createdBy ?: error("vote must be contain an author")
+ val author = vote.createdBy
val anonymous = author.voteAnonymous
return requester
.getFunction("vote")
.selectOne(
- "reference" to reference,
+ "reference" to vote.target.reference,
"target_id" to vote.target.id,
"note" to vote.note,
"created_by_id" to author.id,
@@ -56,12 +47,11 @@ open class Vote (override var requester: Requester) : Repository
citizen: CitizenEntity,
targets: List
): List> {
- val typeReference = object : TypeReference>>() {}
+ val typeReference = object : TypeReference>>() {}
return requester.run {
- val citizenId = citizen.id ?: error("The citizen must have an id")
getFunction("find_citizen_votes_by_target_ids")
.select(typeReference, mapOf(
- "citizen_id" to citizenId,
+ "citizen_id" to citizen.id,
"ids" to targets
))
}
@@ -75,7 +65,7 @@ class VoteArticle(requester: Requester) : Vote(requester) {
limit: Int = 50
): Paginated> =
findByCitizen(
- citizen.id ?: error("The citizen must have an id"),
+ citizen.id,
"article",
object : TypeReference>>() {},
page,
@@ -90,7 +80,7 @@ class VoteArticleComment(requester: Requester) : Vote>(requeste
limit: Int = 50
): Paginated>> =
findByCitizen(
- citizen.id ?: error("The citizen must have an id"),
+ citizen.id,
"article",
object : TypeReference>>>() {},
page,
@@ -98,16 +88,16 @@ class VoteArticleComment(requester: Requester) : Vote>(requeste
)
}
-class VoteComment(requester: Requester) : Vote>(requester) {
+class VoteComment(requester: Requester) : Vote>(requester) {
fun findByCitizen(
citizen: CitizenEntity,
page: Int = 1,
limit: Int = 50
- ): Paginated>> =
+ ): Paginated>> =
findByCitizen(
- citizen.id ?: error("The citizen must have an id"),
+ citizen.id,
"article",
- object : TypeReference>>>() {},
+ object : TypeReference>>>() {},
page,
limit
)
@@ -120,7 +110,7 @@ class VoteConstitution(requester: Requester) : Vote(requester) {
limit: Int = 50
): Paginated> =
findByCitizen(
- citizen.id ?: error("The citizen must have an id"),
+ citizen.id,
"constitution",
object : TypeReference>>() {},
page,
diff --git a/src/main/kotlin/fr/dcproject/routes/Auth.kt b/src/main/kotlin/fr/dcproject/routes/Auth.kt
index ea9e494..ad10b76 100644
--- a/src/main/kotlin/fr/dcproject/routes/Auth.kt
+++ b/src/main/kotlin/fr/dcproject/routes/Auth.kt
@@ -1,8 +1,9 @@
package fr.dcproject.routes
import com.fasterxml.jackson.databind.exc.MismatchedInputException
+import com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException
import fr.dcproject.JwtConfig
-import fr.dcproject.entity.User
+import fr.dcproject.entity.UserI.Roles.ROLE_USER
import fr.dcproject.messages.SsoManager
import fr.dcproject.routes.AuthPaths.LoginRequest
import fr.dcproject.routes.AuthPaths.RegisterRequest
@@ -52,12 +53,14 @@ fun Route.auth(
}
post {
- val citizen = call.receive()
- citizen.user?.roles = listOf(User.Roles.ROLE_USER)
- // TODO implement with validator
- citizen.email ?: throw BadRequestException("Bad request")
- val created = citizenRepo.insertWithUser(citizen)?.user ?: throw BadRequestException("Bad request")
- call.respondText(JwtConfig.makeToken(created))
+ try {
+ val citizen = call.receive()
+ citizen.user.roles = listOf(ROLE_USER)
+ val created = citizenRepo.insertWithUser(citizen)?.user ?: throw BadRequestException("Bad request")
+ call.respondText(JwtConfig.makeToken(created))
+ } catch (e: MissingKotlinParameterException) {
+ call.respond(HttpStatusCode.BadRequest)
+ }
}
post {
diff --git a/src/main/kotlin/fr/dcproject/routes/Citizen.kt b/src/main/kotlin/fr/dcproject/routes/Citizen.kt
index c035574..c4644d2 100644
--- a/src/main/kotlin/fr/dcproject/routes/Citizen.kt
+++ b/src/main/kotlin/fr/dcproject/routes/Citizen.kt
@@ -62,7 +62,7 @@ fun Route.citizen(
assertCan(CHANGE_PASSWORD, it.citizen)
val content = call.receive()
- val user = it.citizen.user ?: error("Citizen must have User")
+ val user = it.citizen.user
user.plainPassword = content.password
userRepository.changePassword(user)
diff --git a/src/main/kotlin/fr/dcproject/routes/Comment.kt b/src/main/kotlin/fr/dcproject/routes/Comment.kt
index e866e7e..beeaefb 100644
--- a/src/main/kotlin/fr/dcproject/routes/Comment.kt
+++ b/src/main/kotlin/fr/dcproject/routes/Comment.kt
@@ -73,7 +73,6 @@ fun Route.comment(repo: CommentRepository) {
assertCan(CREATE, newComment)
repo.comment(newComment)
-
call.respond(HttpStatusCode.Created, newComment)
}
@@ -86,4 +85,4 @@ fun Route.comment(repo: CommentRepository) {
call.respond(HttpStatusCode.OK, comment)
}
-}
\ No newline at end of file
+}
diff --git a/src/main/kotlin/fr/dcproject/routes/CommentArticle.kt b/src/main/kotlin/fr/dcproject/routes/CommentArticle.kt
index dd7e268..8dc12d9 100644
--- a/src/main/kotlin/fr/dcproject/routes/CommentArticle.kt
+++ b/src/main/kotlin/fr/dcproject/routes/CommentArticle.kt
@@ -1,6 +1,7 @@
package fr.dcproject.routes
import fr.dcproject.citizen
+import fr.dcproject.entity.ArticleRef
import fr.dcproject.entity.Citizen
import fr.dcproject.security.voter.CommentVoter.Action.CREATE
import fr.dcproject.security.voter.CommentVoter.Action.VIEW
@@ -14,7 +15,6 @@ import io.ktor.locations.post
import io.ktor.request.receive
import io.ktor.response.respond
import io.ktor.routing.Route
-import fr.dcproject.entity.Article as ArticleEntity
import fr.dcproject.entity.Comment as CommentEntity
import fr.dcproject.entity.request.Comment as CommentEntityRequest
import fr.dcproject.repository.CommentArticle as CommentArticleRepository
@@ -23,7 +23,7 @@ import fr.dcproject.repository.CommentArticle as CommentArticleRepository
object CommentArticlePaths {
@Location("/articles/{article}/comments")
class ArticleCommentRequest(
- val article: ArticleEntity,
+ val article: ArticleRef,
page: Int = 1,
limit: Int = 50,
val search: String? = null
diff --git a/src/main/kotlin/fr/dcproject/routes/Constitution.kt b/src/main/kotlin/fr/dcproject/routes/Constitution.kt
index 2f9ef7d..3996a03 100644
--- a/src/main/kotlin/fr/dcproject/routes/Constitution.kt
+++ b/src/main/kotlin/fr/dcproject/routes/Constitution.kt
@@ -1,6 +1,7 @@
package fr.dcproject.routes
import fr.dcproject.citizen
+import fr.dcproject.entity.request.Constitution
import fr.dcproject.security.voter.ConstitutionVoter.Action.CREATE
import fr.dcproject.security.voter.ConstitutionVoter.Action.VIEW
import fr.dcproject.security.voter.assertCan
@@ -41,8 +42,7 @@ fun Route.constitution(repo: ConstitutionRepository) {
}
post {
- val constitution = call.receive()
- constitution.createdBy = citizen
+ val constitution = call.receive().create(citizen)
assertCan(CREATE, constitution)
repo.upsert(constitution)
diff --git a/src/main/kotlin/fr/dcproject/security/voter/ArticleVoter.kt b/src/main/kotlin/fr/dcproject/security/voter/ArticleVoter.kt
index 44a26d1..0d601b5 100644
--- a/src/main/kotlin/fr/dcproject/security/voter/ArticleVoter.kt
+++ b/src/main/kotlin/fr/dcproject/security/voter/ArticleVoter.kt
@@ -1,8 +1,8 @@
package fr.dcproject.security.voter
-import fr.dcproject.entity.User
+import fr.dcproject.entity.ArticleSimpleI
+import fr.dcproject.entity.UserI
import io.ktor.application.ApplicationCall
-import fr.dcproject.entity.Article as ArticleEntity
import fr.dcproject.entity.Comment as CommentEntity
import fr.dcproject.entity.Vote as VoteEntity
@@ -16,23 +16,23 @@ class ArticleVoter : Voter {
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
return (action is Action || action is CommentVoter.Action || action is VoteVoter.Action)
- .and(subject is List<*> || subject is ArticleEntity? || subject is VoteEntity<*> || subject is CommentEntity<*>)
+ .and(subject is List<*> || subject is ArticleSimpleI? || subject is VoteEntity<*> || subject is CommentEntity<*>)
}
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
val user = call.user
- if (action == Action.CREATE && user is User) {
+ if (action == Action.CREATE && user is UserI) {
return Vote.GRANTED
}
if (action == Action.VIEW) {
- if (subject is ArticleEntity) {
+ if (subject is ArticleSimpleI) {
return if (subject.isDeleted()) Vote.DENIED
else Vote.GRANTED
}
if (subject is List<*>) {
subject.forEach {
- if (it !is ArticleEntity || it.isDeleted()) {
+ if (it !is ArticleSimpleI || it.isDeleted()) {
return Vote.DENIED
}
}
@@ -44,12 +44,12 @@ class ArticleVoter : Voter {
if (action is CommentVoter.Action) return voteForComment(action)
if (action is VoteVoter.Action) return voteForVote(action, subject)
- if (subject is ArticleEntity) {
- if (action == Action.DELETE && user is User && subject.createdBy?.userId == user.id) {
+ if (subject is ArticleSimpleI) {
+ if (action == Action.DELETE && user is UserI && subject.createdBy.user.id == user.id) {
return Vote.GRANTED
}
- if (action == Action.UPDATE && user is User && subject.createdBy?.userId == user.id) {
+ if (action == Action.UPDATE && user is UserI && subject.createdBy.user.id == user.id) {
return Vote.GRANTED
}
@@ -66,7 +66,7 @@ class ArticleVoter : Voter {
private fun voteForVote(action: VoteVoter.Action, subject: Any?): Vote {
if (action == VoteVoter.Action.CREATE && subject is VoteEntity<*>) {
val target = subject.target
- if (target !is ArticleEntity) {
+ if (target !is ArticleSimpleI) {
return Vote.ABSTAIN
}
if (target.isDeleted()) {
diff --git a/src/main/kotlin/fr/dcproject/security/voter/CitizenVoter.kt b/src/main/kotlin/fr/dcproject/security/voter/CitizenVoter.kt
index f45a0c5..1f8e89f 100644
--- a/src/main/kotlin/fr/dcproject/security/voter/CitizenVoter.kt
+++ b/src/main/kotlin/fr/dcproject/security/voter/CitizenVoter.kt
@@ -1,7 +1,7 @@
package fr.dcproject.security.voter
-import fr.dcproject.entity.Citizen
-import fr.dcproject.entity.User
+import fr.dcproject.entity.CitizenBasicI
+import fr.dcproject.entity.UserI
import io.ktor.application.ApplicationCall
import io.ktor.locations.KtorExperimentalLocationsAPI
@@ -17,7 +17,7 @@ class CitizenVoter : Voter {
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
return (action is Action)
- .and(subject is List<*> || subject is Citizen?)
+ .and(subject is List<*> || subject is CitizenBasicI?)
}
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
@@ -28,13 +28,13 @@ class CitizenVoter : Voter {
if (action == Action.VIEW) {
if (user == null) return Vote.DENIED
- if (subject is Citizen) {
+ if (subject is CitizenBasicI) {
return if (subject.isDeleted()) Vote.DENIED
else Vote.GRANTED
}
if (subject is List<*>) {
subject.forEach {
- if (it !is Citizen || it.isDeleted()) {
+ if (it !is CitizenBasicI || it.isDeleted()) {
return Vote.DENIED
}
}
@@ -48,14 +48,14 @@ class CitizenVoter : Voter {
}
if (action == Action.UPDATE &&
- user is User &&
- subject is Citizen &&
- subject.user?.id == user.id) {
+ user is UserI &&
+ subject is CitizenBasicI &&
+ subject.user.id == user.id) {
return Vote.GRANTED
}
- if (action == Action.CHANGE_PASSWORD && user != null && subject is Citizen) {
- val userToChange = subject.user ?: error("Citizen must have User")
+ if (action == Action.CHANGE_PASSWORD && user != null && subject is CitizenBasicI) {
+ val userToChange = subject.user
return if (user.id == userToChange.id) {
Vote.GRANTED
} else {
diff --git a/src/main/kotlin/fr/dcproject/security/voter/CommentVoter.kt b/src/main/kotlin/fr/dcproject/security/voter/CommentVoter.kt
index 9c94284..b7760f6 100644
--- a/src/main/kotlin/fr/dcproject/security/voter/CommentVoter.kt
+++ b/src/main/kotlin/fr/dcproject/security/voter/CommentVoter.kt
@@ -38,7 +38,7 @@ class CommentVoter : Voter {
return Vote.DENIED
}
- if (action == Action.UPDATE && user != null && subject is Comment<*> && user.id == subject.createdBy?.userId) {
+ if (action == Action.UPDATE && user != null && subject is Comment<*> && user.id == subject.createdBy.user.id) {
return Vote.GRANTED
}
diff --git a/src/main/kotlin/fr/dcproject/security/voter/ConstitutionVoter.kt b/src/main/kotlin/fr/dcproject/security/voter/ConstitutionVoter.kt
index 8f1f57e..a73a5bd 100644
--- a/src/main/kotlin/fr/dcproject/security/voter/ConstitutionVoter.kt
+++ b/src/main/kotlin/fr/dcproject/security/voter/ConstitutionVoter.kt
@@ -1,9 +1,9 @@
package fr.dcproject.security.voter
import fr.dcproject.entity.Comment
-import fr.dcproject.entity.User
+import fr.dcproject.entity.ConstitutionSimple
+import fr.dcproject.entity.UserI
import io.ktor.application.ApplicationCall
-import fr.dcproject.entity.Constitution as ConstitutionEntity
import fr.dcproject.entity.Vote as VoteEntity
class ConstitutionVoter : Voter {
@@ -16,7 +16,7 @@ class ConstitutionVoter : Voter {
override fun supports(action: ActionI, call: ApplicationCall, subject: Any?): Boolean {
return (action is Action || action is CommentVoter.Action || action is VoteVoter.Action)
- .and(subject is List<*> || subject is ConstitutionEntity? || subject is VoteEntity<*> || subject is Comment<*>)
+ .and(subject is List<*> || subject is ConstitutionSimple<*, *>? || subject is VoteEntity<*> || subject is Comment<*>)
}
override fun vote(action: ActionI, call: ApplicationCall, subject: Any?): Vote {
@@ -26,13 +26,13 @@ class ConstitutionVoter : Voter {
}
if (action == Action.VIEW) {
- if (subject is ConstitutionEntity) {
+ if (subject is ConstitutionSimple<*, *>) {
return if (subject.isDeleted()) Vote.DENIED
else Vote.GRANTED
}
if (subject is List<*>) {
subject.forEach {
- if (it !is ConstitutionEntity || it.isDeleted()) {
+ if (it !is ConstitutionSimple<*, *> || it.isDeleted()) {
return Vote.DENIED
}
}
@@ -41,11 +41,11 @@ class ConstitutionVoter : Voter {
return Vote.DENIED
}
- if (action == Action.DELETE && user is User && subject is ConstitutionEntity && subject.createdBy?.userId == user.id) {
+ if (action == Action.DELETE && user is UserI && subject is ConstitutionSimple<*, *> && subject.createdBy.user.id == user.id) {
return Vote.GRANTED
}
- if (action == Action.UPDATE && user is User && subject is ConstitutionEntity && subject.createdBy?.userId == user.id) {
+ if (action == Action.UPDATE && user is UserI && subject is ConstitutionSimple<*, *> && subject.createdBy.user.id == user.id) {
return Vote.GRANTED
}
@@ -62,7 +62,7 @@ class ConstitutionVoter : Voter {
private fun voteForVote(action: VoteVoter.Action, subject: Any?): Vote {
if (action == VoteVoter.Action.CREATE && subject is VoteEntity<*>) {
val target = subject.target
- if (target !is ConstitutionEntity) {
+ if (target !is ConstitutionSimple<*, *>) {
return Vote.ABSTAIN
}
if (target.isDeleted()) {
diff --git a/src/main/kotlin/fr/dcproject/security/voter/FollowVoter.kt b/src/main/kotlin/fr/dcproject/security/voter/FollowVoter.kt
index d19fa73..763d234 100644
--- a/src/main/kotlin/fr/dcproject/security/voter/FollowVoter.kt
+++ b/src/main/kotlin/fr/dcproject/security/voter/FollowVoter.kt
@@ -47,7 +47,7 @@ class FollowVoter : Voter {
}
private fun voteView(user: UserEntity?, subject: FollowEntity<*>): Vote {
- return if ((user != null && subject.createdBy?.user?.id == user.id) || subject.createdBy?.followAnonymous == false) Vote.GRANTED
+ return if ((user != null && subject.createdBy.user.id == user.id) || !subject.createdBy.followAnonymous) Vote.GRANTED
else Vote.DENIED
}
}
diff --git a/src/main/kotlin/fr/dcproject/security/voter/VoteVoter.kt b/src/main/kotlin/fr/dcproject/security/voter/VoteVoter.kt
index 8cef8e4..69b0712 100644
--- a/src/main/kotlin/fr/dcproject/security/voter/VoteVoter.kt
+++ b/src/main/kotlin/fr/dcproject/security/voter/VoteVoter.kt
@@ -24,7 +24,7 @@ class VoteVoter : Voter {
if (action == Action.VIEW && user != null) {
if (subject is VoteEntity<*>) {
- return if (subject.createdBy?.userId != user.id) {
+ return if (subject.createdBy.user.id != user.id) {
Vote.DENIED
} else {
Vote.GRANTED
@@ -33,7 +33,7 @@ class VoteVoter : Voter {
if (subject is List<*>) {
subject.forEach {
- if (it !is VoteEntity<*> || it.createdBy?.userId != user.id) {
+ if (it !is VoteEntity<*> || it.createdBy.user.id != user.id) {
return Vote.DENIED
}
}
diff --git a/src/main/resources/sql/fixtures/05-constitution.sql b/src/main/resources/sql/fixtures/05-constitution.sql
index 2437643..1c6e4c7 100644
--- a/src/main/resources/sql/fixtures/05-constitution.sql
+++ b/src/main/resources/sql/fixtures/05-constitution.sql
@@ -17,20 +17,18 @@ begin
now() + (row_number() over () * interval '7 minute 3 second')
from citizen z;
- insert into title (id, created_by_id, name, rank, constitution_id)
+ insert into title (id, name, rank, constitution_id)
select
uuid_in(md5('constitution_title'||row_number() over ())::cstring),
- c.created_by_id,
'name' || row_number() over (),
row_number() over (),
c.id
from constitution c,
lateral generate_series(1, 5) g;
- insert into article_in_title (id, created_by_id, rank, title_id, article_id, constitution_id)
+ insert into article_in_title (id, rank, title_id, article_id, constitution_id)
select
uuid_in(md5('article_in_title'||row_number() over ())::cstring),
- ti.created_by_id,
row_number() over (),
ti.id,
a.id,
diff --git a/src/main/resources/sql/functions/citizen/find_citizen_by_id.sql b/src/main/resources/sql/functions/citizen/find_citizen_by_id.sql
index 07a2672..6284a0f 100644
--- a/src/main/resources/sql/functions/citizen/find_citizen_by_id.sql
+++ b/src/main/resources/sql/functions/citizen/find_citizen_by_id.sql
@@ -6,7 +6,8 @@ begin
select to_json(t) into resource
from (
select
- z.*
+ z.*,
+ find_user_by_id(z.user_id) as "user"
from citizen as z
where z.id = _id
) as t;
diff --git a/src/main/resources/sql/functions/citizen/find_citizen_by_id_with_user.sql b/src/main/resources/sql/functions/citizen/find_citizen_by_id_with_user.sql
index 3361647..d65b757 100644
--- a/src/main/resources/sql/functions/citizen/find_citizen_by_id_with_user.sql
+++ b/src/main/resources/sql/functions/citizen/find_citizen_by_id_with_user.sql
@@ -7,9 +7,8 @@ begin
from (
select
z.*,
- u as "user"
+ find_user_by_id(z.user_id) as "user"
from citizen as z
- join "user" u on z.user_id = u.id
where z.id = _id
) as t;
end;
diff --git a/src/main/resources/sql/functions/citizen/find_citizens.sql b/src/main/resources/sql/functions/citizen/find_citizens.sql
index 5f57222..ae4e809 100644
--- a/src/main/resources/sql/functions/citizen/find_citizens.sql
+++ b/src/main/resources/sql/functions/citizen/find_citizens.sql
@@ -13,7 +13,8 @@ begin
into resource, total
from (
select
- z.*
+ z.*,
+ json_build_object('id', z.user_id) as "user"
from citizen as z
where "search" is null or (
(name->'first_name')::text ilike '%'||"search"||'%' or
diff --git a/src/main/resources/sql/functions/constitution/create_title_in_constitution.sql b/src/main/resources/sql/functions/constitution/create_title_in_constitution.sql
index dad5dd5..548d98e 100644
--- a/src/main/resources/sql/functions/constitution/create_title_in_constitution.sql
+++ b/src/main/resources/sql/functions/constitution/create_title_in_constitution.sql
@@ -4,12 +4,10 @@ $$
declare
_title alias for title;
_constitution_id uuid = coalesce(constitution_id, (title#>>'{constitution_id}')::uuid);
- _author_id uuid = (title#>>'{created_by, id}')::uuid;
new_id uuid;
begin
- insert into title (created_by_id, name, rank, constitution_id)
+ insert into title (name, rank, constitution_id)
select
- _author_id,
ti.name,
row_number() OVER (),
_constitution_id
@@ -17,9 +15,8 @@ begin
returning id into new_id;
if (_title->'articles' is not null) then
- insert into article_in_title (created_by_id, rank, title_id, article_id, constitution_id)
+ insert into article_in_title (rank, title_id, article_id, constitution_id)
select
- _author_id,
row_number() over (),
new_id,
id,
diff --git a/src/main/resources/sql/functions/constitution/upsert_constitution.sql b/src/main/resources/sql/functions/constitution/upsert_constitution.sql
index 0c88219..4968c73 100644
--- a/src/main/resources/sql/functions/constitution/upsert_constitution.sql
+++ b/src/main/resources/sql/functions/constitution/upsert_constitution.sql
@@ -46,10 +46,6 @@ begin
titles := (resource->>'titles');
for _title in select json_array_elements(titles) loop
- if _title#>>'{created_by, id}' is null then
- _title := jsonb_set(_title::jsonb, '{created_by}'::text[], jsonb_build_object('id', _citizen_id::text), true)::json;
- end if;
-
perform create_title_in_constitution(_title, new_id);
end loop;
diff --git a/src/main/resources/sql/migrations/0000-init_schema.up.sql b/src/main/resources/sql/migrations/0000-init_schema.up.sql
index 528fbd2..8aead58 100644
--- a/src/main/resources/sql/migrations/0000-init_schema.up.sql
+++ b/src/main/resources/sql/migrations/0000-init_schema.up.sql
@@ -274,7 +274,6 @@ create table title
(
id uuid default uuid_generate_v4() not null primary key,
created_at timestamptz default now() not null,
- created_by_id uuid not null references citizen (id),
name text not null check ( name != '' ),
rank int not null check ( rank >= 0 ),
constitution_id uuid not null references constitution (id)
@@ -284,7 +283,6 @@ create table article_in_title
(
id uuid default uuid_generate_v4() not null primary key,
created_at timestamptz default now() not null,
- created_by_id uuid not null references citizen (id),
rank int not null check ( rank >= 0 ),
title_id uuid not null references title (id),
article_id uuid not null references article (id),
diff --git a/src/test/kotlin/ArticleTest.kt b/src/test/kotlin/ArticleTest.kt
index 0ab39df..573edf1 100644
--- a/src/test/kotlin/ArticleTest.kt
+++ b/src/test/kotlin/ArticleTest.kt
@@ -1,5 +1,6 @@
import fr.dcproject.entity.Article
-import fr.dcproject.entity.Citizen
+import fr.dcproject.entity.CitizenBasic
+import fr.dcproject.entity.CitizenI
import fr.dcproject.entity.User
import fr.postgresjson.serializer.deserialize
import fr.postgresjson.serializer.serialize
@@ -57,8 +58,8 @@ class ArticleTest {
@Test
fun `test Article serialize`() {
val user = User(username = "jaque", plainPassword = "azerty")
- val citizen = Citizen(
- name = Citizen.Name("Jaque", "Bono"),
+ val citizen = CitizenBasic(
+ name = CitizenI.Name("Jaque", "Bono"),
birthday = DateTime.now(),
email = "jaque.bono@gmail.com",
user = user
diff --git a/src/test/kotlin/ConstitutionTest.kt b/src/test/kotlin/ConstitutionTest.kt
index b9fdbe0..bd69fff 100644
--- a/src/test/kotlin/ConstitutionTest.kt
+++ b/src/test/kotlin/ConstitutionTest.kt
@@ -1,4 +1,5 @@
-import fr.dcproject.entity.Citizen
+import fr.dcproject.entity.CitizenBasic
+import fr.dcproject.entity.CitizenI
import fr.dcproject.entity.Constitution
import fr.dcproject.entity.User
import fr.postgresjson.serializer.deserialize
@@ -78,8 +79,8 @@ class ConstitutionTest {
@Test
fun `test Constitution serialize`() {
val user = User(username = "jaque", plainPassword = "azerty")
- val citizen = Citizen(
- name = Citizen.Name("Jaque", "Bono"),
+ val citizen = CitizenBasic(
+ name = CitizenI.Name("Jaque", "Bono"),
email = "jaque.bono@gmail.com",
birthday = DateTime.now(),
user = user
@@ -90,7 +91,7 @@ class ConstitutionTest {
val constitution = Constitution(
title = "Hello world!",
anonymous = true,
- titles = listOf(title1),
+ titles = mutableListOf(title1),
createdBy = citizen
)
println(constitution.serialize())
diff --git a/src/test/kotlin/FollowTest.kt b/src/test/kotlin/FollowTest.kt
index e9505c7..db67081 100644
--- a/src/test/kotlin/FollowTest.kt
+++ b/src/test/kotlin/FollowTest.kt
@@ -1,7 +1,4 @@
-import fr.dcproject.entity.Article
-import fr.dcproject.entity.Citizen
-import fr.dcproject.entity.Follow
-import fr.dcproject.entity.User
+import fr.dcproject.entity.*
import fr.postgresjson.serializer.deserialize
import fr.postgresjson.serializer.serialize
import io.ktor.locations.KtorExperimentalLocationsAPI
@@ -53,7 +50,25 @@ class FollowTest {
],
"created_by":{
- "id":"4a87ad24-187a-46a8-97ab-00b30a24e561"
+ "id":"4a87ad24-187a-46a8-97ab-00b30a24e561",
+ "name":{
+ "first_name":"Jaque",
+ "last_name":"Bono",
+ "civility":null
+ },
+ "email": "jaque.bono@gmail.com",
+ "birthday":"2019-08-09T11:42:47.168Z",
+ "user_id":null,
+ "vote_anonymous":null,
+ "follow_anonymous":null,
+ "user":{
+ "id":"721db690-d050-46e6-92b0-056f2e8ba993",
+ "username":"jaque",
+ "blocked_at":null,
+ "plain_password":"azerty",
+ "created_at":null,
+ "updated_at":null
+ }
},
"version_id":"a4aa7dd4-d174-42d2-9ba5-ae6f1129ffce",
"version_number":null,
@@ -65,8 +80,8 @@ class FollowTest {
@Test
fun `test Follow Article serialize`() {
val user = User(username = "jaque", plainPassword = "azerty")
- val citizen = Citizen(
- name = Citizen.Name("Jaque", "Bono"),
+ val citizen = CitizenBasic(
+ name = CitizenI.Name("Jaque", "Bono"),
email = "jaque.bono@gmail.com",
birthday = DateTime.now(),
user = user
@@ -87,7 +102,7 @@ class FollowTest {
@Test
fun `test Follow Article Deserialize`() {
- val follow: Follow = followJson.deserialize()!!
+ val follow: Follow = followJson.deserialize()!!
follow.id.toString() `should equal` "bae81585-d985-4d7a-9b58-3a13e911688a"
}
}
diff --git a/src/test/kotlin/VoteTest.kt b/src/test/kotlin/VoteTest.kt
index a179117..926d79d 100644
--- a/src/test/kotlin/VoteTest.kt
+++ b/src/test/kotlin/VoteTest.kt
@@ -1,7 +1,4 @@
-import fr.dcproject.entity.Article
-import fr.dcproject.entity.Citizen
-import fr.dcproject.entity.User
-import fr.dcproject.entity.Vote
+import fr.dcproject.entity.*
import fr.postgresjson.serializer.deserialize
import fr.postgresjson.serializer.serialize
import io.ktor.locations.KtorExperimentalLocationsAPI
@@ -40,11 +37,12 @@ class VoteTest {
"blocked_at": null,
"plain_password": "azerty",
"roles": [],
- "created_at": null,
- "updated_at": null
+ "created_at": "2019-10-01T10:59:40.570Z",
+ "updated_at": "2019-10-01T10:59:40.570Z"
},
"deleted": false,
- "created_at": null,
+ "created_at": "2019-10-01T10:59:40.570Z",
+ "updated_at": "2019-10-01T10:59:40.570Z",
"deleted_at": null
},
"target": {
@@ -90,20 +88,20 @@ class VoteTest {
"version_id": "48dad61e-c54b-4f4c-9f66-428f90b94045",
"version_number": null,
"deleted": false,
- "created_at": null,
- "deleted_at": null
+ "created_at": "2019-10-01T10:59:40.570Z",
+ "deleted_at": "2019-10-01T10:59:40.570Z"
},
"note": -1,
"anonymous": true,
- "updated_at": null,
- "created_at": null
+ "updated_at": "2019-10-01T10:59:40.570Z",
+ "created_at": "2019-10-01T10:59:40.570Z"
}""".trimIndent()
@Test
fun `test Vote Article serialize`() {
val user = User(username = "jaque", plainPassword = "azerty")
- val citizen = Citizen(
- name = Citizen.Name("Jaque", "Bono"),
+ val citizen = CitizenBasic(
+ name = CitizenI.Name("Jaque", "Bono"),
email = "jaque.bono@gmail.com",
birthday = DateTime.now(),
user = user
diff --git a/src/test/kotlin/feature/ArticleSteps.kt b/src/test/kotlin/feature/ArticleSteps.kt
index d708c25..63d0f37 100644
--- a/src/test/kotlin/feature/ArticleSteps.kt
+++ b/src/test/kotlin/feature/ArticleSteps.kt
@@ -1,6 +1,6 @@
package feature
-import fr.dcproject.entity.Citizen
+import fr.dcproject.entity.*
import fr.dcproject.repository.CommentArticle
import io.cucumber.java8.En
import org.joda.time.DateTime
@@ -18,7 +18,7 @@ class ArticleSteps : En, KoinTest {
init {
Given("I have article with id {string}") { id: String ->
var citizen = Citizen(
- name = Citizen.Name("John", "Doe"),
+ name = CitizenI.Name("John", "Doe"),
email = "john.doe@gmail.com",
birthday = DateTime.now(),
user = UserEntity(username = "john-doe", plainPassword = "azerty")
@@ -55,7 +55,7 @@ class ArticleSteps : En, KoinTest {
Given("I have comment {string} on article {string}") { commentId: String, articleId: String ->
var citizen = Citizen(
- name = Citizen.Name("John", "Doe"),
+ name = CitizenI.Name("John", "Doe"),
email = "john.doe@gmail.com",
birthday = DateTime.now(),
user = UserEntity(username = "john-doe", plainPassword = "azerty")
@@ -76,7 +76,7 @@ class ArticleSteps : En, KoinTest {
)
get().upsert(article)
- val comment = CommentEntity(
+ val comment: CommentEntity = CommentEntity(
id = UUID.fromString(commentId),
createdBy = citizen,
target = article,
diff --git a/src/test/kotlin/feature/ConstitutionSteps.kt b/src/test/kotlin/feature/ConstitutionSteps.kt
index 6c35d6b..87dab5d 100644
--- a/src/test/kotlin/feature/ConstitutionSteps.kt
+++ b/src/test/kotlin/feature/ConstitutionSteps.kt
@@ -1,14 +1,14 @@
package feature
-import fr.dcproject.entity.Citizen
+import fr.dcproject.entity.*
+import fr.dcproject.entity.ConstitutionSimple.TitleSimple
+import fr.dcproject.entity.request.Constitution
import io.cucumber.java8.En
import org.joda.time.DateTime
import org.koin.test.KoinTest
import org.koin.test.get
import java.util.*
import java.util.concurrent.CompletionException
-import fr.dcproject.entity.Constitution as ConstitutionEntity
-import fr.dcproject.entity.Constitution.Title as TitleEntity
import fr.dcproject.entity.User as UserEntity
import fr.dcproject.repository.Citizen as CitizenRepository
import fr.dcproject.repository.Constitution as ConstitutionRepository
@@ -17,7 +17,7 @@ class ConstitutionSteps : En, KoinTest {
init {
Given("I have constitution with id {string}") { id: String ->
var citizen = Citizen(
- name = Citizen.Name("John", "Doe"),
+ name = CitizenI.Name("John", "Doe"),
email = "john.doe@gmail.com",
birthday = DateTime.now(),
user = UserEntity(username = "john-doe", plainPassword = "azerty")
@@ -29,33 +29,31 @@ class ConstitutionSteps : En, KoinTest {
citizen = get().findByUsername("john-doe")!!
}
- val title1 = TitleEntity(
+ val title1 = Constitution.Title(
name = "My Title"
)
- val constitution = ConstitutionEntity(
- id = UUID.fromString(id),
+ val constitution = Constitution(
title = "hello",
- titles = listOf(title1),
- createdBy = citizen,
+ titles = mutableListOf(title1),
anonymous = false
)
- get().upsert(constitution)
+ get().upsert(constitution.create(citizen))
}
Given("I have constitution with id {string} created by {string}") { id: String, username: String ->
val citizen = get().findByUsername(username)!!
- val title1 = TitleEntity(
+ val title1 = TitleSimple(
name = "My Title"
)
- val constitution = ConstitutionEntity(
+ val constitution = ConstitutionSimple>(
id = UUID.fromString(id),
title = "hello",
- titles = listOf(title1),
- createdBy = citizen,
- anonymous = false
+ titles = mutableListOf(title1),
+ anonymous = false,
+ createdBy = citizen
)
get().upsert(constitution)
}
diff --git a/src/test/kotlin/feature/KtorServerAuthSteps.kt b/src/test/kotlin/feature/KtorServerAuthSteps.kt
index e313628..b28b83e 100644
--- a/src/test/kotlin/feature/KtorServerAuthSteps.kt
+++ b/src/test/kotlin/feature/KtorServerAuthSteps.kt
@@ -3,6 +3,7 @@ package feature
import com.auth0.jwt.JWT
import fr.dcproject.JwtConfig
import fr.dcproject.entity.Citizen
+import fr.dcproject.entity.CitizenI
import fr.dcproject.entity.User
import fr.postgresjson.connexion.Requester
import io.cucumber.datatable.DataTable
@@ -29,7 +30,7 @@ class KtorServerAuthSteps : En, KoinTest {
val data = body.asMap(String::class.java, String::class.java)
val citizen = Citizen(
id = UUID.fromString(data["id"]),
- name = Citizen.Name(data["firstName"], data["lastName"]),
+ name = CitizenI.Name(data["firstName"]!!, data["lastName"]!!),
email = data["email"] ?: ((data["firstName"] + "-" + data["lastName"]).toLowerCase()) + "@dc-project.com",
birthday = DateTime.now(),
user = user
@@ -52,7 +53,7 @@ class KtorServerAuthSteps : En, KoinTest {
)
val citizen = Citizen(
id = UUID.fromString(id),
- name = Citizen.Name(firstName, lastName),
+ name = CitizenI.Name(firstName, lastName),
email = ("$firstName-$lastName".toLowerCase()) + "@dc-project.fr",
birthday = DateTime.now(),
user = user
@@ -77,7 +78,7 @@ class KtorServerAuthSteps : En, KoinTest {
)
val citizen = Citizen(
id = UUID.fromString(id),
- name = Citizen.Name(firstName, lastName),
+ name = CitizenI.Name(firstName, lastName),
email = "$firstName-$lastName".toLowerCase() + "@gmail.com",
birthday = DateTime.now(),
user = user,
diff --git a/src/test/resources/feature/commentConstitution.feature b/src/test/resources/feature/commentConstitution.feature
index 13577fd..8cfb9ce 100644
--- a/src/test/resources/feature/commentConstitution.feature
+++ b/src/test/resources/feature/commentConstitution.feature
@@ -1,9 +1,9 @@
Feature: comment Constitution
Scenario: Can comment an constitution
- Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
- And I have constitution with id "9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b"
- When I send a POST request to "/constitutions/9226c1a3-8091-c3fa-7d0d-c2e98c9bee7b/comments" with body:
+ Given I am authenticated as John Toe with id "a6eb1f5a-8c02-42f4-8e8e-a722f26841ef"
+ And I have constitution with id "d7e20f0b-3fdd-4638-817a-bbd87054eb82" created by "john-toe"
+ When I send a POST request to "/constitutions/d7e20f0b-3fdd-4638-817a-bbd87054eb82/comments" with body:
"""
Hello mister
"""
diff --git a/src/test/resources/feature/constitution.feature b/src/test/resources/feature/constitution.feature
index 4b7c6b8..110a1f9 100644
--- a/src/test/resources/feature/constitution.feature
+++ b/src/test/resources/feature/constitution.feature
@@ -32,7 +32,6 @@ Feature: constitution routes
"id":"64b7b379-2298-43ec-b428-ba134930cabd"
},
"created_at":null,
- "version_id":"3311a7af-2a62-4e31-b4cd-889f8ead9737",
"version_number":null
}
"""
diff --git a/src/test/resources/feature/vote.feature b/src/test/resources/feature/vote.feature
index 292420c..b5fe75a 100644
--- a/src/test/resources/feature/vote.feature
+++ b/src/test/resources/feature/vote.feature
@@ -37,7 +37,7 @@ Feature: vote Article
And the response should contain object:
| [0].note | 1 |
- Scenario: Can vote a comment on article
+ Scenario: Can vote a comment
Given I am authenticated as John Doe with id "64b7b379-2298-43ec-b428-ba134930cabd"
And I have comment "ea5c9e87-c99e-4646-a381-2910219e077f" on article "cc9c624e-a27e-42de-af78-ae821c657a68"
When I send a PUT request to "/comments/ea5c9e87-c99e-4646-a381-2910219e077f/vote" with body: