Split Entities for remove nullable variables
This commit is contained in:
@@ -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<Article> {
|
||||
decode { values, _ ->
|
||||
val id = values.singleOrNull()?.let { UUID.fromString(it) }
|
||||
?: throw InternalError("Cannot convert $values to UUID")
|
||||
get<RepositoryArticle>().findById(id) ?: throw InternalError("Article $values not found")
|
||||
values.singleOrNull()?.let {
|
||||
get<RepositoryArticle>().findById(UUID.fromString(it)) ?: throw InternalError("Article $values not found")
|
||||
} ?: throw NotFoundException("Article $values not found")
|
||||
}
|
||||
}
|
||||
convert<ArticleRef> {
|
||||
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<RepositoryConstitution>().findById(id) ?: throw InternalError("Constitution $values not found")
|
||||
get<RepositoryConstitution>().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<RepositoryCitizen>().findById(id, true) ?: throw InternalError("Citizen $values not found")
|
||||
get<RepositoryCitizen>().findById(id, true) ?: throw NotFoundException("Citizen $values not found")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -179,6 +183,9 @@ fun Application.module(env: Env = PROD) {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
exception<NotFoundException> { e ->
|
||||
call.respond(HttpStatusCode.BadRequest, e.message!!)
|
||||
}
|
||||
}
|
||||
|
||||
install(CORS) {
|
||||
|
||||
@@ -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<CitizenEntity>("CitizenContext")
|
||||
@@ -16,7 +16,7 @@ private val citizenAttributeKey = AttributeKey<CitizenEntity>("CitizenContext")
|
||||
val ApplicationCall.citizen: CitizenEntity
|
||||
get() = attributes.computeIfAbsent(citizenAttributeKey) {
|
||||
runBlocking {
|
||||
val user = authentication.principal<UserEntity>() ?: throw ForbiddenException()
|
||||
val user = authentication.principal<UserI>() ?: throw ForbiddenException()
|
||||
GlobalContext.get().koin.get<CitizenRepository>().findByUser(user) ?: throw ForbiddenException("Citizen not found for this user id \"${user.id}\"")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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<String> = emptyList(),
|
||||
var draft: Boolean = false,
|
||||
var lastVersion: Boolean = false,
|
||||
createdBy: Citizen?
|
||||
) :
|
||||
UuidEntity(id),
|
||||
EntityVersioning<UUID, Int> by UuidEntityVersioning(),
|
||||
EntityCreatedAt by EntityCreatedAtImp(),
|
||||
EntityCreatedBy<Citizen> by EntityCreatedByImp(createdBy),
|
||||
EntityDeletedAt by EntityDeletedAtImp(),
|
||||
Votable by VotableImp() {
|
||||
title: String,
|
||||
anonymous: Boolean = true,
|
||||
content: String,
|
||||
description: String,
|
||||
tags: List<String> = 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<String> = emptyList(),
|
||||
override val createdBy: CitizenBasic
|
||||
) : ArticleBasicI,
|
||||
ArticleSimple(id, title, createdBy) {
|
||||
|
||||
init {
|
||||
tags = tags.distinct()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class ArticleSimple(
|
||||
id: UUID = UUID.randomUUID(),
|
||||
override var title: String,
|
||||
override val createdBy: CitizenBasic
|
||||
) : ArticleSimpleI,
|
||||
ArticleRef(id),
|
||||
EntityCreatedAt by EntityCreatedAtImp(),
|
||||
EntityCreatedBy<CitizenBasicI> by EntityCreatedByImp(createdBy),
|
||||
EntityDeletedAt by EntityDeletedAtImp(),
|
||||
EntityVersioning<UUID, Int> by UuidEntityVersioning(),
|
||||
Votable by VotableImp()
|
||||
|
||||
open class ArticleRef(
|
||||
id: UUID = UUID.randomUUID()
|
||||
) : ArticleI, TargetRef(id)
|
||||
|
||||
interface ArticleI : UuidEntityI, TargetI
|
||||
|
||||
interface ArticleSimpleI :
|
||||
ArticleI,
|
||||
EntityVersioning<UUID, Int>,
|
||||
EntityCreatedBy<CitizenBasicI>,
|
||||
EntityCreatedAt,
|
||||
EntityDeletedAt,
|
||||
Votable {
|
||||
var title: String
|
||||
}
|
||||
interface ArticleBasicI :
|
||||
ArticleSimpleI {
|
||||
var anonymous: Boolean
|
||||
var content: String
|
||||
var description: String
|
||||
var tags: List<String>
|
||||
}
|
||||
|
||||
interface ArticleFull :
|
||||
ArticleBasicI {
|
||||
var draft: Boolean
|
||||
var lastVersion: Boolean
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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 <T : UuidEntity> (
|
||||
open class Comment<T : TargetI>(
|
||||
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<Comment<T>>? = null,
|
||||
var parent: Comment<T>? = null,
|
||||
@@ -16,17 +18,18 @@ open class Comment <T : UuidEntity> (
|
||||
) : Extra<T>(id, createdBy, target),
|
||||
EntityUpdatedAt by EntityUpdatedAtImp(),
|
||||
EntityDeletedAt by EntityDeletedAtImp(),
|
||||
Votable by VotableImp()
|
||||
{
|
||||
Votable by VotableImp(),
|
||||
TargetI {
|
||||
constructor(
|
||||
createdBy: Citizen,
|
||||
createdBy: CitizenBasic,
|
||||
parent: Comment<T>,
|
||||
content: String
|
||||
) : this(
|
||||
createdBy = createdBy,
|
||||
parent = parent,
|
||||
target = parent.target,
|
||||
targetReference = parent.targetReference,
|
||||
content = content
|
||||
)
|
||||
|
||||
override val reference get() = TargetI.getReference(this)
|
||||
}
|
||||
|
||||
@@ -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<Title> = listOf(),
|
||||
title: String,
|
||||
anonymous: Boolean = true,
|
||||
titles: MutableList<TitleSimple<ArticleSimple>> = mutableListOf(),
|
||||
draft: Boolean = false,
|
||||
lastVersion: Boolean = false,
|
||||
override val createdBy: CitizenSimple
|
||||
) : ConstitutionSimple<CitizenSimple, ConstitutionSimple.TitleSimple<ArticleSimple>>(
|
||||
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<ArticleSimple> = mutableListOf()
|
||||
) : ConstitutionSimple.TitleSimple<ArticleSimple>(id, name, rank)
|
||||
}
|
||||
|
||||
open class ConstitutionSimple<Cr : CitizenRef, T : ConstitutionSimple.TitleSimple<*>>(
|
||||
id: UUID = UUID.randomUUID(),
|
||||
var title: String,
|
||||
var anonymous: Boolean = true,
|
||||
open var titles: MutableList<T> = mutableListOf(),
|
||||
var draft: Boolean = false,
|
||||
var lastVersion: Boolean = false,
|
||||
createdBy: Citizen?
|
||||
) : UuidEntity(id),
|
||||
EntityVersioning<UUID, Int> by UuidEntityVersioning(),
|
||||
override val createdBy: Cr,
|
||||
versionId: UUID = UUID.randomUUID()
|
||||
) : ConstitutionRef(id),
|
||||
EntityVersioning<UUID, Int?> by UuidEntityVersioning(versionId = versionId),
|
||||
EntityCreatedAt by EntityCreatedAtImp(),
|
||||
EntityCreatedBy<Citizen> by EntityCreatedByImp(createdBy),
|
||||
EntityCreatedBy<Cr> by EntityCreatedByImp(createdBy),
|
||||
EntityDeletedAt by EntityDeletedAtImp() {
|
||||
|
||||
init {
|
||||
titles.forEachIndexed { index, title ->
|
||||
title.createdBy = this.createdBy
|
||||
title.rank = index
|
||||
}
|
||||
}
|
||||
|
||||
class Title(
|
||||
open class TitleSimple<A : ArticleI>(
|
||||
id: UUID = UUID.randomUUID(),
|
||||
var name: String?,
|
||||
var name: String,
|
||||
var rank: Int? = null,
|
||||
var articles: List<Article> = listOf(),
|
||||
createdBy: Citizen? = null
|
||||
) : UuidEntity(id),
|
||||
EntityCreatedAt by EntityCreatedAtImp(),
|
||||
EntityCreatedBy<Citizen> by EntityCreatedByImp(createdBy)
|
||||
open val articles: MutableList<A> = 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
|
||||
@@ -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 <T : EntityI> :
|
||||
EntityI,
|
||||
interface ExtraI<T : TargetI> :
|
||||
UuidEntityI,
|
||||
EntityCreatedAt,
|
||||
EntityCreatedBy<Citizen> {
|
||||
EntityCreatedBy<CitizenBasicI> {
|
||||
var target: T
|
||||
var targetReference: String
|
||||
}
|
||||
|
||||
abstract class Extra<T : UuidEntity>(
|
||||
id: UUID? = UUID.randomUUID(),
|
||||
createdBy: Citizen,
|
||||
override var target: T,
|
||||
override var targetReference: String = target::class.simpleName!!.toLowerCase()
|
||||
abstract class Extra<T : TargetI>(
|
||||
id: UUID = UUID.randomUUID(),
|
||||
override val createdBy: CitizenBasic,
|
||||
override var target: T
|
||||
) :
|
||||
ExtraI<T>,
|
||||
UuidEntity(id),
|
||||
EntityCreatedAt by EntityCreatedAtImp(),
|
||||
EntityCreatedBy<Citizen> by EntityCreatedByImp(createdBy)
|
||||
EntityCreatedBy<CitizenBasicI> 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 <T : TargetI> getReference(t: KClass<T>): 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
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
package fr.dcproject.entity
|
||||
import fr.postgresjson.entity.mutable.UuidEntity
|
||||
import java.util.*
|
||||
|
||||
class Follow <T : UuidEntity> (
|
||||
class Follow <T : TargetI> (
|
||||
id: UUID = UUID.randomUUID(),
|
||||
createdBy: Citizen,
|
||||
override val createdBy: CitizenBasic,
|
||||
target: T
|
||||
) : Extra<T>(id, createdBy, target)
|
||||
|
||||
@@ -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<Roles> = emptyList()
|
||||
) : UuidEntity(id),
|
||||
id: UUID = UUID.randomUUID(),
|
||||
username: String,
|
||||
blockedAt: DateTime? = null,
|
||||
override var plainPassword: String?,
|
||||
override var roles: List<Roles> = 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<Roles>
|
||||
}
|
||||
|
||||
@@ -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 <T : UuidEntity> (
|
||||
open class Vote <T : TargetI> (
|
||||
id: UUID = UUID.randomUUID(),
|
||||
createdBy: Citizen,
|
||||
override val createdBy: CitizenBasic,
|
||||
target: T,
|
||||
var note: Int,
|
||||
var anonymous: Boolean = true
|
||||
|
||||
@@ -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<String> = 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
|
||||
|
||||
48
src/main/kotlin/fr/dcproject/entity/request/Constitution.kt
Normal file
48
src/main/kotlin/fr/dcproject/entity/request/Constitution.kt
Normal file
@@ -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<Title> = 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<ArticleRef> = mutableListOf()
|
||||
) : UuidEntity(id) {
|
||||
fun create(): ConstitutionSimple.TitleSimple<ArticleRef> {
|
||||
return ConstitutionSimple.TitleSimple(
|
||||
id, name, rank, articles
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun create(createdBy: Citizen): ConstitutionSimple<CitizenSimple, ConstitutionSimple.TitleSimple<ArticleRef>> {
|
||||
return ConstitutionSimple(
|
||||
title = title,
|
||||
titles = titles.create(),
|
||||
createdBy = createdBy,
|
||||
versionId = versionId
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun List<Constitution.Title>.create(): MutableList<ConstitutionSimple.TitleSimple<ArticleRef>> =
|
||||
map { it.create() }.toMutableList()
|
||||
@@ -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 <a href=\"${urlObject.buildString()}\">here</a> 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()}"
|
||||
}
|
||||
|
||||
|
||||
@@ -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<ArticleEntity> {
|
||||
): Paginated<ArticleSimple> {
|
||||
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)
|
||||
|
||||
@@ -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<CitizenEntity> {
|
||||
): Paginated<CitizenBasic> {
|
||||
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)
|
||||
|
||||
@@ -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 <T : UuidEntity>(override var requester: Requester) : RepositoryI {
|
||||
abstract class Comment <T : TargetI>(override var requester: Requester) : RepositoryI {
|
||||
abstract fun findById(id: UUID): CommentEntity<T>?
|
||||
|
||||
abstract fun findByCitizen(
|
||||
@@ -24,7 +26,7 @@ abstract class Comment <T : UuidEntity>(override var requester: Requester) : Rep
|
||||
page: Int = 1,
|
||||
limit: Int = 50
|
||||
): Paginated<CommentEntity<T>> {
|
||||
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 <T : UuidEntity>(override var requester: Requester) : Rep
|
||||
}
|
||||
|
||||
open fun findByTarget(
|
||||
target: UuidEntity,
|
||||
target: UuidEntityI,
|
||||
page: Int = 1,
|
||||
limit: Int = 50
|
||||
): Paginated<CommentEntity<T>> {
|
||||
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 <T : UuidEntity>(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 <T : UuidEntity>(override var requester: Requester) : Rep
|
||||
}
|
||||
}
|
||||
|
||||
class CommentGeneric(requester: Requester) : Comment<UuidEntity>(requester) {
|
||||
override fun findById(id: UUID): CommentEntity<UuidEntity>? {
|
||||
class CommentGeneric(requester: Requester) : Comment<TargetRef>(requester) {
|
||||
override fun findById(id: UUID): CommentEntity<TargetRef>? {
|
||||
return requester
|
||||
.getFunction("find_comment_by_id")
|
||||
.selectOne(mapOf("id" to id))
|
||||
@@ -91,7 +93,7 @@ class CommentGeneric(requester: Requester) : Comment<UuidEntity>(requester) {
|
||||
citizen: CitizenEntity,
|
||||
page: Int,
|
||||
limit: Int
|
||||
): Paginated<CommentEntity<UuidEntity>> {
|
||||
): Paginated<CommentEntity<TargetRef>> {
|
||||
return requester.run {
|
||||
getFunction("find_comments_by_citizen")
|
||||
.select(page, limit,
|
||||
@@ -101,8 +103,8 @@ class CommentGeneric(requester: Requester) : Comment<UuidEntity>(requester) {
|
||||
}
|
||||
}
|
||||
|
||||
class CommentArticle(requester: Requester) : Comment<ArticleEntity>(requester) {
|
||||
override fun findById(id: UUID): CommentEntity<ArticleEntity>? {
|
||||
class CommentArticle(requester: Requester) : Comment<ArticleRef>(requester) {
|
||||
override fun findById(id: UUID): CommentEntity<ArticleRef>? {
|
||||
return requester
|
||||
.getFunction("find_comment_by_id")
|
||||
.selectOne(mapOf("id" to id))
|
||||
@@ -112,13 +114,12 @@ class CommentArticle(requester: Requester) : Comment<ArticleEntity>(requester) {
|
||||
citizen: CitizenEntity,
|
||||
page: Int,
|
||||
limit: Int
|
||||
): Paginated<CommentEntity<ArticleEntity>> {
|
||||
val reference = ArticleEntity::class.simpleName!!.toLowerCase()
|
||||
): Paginated<CommentEntity<ArticleRef>> {
|
||||
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<ConstitutionEntity>(re
|
||||
page: Int,
|
||||
limit: Int
|
||||
): Paginated<CommentEntity<ConstitutionEntity>> {
|
||||
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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<CitizenSimple, ConstitutionSimple.TitleSimple<ArticleRef>>): ConstitutionEntity? {
|
||||
return requester
|
||||
.getFunction("upsert_constitution")
|
||||
.selectOne("resource" to constitution)
|
||||
|
||||
@@ -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 <T : UuidEntity>(override var requester: Requester) : RepositoryI {
|
||||
open class Follow <T : TargetI>(override var requester: Requester) : RepositoryI {
|
||||
open fun findByCitizen(
|
||||
citizen: CitizenEntity,
|
||||
citizen: CitizenI,
|
||||
page: Int = 1,
|
||||
limit: Int = 50
|
||||
): Paginated<FollowEntity<T>> =
|
||||
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 <T : UuidEntity>(override var requester: Requester) : Reposito
|
||||
}
|
||||
|
||||
fun follow(follow: FollowEntity<T>) {
|
||||
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<T>) {
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 <T : UuidEntity>(override var requester: Requester) : RepositoryI {
|
||||
open class Vote <T : TargetI>(override var requester: Requester) : RepositoryI {
|
||||
fun vote(vote: VoteEntity<T>): 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 <T : UuidEntity>(override var requester: Requester) : Repository
|
||||
citizen: CitizenEntity,
|
||||
targets: List<UUID>
|
||||
): List<VoteEntity<*>> {
|
||||
val typeReference = object : TypeReference<List<VoteEntity<UuidEntity>>>() {}
|
||||
val typeReference = object : TypeReference<List<VoteEntity<TargetRef>>>() {}
|
||||
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<Article>(requester) {
|
||||
limit: Int = 50
|
||||
): Paginated<VoteEntity<Article>> =
|
||||
findByCitizen(
|
||||
citizen.id ?: error("The citizen must have an id"),
|
||||
citizen.id,
|
||||
"article",
|
||||
object : TypeReference<List<VoteEntity<Article>>>() {},
|
||||
page,
|
||||
@@ -90,7 +80,7 @@ class VoteArticleComment(requester: Requester) : Vote<Comment<Article>>(requeste
|
||||
limit: Int = 50
|
||||
): Paginated<VoteEntity<Comment<Article>>> =
|
||||
findByCitizen(
|
||||
citizen.id ?: error("The citizen must have an id"),
|
||||
citizen.id,
|
||||
"article",
|
||||
object : TypeReference<List<VoteEntity<Comment<Article>>>>() {},
|
||||
page,
|
||||
@@ -98,16 +88,16 @@ class VoteArticleComment(requester: Requester) : Vote<Comment<Article>>(requeste
|
||||
)
|
||||
}
|
||||
|
||||
class VoteComment(requester: Requester) : Vote<Comment<UuidEntity>>(requester) {
|
||||
class VoteComment(requester: Requester) : Vote<Comment<TargetRef>>(requester) {
|
||||
fun findByCitizen(
|
||||
citizen: CitizenEntity,
|
||||
page: Int = 1,
|
||||
limit: Int = 50
|
||||
): Paginated<VoteEntity<Comment<UuidEntity>>> =
|
||||
): Paginated<VoteEntity<Comment<TargetRef>>> =
|
||||
findByCitizen(
|
||||
citizen.id ?: error("The citizen must have an id"),
|
||||
citizen.id,
|
||||
"article",
|
||||
object : TypeReference<List<VoteEntity<Comment<UuidEntity>>>>() {},
|
||||
object : TypeReference<List<VoteEntity<Comment<TargetRef>>>>() {},
|
||||
page,
|
||||
limit
|
||||
)
|
||||
@@ -120,7 +110,7 @@ class VoteConstitution(requester: Requester) : Vote<Constitution>(requester) {
|
||||
limit: Int = 50
|
||||
): Paginated<VoteEntity<Constitution>> =
|
||||
findByCitizen(
|
||||
citizen.id ?: error("The citizen must have an id"),
|
||||
citizen.id,
|
||||
"constitution",
|
||||
object : TypeReference<List<VoteEntity<Constitution>>>() {},
|
||||
page,
|
||||
|
||||
@@ -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 <RegisterRequest> {
|
||||
val citizen = call.receive<CitizenEntity>()
|
||||
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<CitizenEntity>()
|
||||
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<SsoRequest> {
|
||||
|
||||
@@ -62,7 +62,7 @@ fun Route.citizen(
|
||||
assertCan(CHANGE_PASSWORD, it.citizen)
|
||||
val content = call.receive<ChangePasswordCitizenRequest.Content>()
|
||||
|
||||
val user = it.citizen.user ?: error("Citizen must have User")
|
||||
val user = it.citizen.user
|
||||
|
||||
user.plainPassword = content.password
|
||||
userRepository.changePassword(user)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<ConstitutionPaths.PostConstitutionRequest> {
|
||||
val constitution = call.receive<ConstitutionEntity>()
|
||||
constitution.createdBy = citizen
|
||||
val constitution = call.receive<Constitution>().create(citizen)
|
||||
assertCan(CREATE, constitution)
|
||||
|
||||
repo.upsert(constitution)
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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<Article> = followJson.deserialize()!!
|
||||
val follow: Follow<ArticleSimple> = followJson.deserialize()!!
|
||||
follow.id.toString() `should equal` "bae81585-d985-4d7a-9b58-3a13e911688a"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<ArticleRepository>().upsert(article)
|
||||
|
||||
val comment = CommentEntity(
|
||||
val comment: CommentEntity<ArticleRef> = CommentEntity(
|
||||
id = UUID.fromString(commentId),
|
||||
createdBy = citizen,
|
||||
target = article,
|
||||
|
||||
@@ -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<CitizenRepository>().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<ConstitutionRepository>().upsert(constitution)
|
||||
get<ConstitutionRepository>().upsert(constitution.create(citizen))
|
||||
}
|
||||
|
||||
Given("I have constitution with id {string} created by {string}") { id: String, username: String ->
|
||||
val citizen = get<CitizenRepository>().findByUsername(username)!!
|
||||
|
||||
val title1 = TitleEntity(
|
||||
val title1 = TitleSimple<ArticleRef>(
|
||||
name = "My Title"
|
||||
)
|
||||
|
||||
val constitution = ConstitutionEntity(
|
||||
val constitution = ConstitutionSimple<CitizenSimple, TitleSimple<ArticleRef>>(
|
||||
id = UUID.fromString(id),
|
||||
title = "hello",
|
||||
titles = listOf(title1),
|
||||
createdBy = citizen,
|
||||
anonymous = false
|
||||
titles = mutableListOf(title1),
|
||||
anonymous = false,
|
||||
createdBy = citizen
|
||||
)
|
||||
get<ConstitutionRepository>().upsert(constitution)
|
||||
}
|
||||
|
||||
@@ -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, String>(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,
|
||||
|
||||
@@ -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
|
||||
"""
|
||||
|
||||
@@ -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
|
||||
}
|
||||
"""
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user