Fix #106
@@ -48,7 +48,7 @@ data class ArticleForView(
|
||||
val lastVersion: Boolean = false
|
||||
}
|
||||
|
||||
interface ArticleForUpdateI<C : CitizenRef> : ArticleI, ArticleWithTitleI, VersionableId, TargetI, CreatedBy<C> {
|
||||
sealed interface ArticleForUpdateI<C : CitizenRef> : ArticleI, ArticleWithTitleI, VersionableId, TargetI, CreatedBy<C> {
|
||||
val anonymous: Boolean
|
||||
val content: String
|
||||
val description: String
|
||||
@@ -56,13 +56,13 @@ interface ArticleForUpdateI<C : CitizenRef> : ArticleI, ArticleWithTitleI, Versi
|
||||
val workgroup: WorkgroupRef?
|
||||
}
|
||||
|
||||
class ArticleForUpdate(
|
||||
data class ArticleForUpdate(
|
||||
override val id: UUID = UUID.randomUUID(),
|
||||
override val title: String,
|
||||
override val anonymous: Boolean = true,
|
||||
override val content: String,
|
||||
override val description: String,
|
||||
tags: List<String> = emptyList(),
|
||||
val tags: Set<String> = emptySet(),
|
||||
override val draft: Boolean = false,
|
||||
override val createdBy: CitizenRef,
|
||||
override val workgroup: WorkgroupRef? = null,
|
||||
@@ -71,12 +71,10 @@ class ArticleForUpdate(
|
||||
) : ArticleRef(id),
|
||||
ArticleForUpdateI<CitizenRef>,
|
||||
ArticleAuthI<CitizenRef>,
|
||||
VersionableId {
|
||||
val tags: List<String> = tags.distinct()
|
||||
}
|
||||
VersionableId
|
||||
|
||||
class ArticleForListing(
|
||||
id: UUID? = null,
|
||||
data class ArticleForListing(
|
||||
override val id: UUID = UUID.randomUUID(),
|
||||
override val title: String,
|
||||
override val createdBy: CitizenCreator,
|
||||
override val workgroup: WorkgroupCart? = null,
|
||||
@@ -90,7 +88,7 @@ class ArticleForListing(
|
||||
CreatedAt by CreatedAt.Imp(),
|
||||
CreatedBy<CitizenCartI>
|
||||
|
||||
interface ArticleForListingI : ArticleWithTitleI, CreatedBy<CitizenCartI> {
|
||||
sealed interface ArticleForListingI : ArticleWithTitleI, CreatedBy<CitizenCartI> {
|
||||
val workgroup: WorkgroupCartI?
|
||||
}
|
||||
|
||||
@@ -98,13 +96,13 @@ open class ArticleRef(
|
||||
id: UUID? = null
|
||||
) : ArticleI, TargetRef(id)
|
||||
|
||||
interface ArticleI : EntityI, TargetI
|
||||
sealed interface ArticleI : EntityI, TargetI
|
||||
|
||||
interface ArticleWithTitleI : ArticleI {
|
||||
sealed interface ArticleWithTitleI : ArticleI {
|
||||
val title: String
|
||||
}
|
||||
|
||||
interface ArticleAuthI<U : CitizenI> :
|
||||
sealed interface ArticleAuthI<U : CitizenI> :
|
||||
ArticleI,
|
||||
CreatedBy<U>,
|
||||
DeletedAt {
|
||||
|
||||
@@ -65,7 +65,7 @@ object FindArticleVersions {
|
||||
it.validate().badRequestIfNotValid()
|
||||
|
||||
repo.findVersions(it)
|
||||
.apply { ac.assert { canView(result, citizenOrNull) } }
|
||||
.apply { ac.canView(result, citizenOrNull).assert() }
|
||||
.run {
|
||||
call.respond(
|
||||
toOutput { a: ArticleForListing ->
|
||||
|
||||
@@ -76,7 +76,7 @@ object FindArticles {
|
||||
it.validate().badRequestIfNotValid()
|
||||
|
||||
repo.findArticles(it)
|
||||
.apply { ac.assert { canView(result, citizenOrNull) } }
|
||||
.apply { ac.canView(result, citizenOrNull).assert() }
|
||||
.let {
|
||||
call.respond(
|
||||
it.toOutput {
|
||||
|
||||
@@ -27,7 +27,7 @@ object GetOneArticle {
|
||||
fun Route.getOneArticle(viewRepository: ArticleViewRepository<ArticleForView>, ac: ArticleAccessControl, repo: ArticleRepository) {
|
||||
get<ArticleRequest> {
|
||||
val article: ArticleForView = repo.findById(it.article.id) ?: throw NotFoundException("Article ${it.article.id} not found")
|
||||
ac.assert { canView(article, citizenOrNull) }
|
||||
ac.canView(article, citizenOrNull).assert()
|
||||
|
||||
call.respond(
|
||||
article.let { a ->
|
||||
|
||||
@@ -37,7 +37,7 @@ object UpsertArticle {
|
||||
val anonymous: Boolean = true,
|
||||
val content: String,
|
||||
val description: String,
|
||||
val tags: List<String> = emptyList(),
|
||||
val tags: Set<String> = emptySet(),
|
||||
val draft: Boolean = false,
|
||||
val versionId: UUID,
|
||||
val workgroup: WorkgroupRef? = null,
|
||||
@@ -83,7 +83,7 @@ object UpsertArticle {
|
||||
post<UpsertArticleRequest> {
|
||||
mustBeAuth()
|
||||
val article = call.convertRequestToEntity()
|
||||
ac.assert { canUpsert(article, citizenOrNull) }
|
||||
ac.canUpsert(article, citizenOrNull).assert()
|
||||
repo.upsert(article)?.let { a ->
|
||||
call.respond(
|
||||
object {
|
||||
|
||||
@@ -9,35 +9,45 @@ import io.ktor.auth.Principal
|
||||
import org.joda.time.DateTime
|
||||
import java.util.UUID
|
||||
|
||||
class UserForCreate(
|
||||
id: UUID = UUID.randomUUID(),
|
||||
username: String,
|
||||
data class UserForCreate(
|
||||
override val id: UUID = UUID.randomUUID(),
|
||||
override val username: String,
|
||||
override val password: String,
|
||||
blockedAt: DateTime? = null,
|
||||
roles: List<Roles> = emptyList()
|
||||
) : User(id, username, blockedAt, roles),
|
||||
UserWithPasswordI
|
||||
override val blockedAt: DateTime? = null,
|
||||
override val roles: Set<Roles> = emptySet()
|
||||
) : UserForViewI,
|
||||
UserWithPasswordI,
|
||||
CreatedAt by CreatedAt.Imp(),
|
||||
UpdatedAt by UpdatedAt.Imp()
|
||||
|
||||
open class User(
|
||||
id: UUID = UUID.randomUUID(),
|
||||
override var username: String,
|
||||
var blockedAt: DateTime? = null,
|
||||
var roles: List<Roles> = emptyList()
|
||||
data class User(
|
||||
override val id: UUID = UUID.randomUUID(),
|
||||
override val username: String,
|
||||
override val blockedAt: DateTime? = null,
|
||||
override val roles: Set<Roles> = emptySet()
|
||||
) : UserRef(id),
|
||||
UserForViewI,
|
||||
UserWithUsername,
|
||||
CreatedAt by CreatedAt.Imp(),
|
||||
UpdatedAt by UpdatedAt.Imp()
|
||||
|
||||
sealed interface UserForViewI :
|
||||
UserI,
|
||||
UserWithUsername,
|
||||
UserForAuthI,
|
||||
CreatedAt,
|
||||
UpdatedAt
|
||||
|
||||
class UserCreator(
|
||||
id: UUID = UUID.randomUUID(),
|
||||
override val username: String,
|
||||
) : UserRef(id), UserWithUsername
|
||||
|
||||
interface UserWithUsername : UserI {
|
||||
sealed interface UserWithUsername : UserI {
|
||||
val username: String
|
||||
}
|
||||
|
||||
interface UserWithPasswordI : UserI {
|
||||
sealed interface UserWithPasswordI : UserI {
|
||||
val password: String
|
||||
}
|
||||
|
||||
@@ -51,11 +61,11 @@ open class UserRef(
|
||||
id: UUID = UUID.randomUUID()
|
||||
) : UserI, Entity(id)
|
||||
|
||||
interface UserI : EntityI, Principal {
|
||||
sealed interface UserI : EntityI, Principal {
|
||||
enum class Roles { ROLE_USER, ROLE_ADMIN }
|
||||
}
|
||||
|
||||
interface UserForAuthI : UserI {
|
||||
var roles: List<Roles>
|
||||
var blockedAt: DateTime?
|
||||
sealed interface UserForAuthI : UserI {
|
||||
val roles: Set<Roles>
|
||||
val blockedAt: DateTime?
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ object Register {
|
||||
user = UserForCreate(
|
||||
username = user.username,
|
||||
password = user.password,
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
roles = setOf(UserI.Roles.ROLE_USER)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -17,19 +17,19 @@ import fr.postgresjson.entity.Serializable
|
||||
import org.joda.time.DateTime
|
||||
import java.util.UUID
|
||||
|
||||
class CitizenForCreate(
|
||||
data class CitizenForCreate(
|
||||
val name: Name,
|
||||
val email: String,
|
||||
val birthday: DateTime,
|
||||
val voteAnonymous: Boolean = true,
|
||||
val followAnonymous: Boolean = true,
|
||||
override val user: UserForCreate,
|
||||
id: UUID = UUID.randomUUID(),
|
||||
override val id: UUID = UUID.randomUUID(),
|
||||
) : CitizenI,
|
||||
CitizenRefWithUser(id, user),
|
||||
CitizenWithUserI by CitizenRefWithUser(id, user),
|
||||
CreatedAt by CreatedAt.Imp()
|
||||
|
||||
class Citizen(
|
||||
data class Citizen(
|
||||
override val id: UUID = UUID.randomUUID(),
|
||||
override val name: Name,
|
||||
override val email: String,
|
||||
@@ -37,7 +37,7 @@ class Citizen(
|
||||
override val voteAnonymous: Boolean = true,
|
||||
override val followAnonymous: Boolean = true,
|
||||
override val user: User,
|
||||
deletedAt: DateTime? = null
|
||||
override val deletedAt: DateTime? = null
|
||||
) : CitizenWithEmail,
|
||||
CitizenCreatorI,
|
||||
CitizenWithUserI,
|
||||
@@ -62,10 +62,11 @@ data class CitizenCreator(
|
||||
override val user: UserCreator,
|
||||
override val deletedAt: DateTime? = null
|
||||
) : CitizenCreatorI,
|
||||
CitizenRefWithUser(id, user),
|
||||
CitizenI,
|
||||
CitizenWithUserI by CitizenRefWithUser(id, user),
|
||||
DeletedAt by DeletedAt.Imp(deletedAt)
|
||||
|
||||
interface CitizenCreatorI : CitizenWithUserI, CitizenWithEmail, CitizenCartI, DeletedAt {
|
||||
sealed interface CitizenCreatorI : CitizenWithUserI, CitizenWithEmail, CitizenCartI, DeletedAt {
|
||||
override val id: UUID
|
||||
override val name: Name
|
||||
override val email: String
|
||||
@@ -75,8 +76,8 @@ interface CitizenCreatorI : CitizenWithUserI, CitizenWithEmail, CitizenCartI, De
|
||||
override val deletedAt: DateTime?
|
||||
}
|
||||
|
||||
class CitizenCart(
|
||||
id: UUID = UUID.randomUUID(),
|
||||
data class CitizenCart(
|
||||
override val id: UUID = UUID.randomUUID(),
|
||||
override val name: Name,
|
||||
override val user: UserRef,
|
||||
override val deletedAt: DateTime? = null,
|
||||
@@ -84,13 +85,13 @@ class CitizenCart(
|
||||
CitizenCartI,
|
||||
DeletedAt by DeletedAt.Imp(deletedAt)
|
||||
|
||||
interface CitizenCartI : CitizenI, CitizenWithUserI {
|
||||
sealed interface CitizenCartI : CitizenI, CitizenWithUserI {
|
||||
val name: Name
|
||||
}
|
||||
|
||||
open class CitizenRefWithUser(
|
||||
id: UUID = UUID.randomUUID(),
|
||||
override val user: UserRef
|
||||
data class CitizenRefWithUser(
|
||||
override val id: UUID = UUID.randomUUID(),
|
||||
override val user: UserI
|
||||
) : CitizenWithUserI,
|
||||
CitizenRef(id)
|
||||
|
||||
@@ -99,7 +100,7 @@ open class CitizenRef(
|
||||
) : TargetRef(id),
|
||||
CitizenI
|
||||
|
||||
interface CitizenI : EntityI, TargetI {
|
||||
sealed interface CitizenI : EntityI, TargetI {
|
||||
data class Name(
|
||||
override val firstName: String,
|
||||
override val lastName: String,
|
||||
@@ -114,10 +115,10 @@ interface CitizenI : EntityI, TargetI {
|
||||
}
|
||||
}
|
||||
|
||||
interface CitizenWithUserI : CitizenI {
|
||||
sealed interface CitizenWithUserI : CitizenI {
|
||||
val user: UserI
|
||||
}
|
||||
|
||||
interface CitizenWithEmail : CitizenI {
|
||||
sealed interface CitizenWithEmail : CitizenI {
|
||||
val email: String
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ object ChangeMyPassword {
|
||||
mustBeAuth()
|
||||
val content = call.receiveOrBadRequest<ChangePasswordCitizenRequest.Input>()
|
||||
.apply { validate().badRequestIfNotValid() }
|
||||
ac.assert { canChangePassword(it.citizen, citizenOrNull) }
|
||||
ac.canChangePassword(it.citizen, citizenOrNull).assert()
|
||||
userRepository.findByCredentials(UserPasswordCredential(citizen.user.username, content.oldPassword)) ?: throw BadRequestException("Bad Password")
|
||||
userRepository.changePassword(
|
||||
UserWithPassword(
|
||||
|
||||
@@ -55,7 +55,7 @@ object FindCitizens {
|
||||
mustBeAuth()
|
||||
it.validate().badRequestIfNotValid()
|
||||
val citizens = repo.find(it.page, it.limit, it.sort, it.direction, it.search)
|
||||
ac.assert { canView(citizens.result, citizenOrNull) }
|
||||
ac.canView(citizens.result, citizenOrNull).assert()
|
||||
call.respond(
|
||||
citizens.toOutput { c: CitizenCreator ->
|
||||
object {
|
||||
|
||||
@@ -28,7 +28,7 @@ object GetCurrentCitizen {
|
||||
if (currentUser === null) {
|
||||
call.respond(HttpStatusCode.Unauthorized)
|
||||
} else {
|
||||
ac.assert { canView(currentUser, citizenOrNull) }
|
||||
ac.canView(currentUser, citizenOrNull).assert()
|
||||
call.respond(
|
||||
object {
|
||||
val id: UUID = citizen.id
|
||||
|
||||
@@ -29,7 +29,7 @@ object GetOneCitizen {
|
||||
get<CitizenRequest> {
|
||||
mustBeAuth()
|
||||
val citizen = citizenRepository.findById(it.citizen.id) ?: throw NotFoundException("Citizen not found ${it.citizen.id}")
|
||||
ac.assert { canView(citizen, citizenOrNull) }
|
||||
ac.canView(citizen, citizenOrNull).assert()
|
||||
|
||||
call.respond(
|
||||
object {
|
||||
|
||||
@@ -51,7 +51,7 @@ object CreateCommentArticle {
|
||||
content = content
|
||||
)
|
||||
}.let { comment ->
|
||||
ac.assert { canCreate(comment, citizenOrNull) }
|
||||
ac.canCreate(comment, citizenOrNull).assert()
|
||||
repo.comment(comment)
|
||||
|
||||
call.respond(
|
||||
|
||||
@@ -58,7 +58,7 @@ object GetArticleComments {
|
||||
|
||||
val comments = repo.findByTarget(it.article, it.page, it.limit, it.sort)
|
||||
if (comments.result.isNotEmpty()) {
|
||||
ac.assert { canView(comments.result, citizenOrNull) }
|
||||
ac.canView(comments.result, citizenOrNull).assert()
|
||||
}
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
|
||||
@@ -28,7 +28,7 @@ object GetCitizenArticleComments {
|
||||
get<CitizenCommentArticleRequest> {
|
||||
mustBeAuth()
|
||||
repo.findByCitizen(it.citizen).let { comments ->
|
||||
ac.assert { canView(comments.result, citizenOrNull) }
|
||||
ac.canView(comments.result, citizenOrNull).assert()
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
comments.toOutput { comment ->
|
||||
|
||||
@@ -53,7 +53,7 @@ object CreateConstitutionComment {
|
||||
content = content
|
||||
)
|
||||
}.let { comment ->
|
||||
ac.assert { canCreate(comment, citizenOrNull) }
|
||||
ac.canCreate(comment, citizenOrNull).assert()
|
||||
repo.comment(comment)
|
||||
|
||||
call.respond(
|
||||
|
||||
@@ -28,7 +28,7 @@ object GetCitizenCommentConstitution {
|
||||
get<GetCitizenCommentConstitutionRequest> {
|
||||
mustBeAuth()
|
||||
val comments = repo.findByCitizen(it.citizen)
|
||||
ac.assert { canView(comments.result, citizenOrNull) }
|
||||
ac.canView(comments.result, citizenOrNull).assert()
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
comments.toOutput { comment ->
|
||||
|
||||
@@ -57,7 +57,7 @@ object GetConstitutionComment {
|
||||
it.validate().badRequestIfNotValid()
|
||||
|
||||
val comments = repo.findByTarget(it.constitution)
|
||||
ac.assert { canView(comments.result, citizenOrNull) }
|
||||
ac.canView(comments.result, citizenOrNull).assert()
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
comments.toOutput { comment ->
|
||||
|
||||
@@ -16,8 +16,8 @@ import fr.dcproject.component.vote.entity.VotableImp
|
||||
import org.joda.time.DateTime
|
||||
import java.util.UUID
|
||||
|
||||
class CommentForView<T : TargetI, C : CitizenCreatorI>(
|
||||
id: UUID = UUID.randomUUID(),
|
||||
data class CommentForView<T : TargetI, C : CitizenCreatorI>(
|
||||
override val id: UUID = UUID.randomUUID(),
|
||||
override val createdBy: C,
|
||||
override val target: T,
|
||||
override var content: String,
|
||||
@@ -30,7 +30,7 @@ class CommentForView<T : TargetI, C : CitizenCreatorI>(
|
||||
CommentWithTargetI<T>,
|
||||
CreatedBy<C> by CreatedBy.Imp(createdBy),
|
||||
UpdatedAt by UpdatedAt.Imp(),
|
||||
DeletedAt by DeletedAt.Imp(),
|
||||
DeletedAt,
|
||||
Votable by VotableImp(),
|
||||
TargetI {
|
||||
constructor(
|
||||
@@ -50,9 +50,9 @@ open class CommentForUpdate<T : TargetI, C : CitizenI>(
|
||||
override val createdBy: C,
|
||||
override val target: T,
|
||||
open var content: String,
|
||||
override val parent: CommentParent<T>? = null,
|
||||
override val parent: CommentParentI<T>? = null,
|
||||
override val deletedAt: DateTime? = null
|
||||
) : CommentParent<T>(id, deletedAt, target),
|
||||
) : CommentParentI<T> by CommentParent(id, deletedAt, target),
|
||||
CommentWithParentI<T>,
|
||||
ExtraI<T, C>,
|
||||
CommentWithTargetI<T>,
|
||||
@@ -62,7 +62,7 @@ open class CommentForUpdate<T : TargetI, C : CitizenI>(
|
||||
TargetI {
|
||||
constructor(
|
||||
createdBy: C,
|
||||
parent: CommentParent<T>,
|
||||
parent: CommentParentI<T>,
|
||||
content: String,
|
||||
id: UUID? = null,
|
||||
) : this(
|
||||
@@ -74,21 +74,21 @@ open class CommentForUpdate<T : TargetI, C : CitizenI>(
|
||||
)
|
||||
}
|
||||
|
||||
open class CommentParent<T : TargetI>(
|
||||
data class CommentParent<T : TargetI>(
|
||||
override val id: UUID,
|
||||
override val deletedAt: DateTime?,
|
||||
override val target: T
|
||||
) : CommentRef(id),
|
||||
CommentParentI<T>
|
||||
|
||||
interface CommentParentI<T : TargetI> : CommentI, DeletedAt, CommentWithTargetI<T>
|
||||
sealed interface CommentParentI<T : TargetI> : CommentI, DeletedAt, CommentWithTargetI<T>
|
||||
|
||||
interface CommentWithTargetI<T : TargetI> : CommentI, TargetI, HasTarget<T>
|
||||
|
||||
interface CommentWithParentI<T : TargetI> {
|
||||
val parent: CommentParent<T>?
|
||||
val parent: CommentParentI<T>?
|
||||
}
|
||||
|
||||
open class CommentRef(id: UUID = UUID.randomUUID()) : CommentI, TargetRef(id)
|
||||
|
||||
interface CommentI : EntityI
|
||||
sealed interface CommentI : EntityI
|
||||
|
||||
@@ -32,26 +32,21 @@ abstract class CommentRepositoryAbs<T : TargetI>(override var requester: Request
|
||||
parentId: UUID,
|
||||
page: Int = 1,
|
||||
limit: Int = 50
|
||||
): Paginated<CommentForView<T, CitizenCreatorI>> {
|
||||
return requester.run {
|
||||
getFunction("find_comments_by_parent")
|
||||
): Paginated<CommentForView<T, CitizenCreatorI>> = requester
|
||||
.getFunction("find_comments_by_parent")
|
||||
.select<CommentForView<T, CitizenCreator>>(
|
||||
page,
|
||||
limit,
|
||||
"parent_id" to parentId
|
||||
)
|
||||
as Paginated<CommentForView<T, CitizenCreatorI>>
|
||||
}
|
||||
}
|
||||
|
||||
open fun findByTarget(
|
||||
target: EntityI,
|
||||
page: Int = 1,
|
||||
limit: Int = 50,
|
||||
sort: String = "createdAt"
|
||||
): Paginated<CommentForView<T, CitizenCreatorI>> {
|
||||
return findByTarget(target.id, page, limit, sort)
|
||||
}
|
||||
): Paginated<CommentForView<T, CitizenCreatorI>> = findByTarget(target.id, page, limit, sort)
|
||||
|
||||
open fun findByTarget(
|
||||
targetId: UUID,
|
||||
@@ -85,41 +80,33 @@ abstract class CommentRepositoryAbs<T : TargetI>(override var requester: Request
|
||||
}
|
||||
|
||||
class CommentRepository(requester: Requester) : CommentRepositoryAbs<TargetRef>(requester) {
|
||||
override fun findById(id: UUID): CommentForView<TargetRef, CitizenCreatorI>? {
|
||||
return requester
|
||||
override fun findById(id: UUID): CommentForView<TargetRef, CitizenCreatorI>? = requester
|
||||
.getFunction("find_comment_by_id")
|
||||
.selectOne<CommentForView<TargetRef, CitizenCreator>>(mapOf("id" to id))
|
||||
as CommentForView<TargetRef, CitizenCreatorI>?
|
||||
}
|
||||
|
||||
override fun findByCitizen(
|
||||
citizen: CitizenI,
|
||||
page: Int,
|
||||
limit: Int
|
||||
): Paginated<CommentForView<TargetRef, CitizenCreatorI>> {
|
||||
return requester.run {
|
||||
getFunction("find_comments_by_citizen")
|
||||
): Paginated<CommentForView<TargetRef, CitizenCreatorI>> = requester
|
||||
.getFunction("find_comments_by_citizen")
|
||||
.select<CommentForView<TargetRef, CitizenCreator>>(
|
||||
page,
|
||||
limit,
|
||||
"created_by_id" to citizen.id
|
||||
) as Paginated<CommentForView<TargetRef, CitizenCreatorI>>
|
||||
}
|
||||
}
|
||||
|
||||
override fun findByParent(
|
||||
parentId: UUID,
|
||||
page: Int,
|
||||
limit: Int
|
||||
): Paginated<CommentForView<TargetRef, CitizenCreatorI>> {
|
||||
return requester.run {
|
||||
getFunction("find_comments_by_parent")
|
||||
): Paginated<CommentForView<TargetRef, CitizenCreatorI>> = requester
|
||||
.getFunction("find_comments_by_parent")
|
||||
.select<CommentForView<TargetRef, CitizenCreator>>(
|
||||
page,
|
||||
limit,
|
||||
"parent_id" to parentId
|
||||
)
|
||||
as Paginated<CommentForView<TargetRef, CitizenCreatorI>>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ object CreateComment {
|
||||
parent = parent,
|
||||
)
|
||||
}.let { newComment ->
|
||||
ac.assert { canCreate(newComment, citizenOrNull) }
|
||||
ac.canCreate(newComment, citizenOrNull).assert()
|
||||
repo.comment(newComment)
|
||||
call.respond(HttpStatusCode.Created, newComment.toOutput())
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ object EditComment {
|
||||
put<EditCommentRequest> {
|
||||
mustBeAuth()
|
||||
val commentOld = repo.findById(it.comment.id) ?: throw NotFoundException("Comment not found")
|
||||
ac.assert { canUpdate(commentOld, citizenOrNull) }
|
||||
ac.canUpdate(commentOld, citizenOrNull).assert()
|
||||
|
||||
call.receiveOrBadRequest<EditCommentRequest.Input>()
|
||||
.apply { validate().badRequestIfNotValid() }
|
||||
|
||||
@@ -39,7 +39,7 @@ object GetCommentChildren {
|
||||
it.limit
|
||||
)
|
||||
|
||||
ac.assert { canView(comments.result, citizenOrNull) }
|
||||
ac.canView(comments.result, citizenOrNull).assert()
|
||||
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
|
||||
@@ -27,7 +27,7 @@ object GetOneComment {
|
||||
fun Route.getOneComment(repo: CommentRepository, ac: CommentAccessControl) {
|
||||
get<CommentRequest> {
|
||||
val comment = repo.findById(it.comment.id) ?: throw NotFoundException("Comment ${it.comment.id} not found")
|
||||
ac.assert { canView(comment, citizenOrNull) }
|
||||
ac.canView(comment, citizenOrNull).assert()
|
||||
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
|
||||
@@ -89,7 +89,7 @@ object CreateConstitution {
|
||||
post<PostConstitutionRequest> {
|
||||
mustBeAuth()
|
||||
getNewConstitution(call.receiveOrBadRequest(), citizen).let {
|
||||
ac.assert { canCreate(it, citizenOrNull) }
|
||||
ac.canCreate(it, citizenOrNull).assert()
|
||||
val c = repo.upsert(it) ?: error("Unable to create Constitution")
|
||||
call.respond(
|
||||
HttpStatusCode.Created,
|
||||
|
||||
@@ -54,7 +54,7 @@ object FindConstitutions {
|
||||
get<FindConstitutionsRequest> {
|
||||
it.validate().badRequestIfNotValid()
|
||||
val constitutions = repo.find(it.page, it.limit, it.sort, it.direction, it.search)
|
||||
ac.assert { canView(constitutions.result, citizenOrNull) }
|
||||
ac.canView(constitutions.result, citizenOrNull).assert()
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
constitutions.toOutput { c ->
|
||||
|
||||
@@ -27,7 +27,7 @@ object GetConstitution {
|
||||
fun Route.getConstitution(ac: ConstitutionAccessControl, constitutionRepo: ConstitutionRepository) {
|
||||
get<GetConstitutionRequest> {
|
||||
val constitution = constitutionRepo.findById(it.constitution.id) ?: throw NotFoundException("Unable to find constitution ${it.constitution.id}")
|
||||
ac.assert { canView(constitution, citizenOrNull) }
|
||||
ac.canView(constitution, citizenOrNull).assert()
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
constitution.let { c ->
|
||||
|
||||
@@ -8,19 +8,18 @@ import fr.dcproject.common.entity.HasTarget
|
||||
import fr.dcproject.common.entity.TargetI
|
||||
import fr.dcproject.component.citizen.database.CitizenCreator
|
||||
import fr.dcproject.component.citizen.database.CitizenI
|
||||
import fr.dcproject.component.citizen.database.CitizenRef
|
||||
import java.util.UUID
|
||||
|
||||
open class FollowForView<T : TargetI>(
|
||||
id: UUID = UUID.randomUUID(),
|
||||
data class FollowForView<T : TargetI>(
|
||||
override val id: UUID = UUID.randomUUID(),
|
||||
override val createdBy: CitizenCreator,
|
||||
override var target: T
|
||||
) : ExtraI<T, CitizenRef>,
|
||||
) : ExtraI<T, CitizenI>,
|
||||
FollowRef(id),
|
||||
Created<CitizenRef> by Created.Imp(createdBy)
|
||||
Created<CitizenI> by Created.Imp(createdBy)
|
||||
|
||||
class FollowForUpdate<T : TargetI, C : CitizenI>(
|
||||
id: UUID = UUID.randomUUID(),
|
||||
data class FollowForUpdate<T : TargetI, C : CitizenI>(
|
||||
override val id: UUID = UUID.randomUUID(),
|
||||
override val target: T,
|
||||
override val createdBy: C
|
||||
) : FollowRef(id),
|
||||
@@ -31,4 +30,4 @@ open class FollowRef(
|
||||
override val id: UUID
|
||||
) : FollowI
|
||||
|
||||
interface FollowI : EntityI
|
||||
sealed interface FollowI : EntityI
|
||||
|
||||
@@ -28,7 +28,7 @@ object FollowArticle {
|
||||
post<ArticleFollowRequest> {
|
||||
mustBeAuth()
|
||||
val follow = FollowForUpdate(target = it.article, createdBy = this.citizen)
|
||||
ac.assert { canCreate(follow, citizenOrNull) }
|
||||
ac.canCreate(follow, citizenOrNull).assert()
|
||||
repo.follow(follow)
|
||||
call.respond(HttpStatusCode.Created)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ object GetFollowArticle {
|
||||
fun Route.getFollowArticle(repo: FollowArticleRepository, ac: FollowAccessControl) {
|
||||
get<ArticleFollowRequest> {
|
||||
repo.findFollow(citizen, it.article)?.let { follow ->
|
||||
ac.assert { canView(follow, citizenOrNull) }
|
||||
ac.canView(follow, citizenOrNull).assert()
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
follow.toOutput()
|
||||
|
||||
@@ -28,7 +28,7 @@ object GetMyFollowsArticle {
|
||||
get<CitizenFollowArticleRequest> {
|
||||
mustBeAuth()
|
||||
val follows = repo.findByCitizen(it.citizen)
|
||||
ac.assert { canView(follows.result, citizenOrNull) }
|
||||
ac.canView(follows.result, citizenOrNull).assert()
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
follows.toOutput { f ->
|
||||
|
||||
@@ -28,7 +28,7 @@ object UnfollowArticle {
|
||||
delete<ArticleFollowRequest> {
|
||||
mustBeAuth()
|
||||
val follow = FollowForUpdate(target = it.article, createdBy = this.citizen)
|
||||
ac.assert { canDelete(follow, citizenOrNull) }
|
||||
ac.canDelete(follow, citizenOrNull).assert()
|
||||
repo.unfollow(follow)
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ object FollowCitizen {
|
||||
post<CitizenFollowRequest> {
|
||||
mustBeAuth()
|
||||
val follow = FollowForUpdate(target = it.citizen, createdBy = this.citizen)
|
||||
ac.assert { canCreate(follow, citizenOrNull) }
|
||||
ac.canCreate(follow, citizenOrNull).assert()
|
||||
repo.follow(follow)
|
||||
call.respond(HttpStatusCode.Created)
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ object GetFollowCitizen {
|
||||
fun Route.getFollowCitizen(repo: FollowCitizenRepository, ac: FollowAccessControl) {
|
||||
get<CitizenFollowRequest> {
|
||||
repo.findFollow(citizen, it.citizen)?.let { follow ->
|
||||
ac.assert { canView(follow, citizenOrNull) }
|
||||
ac.canView(follow, citizenOrNull).assert()
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
follow.toOutput()
|
||||
|
||||
@@ -28,7 +28,7 @@ object GetMyFollowsCitizen {
|
||||
get<CitizenFollowCitizenRequest> {
|
||||
mustBeAuth()
|
||||
val follows = repo.findByCitizen(it.citizen)
|
||||
ac.assert { canView(follows.result, citizenOrNull) }
|
||||
ac.canView(follows.result, citizenOrNull).assert()
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
follows.toOutput { f ->
|
||||
|
||||
@@ -28,7 +28,7 @@ object UnfollowCitizen {
|
||||
delete<CitizenFollowRequest> {
|
||||
mustBeAuth()
|
||||
val follow = FollowForUpdate(target = it.citizen, createdBy = this.citizen)
|
||||
ac.assert { canDelete(follow, citizenOrNull) }
|
||||
ac.canDelete(follow, citizenOrNull).assert()
|
||||
repo.unfollow(follow)
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ object FollowConstitution {
|
||||
post<ConstitutionFollowRequest> {
|
||||
mustBeAuth()
|
||||
val follow = FollowForUpdate(target = it.constitution, createdBy = this.citizen)
|
||||
ac.assert { canCreate(follow, citizenOrNull) }
|
||||
ac.canCreate(follow, citizenOrNull).assert()
|
||||
repo.follow(follow)
|
||||
call.respond(HttpStatusCode.Created)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ object GetFollowConstitution {
|
||||
fun Route.getFollowConstitution(repo: FollowConstitutionRepository, ac: FollowAccessControl) {
|
||||
get<ConstitutionFollowRequest> {
|
||||
repo.findFollow(citizen, it.constitution)?.let { follow ->
|
||||
ac.assert { canView(follow, citizenOrNull) }
|
||||
ac.canView(follow, citizenOrNull).assert()
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
follow.toOutput()
|
||||
|
||||
@@ -28,7 +28,7 @@ object GetMyFollowsConstitution {
|
||||
get<CitizenFollowConstitutionRequest> {
|
||||
mustBeAuth()
|
||||
val follows = repo.findByCitizen(it.citizen)
|
||||
ac.assert { canView(follows.result, citizenOrNull) }
|
||||
ac.canView(follows.result, citizenOrNull).assert()
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
follows.toOutput { f ->
|
||||
|
||||
@@ -28,7 +28,7 @@ object UnfollowConstitution {
|
||||
delete<ConstitutionUnfollowRequest> {
|
||||
mustBeAuth()
|
||||
val follow = FollowForUpdate(target = it.constitution, createdBy = this.citizen)
|
||||
ac.assert { canDelete(follow, citizenOrNull) }
|
||||
ac.canDelete(follow, citizenOrNull).assert()
|
||||
repo.unfollow(follow)
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
}
|
||||
|
||||
@@ -53,11 +53,11 @@ open class NotificationMessage(
|
||||
}
|
||||
|
||||
open class EntityNotificationMessage <E : Entity> (
|
||||
val target: E,
|
||||
open val target: E,
|
||||
type: String,
|
||||
val action: String
|
||||
) : NotificationMessage(type)
|
||||
|
||||
class ArticleUpdateNotificationMessage(
|
||||
target: ArticleForView
|
||||
data class ArticleUpdateNotificationMessage(
|
||||
override val target: ArticleForView
|
||||
) : EntityNotificationMessage<ArticleForView>(target, "article", "update")
|
||||
|
||||
@@ -3,7 +3,7 @@ package fr.dcproject.component.notification.email.content
|
||||
import fr.dcproject.component.article.database.ArticleWithTitleI
|
||||
import fr.dcproject.component.citizen.database.Citizen
|
||||
|
||||
class ArticleNotificationEmailContent(
|
||||
data class ArticleNotificationEmailContent(
|
||||
private val citizen: Citizen,
|
||||
private val target: ArticleWithTitleI,
|
||||
private val domain: String,
|
||||
|
||||
@@ -2,7 +2,7 @@ package fr.dcproject.component.notification.email.content
|
||||
|
||||
import fr.dcproject.component.citizen.database.Citizen
|
||||
|
||||
class CitizenNotificationEmailContent(
|
||||
data class CitizenNotificationEmailContent(
|
||||
private val citizen: Citizen,
|
||||
private val target: Citizen,
|
||||
private val domain: String,
|
||||
|
||||
@@ -13,8 +13,8 @@ import fr.dcproject.component.citizen.database.CitizenI
|
||||
import fr.dcproject.component.citizen.database.CitizenRef
|
||||
import java.util.UUID
|
||||
|
||||
open class Opinion<T : TargetI>(
|
||||
id: UUID = UUID.randomUUID(),
|
||||
data class Opinion<T : TargetI>(
|
||||
override val id: UUID = UUID.randomUUID(),
|
||||
override val createdBy: CitizenCreator,
|
||||
override val target: T,
|
||||
val choice: OpinionChoice
|
||||
@@ -39,4 +39,4 @@ open class OpinionRef(
|
||||
override val id: UUID
|
||||
) : OpinionI, TargetRef(id)
|
||||
|
||||
interface OpinionI : EntityI
|
||||
sealed interface OpinionI : EntityI
|
||||
|
||||
@@ -7,6 +7,4 @@ interface Opinionable {
|
||||
val opinions: Opinions
|
||||
}
|
||||
|
||||
class OpinionableImp : Opinionable {
|
||||
override var opinions: OpinionsMutable = mutableMapOf()
|
||||
}
|
||||
data class OpinionableImp(override var opinions: OpinionsMutable = mutableMapOf()) : Opinionable
|
||||
|
||||
@@ -34,7 +34,7 @@ object GetCitizenOpinions {
|
||||
get<CitizenOpinions> {
|
||||
mustBeAuth()
|
||||
val opinionsEntities: List<Opinion<ArticleRef>> = repo.findCitizenOpinionsByTargets(it.citizen, it.id)
|
||||
ac.assert { canView(opinionsEntities, citizenOrNull) }
|
||||
ac.canView(opinionsEntities, citizenOrNull).assert()
|
||||
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
|
||||
@@ -55,7 +55,7 @@ object GetMyOpinionsArticle {
|
||||
it.validate().badRequestIfNotValid()
|
||||
|
||||
val opinions: Paginated<Opinion<TargetRef>> = repo.findCitizenOpinions(citizen, it.page, it.limit)
|
||||
ac.assert { canView(opinions.result, citizenOrNull) }
|
||||
ac.canView(opinions.result, citizenOrNull).assert()
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
opinions.toOutput { it.toOutput() }
|
||||
|
||||
@@ -25,7 +25,7 @@ object GetOpinionChoice {
|
||||
fun Route.getOpinionChoice(ac: OpinionChoiceAccessControl, opinionChoiceRepository: OpinionChoiceRepository) {
|
||||
get<OpinionChoiceRequest> {
|
||||
val opinionChoice = opinionChoiceRepository.findOpinionChoiceById(it.opinionChoice.id) ?: throw NotFoundException("OpinionChoice ${it.opinionChoice.id} not found")
|
||||
ac.assert { canView(it.opinionChoice, citizenOrNull) }
|
||||
ac.canView(it.opinionChoice, citizenOrNull).assert()
|
||||
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
|
||||
@@ -20,7 +20,7 @@ object GetOpinionChoices {
|
||||
fun Route.getOpinionChoices(repo: OpinionChoiceRepository, ac: OpinionChoiceAccessControl) {
|
||||
get<OpinionChoicesRequest> {
|
||||
val opinionChoices = repo.findOpinionsChoices(it.targets)
|
||||
ac.assert { canView(opinionChoices, citizenOrNull) }
|
||||
ac.canView(opinionChoices, citizenOrNull).assert()
|
||||
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
|
||||
@@ -43,7 +43,7 @@ object OpinionArticle {
|
||||
createdBy = citizen
|
||||
)
|
||||
}.let { opinions ->
|
||||
ac.assert { canCreate(opinions, citizenOrNull) }
|
||||
ac.canCreate(opinions, citizenOrNull).assert()
|
||||
repo.updateOpinions(opinions)
|
||||
}.let {
|
||||
call.respond(
|
||||
|
||||
@@ -2,7 +2,7 @@ package fr.dcproject.component.views.dto
|
||||
|
||||
import fr.dcproject.component.views.entity.ViewAggregation
|
||||
|
||||
class ViewAggregation(
|
||||
data class ViewAggregation(
|
||||
val total: Int,
|
||||
val unique: Int
|
||||
) {
|
||||
|
||||
@@ -3,7 +3,7 @@ package fr.dcproject.component.views.entity
|
||||
import fr.dcproject.common.entity.UpdatedAt
|
||||
import fr.postgresjson.entity.EntityI
|
||||
|
||||
class ViewAggregation(
|
||||
data class ViewAggregation(
|
||||
val total: Int,
|
||||
val unique: Int
|
||||
) : EntityI,
|
||||
|
||||
@@ -12,8 +12,8 @@ import fr.dcproject.component.citizen.database.CitizenCreatorI
|
||||
import fr.dcproject.component.citizen.database.CitizenI
|
||||
import java.util.UUID
|
||||
|
||||
class VoteForView<T : TargetI>(
|
||||
id: UUID = UUID.randomUUID(),
|
||||
data class VoteForView<T : TargetI>(
|
||||
override val id: UUID = UUID.randomUUID(),
|
||||
override val createdBy: CitizenCreator,
|
||||
override val target: T,
|
||||
val note: Int,
|
||||
@@ -30,7 +30,7 @@ class VoteForView<T : TargetI>(
|
||||
}
|
||||
}
|
||||
|
||||
class VoteForUpdate<T : TargetI, C : CitizenI>(
|
||||
data class VoteForUpdate<T : TargetI, C : CitizenI>(
|
||||
override val id: UUID = UUID.randomUUID(),
|
||||
override val note: Int,
|
||||
override val target: T,
|
||||
|
||||
@@ -2,10 +2,18 @@ package fr.dcproject.component.vote.dto
|
||||
|
||||
import fr.dcproject.component.vote.entity.Votable
|
||||
|
||||
class VoteAggregation(parent: Votable) {
|
||||
val up: Int = parent.votes.up
|
||||
val neutral: Int = parent.votes.neutral
|
||||
val down: Int = parent.votes.down
|
||||
val total: Int = parent.votes.total
|
||||
val score: Int = parent.votes.score
|
||||
data class VoteAggregation(
|
||||
val up: Int,
|
||||
val neutral: Int,
|
||||
val down: Int,
|
||||
val total: Int,
|
||||
val score: Int
|
||||
) {
|
||||
constructor(parent: Votable) : this(
|
||||
up = parent.votes.up,
|
||||
neutral = parent.votes.neutral,
|
||||
down = parent.votes.down,
|
||||
total = parent.votes.total,
|
||||
score = parent.votes.score
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,6 @@ interface Votable {
|
||||
val votes: VoteAggregation
|
||||
}
|
||||
|
||||
class VotableImp : Votable {
|
||||
data class VotableImp(
|
||||
override val votes: VoteAggregation = VoteAggregation()
|
||||
}
|
||||
) : Votable
|
||||
|
||||
@@ -30,7 +30,7 @@ object GetCitizenVotes {
|
||||
mustBeAuth()
|
||||
val votes = repo.findCitizenVotesByTargets(it.citizen, it.id)
|
||||
if (votes.isNotEmpty()) {
|
||||
ac.assert { canView(votes, citizenOrNull) }
|
||||
ac.canView(votes, citizenOrNull).assert()
|
||||
}
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
|
||||
@@ -49,7 +49,7 @@ object GetCitizenVotesOnArticle {
|
||||
it.validate().badRequestIfNotValid()
|
||||
|
||||
val votes = repo.findByCitizen(it.citizen, it.page, it.limit)
|
||||
ac.assert { canView(votes.result, citizenOrNull) }
|
||||
ac.canView(votes.result, citizenOrNull).assert()
|
||||
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
|
||||
@@ -51,7 +51,7 @@ object PutVoteOnArticle {
|
||||
note = input.note,
|
||||
createdBy = this.citizen
|
||||
)
|
||||
ac.assert { canCreate(vote, citizenOrNull) }
|
||||
ac.canCreate(vote, citizenOrNull).assert()
|
||||
val votes = repo.vote(vote)
|
||||
call.respond(
|
||||
HttpStatusCode.Created,
|
||||
|
||||
@@ -52,7 +52,7 @@ object PutVoteOnComment {
|
||||
note = input.note,
|
||||
createdBy = this.citizen
|
||||
)
|
||||
ac.assert { canCreate(vote, citizenOrNull) }
|
||||
ac.canCreate(vote, citizenOrNull).assert()
|
||||
val votes = voteCommentRepo.vote(vote)
|
||||
call.respond(
|
||||
HttpStatusCode.Created,
|
||||
|
||||
@@ -51,7 +51,7 @@ object PutVoteOnConstitution {
|
||||
note = input.note,
|
||||
createdBy = this.citizen
|
||||
)
|
||||
ac.assert { canCreate(vote, citizenOrNull) }
|
||||
ac.canCreate(vote, citizenOrNull).assert()
|
||||
repo.vote(vote)
|
||||
call.respond(HttpStatusCode.Created)
|
||||
}
|
||||
|
||||
@@ -43,17 +43,17 @@ data class WorkgroupForUpdate<C : CitizenWithUserI>(
|
||||
WorkgroupForUpdateI<C>,
|
||||
CreatedBy<C> by CreatedBy.Imp(createdBy)
|
||||
|
||||
interface WorkgroupForUpdateI<C : CitizenWithUserI> : WorkgroupWithAuthI<C>, WorkgroupCartI, CreatedBy<C> {
|
||||
sealed interface WorkgroupForUpdateI<C : CitizenWithUserI> : WorkgroupWithAuthI<C>, WorkgroupCartI, CreatedBy<C> {
|
||||
val description: String
|
||||
val logo: String?
|
||||
}
|
||||
|
||||
class WorkgroupCart(
|
||||
data class WorkgroupCart(
|
||||
override val id: UUID,
|
||||
override val name: String
|
||||
) : WorkgroupCartI
|
||||
|
||||
interface WorkgroupCartI : EntityI {
|
||||
sealed interface WorkgroupCartI : EntityI {
|
||||
val name: String
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ open class WorkgroupRef(
|
||||
id: UUID? = null
|
||||
) : Entity(id ?: UUID.randomUUID()), WorkgroupI
|
||||
|
||||
interface WorkgroupWithAuthI<Z : CitizenWithUserI> : WorkgroupWithMembersI<Z>, CreatedBy<Z>, DeletedAt {
|
||||
sealed interface WorkgroupWithAuthI<Z : CitizenWithUserI> : WorkgroupWithMembersI<Z>, CreatedBy<Z>, DeletedAt {
|
||||
val anonymous: Boolean
|
||||
|
||||
fun isMember(user: UserI): Boolean = members.isMember(user)
|
||||
@@ -70,11 +70,11 @@ interface WorkgroupWithAuthI<Z : CitizenWithUserI> : WorkgroupWithMembersI<Z>, C
|
||||
fun hasRole(expectedRole: Role, user: UserI): Boolean = members.hasRole(expectedRole, user)
|
||||
fun hasRole(expectedRole: Role, citizen: CitizenI): Boolean = members.hasRole(expectedRole, citizen)
|
||||
|
||||
fun getRoles(user: UserI): List<Role> = members.getRoles(user)
|
||||
fun getRoles(citizen: CitizenI): List<Role> = members.getRoles(citizen)
|
||||
fun getRoles(user: UserI): Collection<Role> = members.getRoles(user)
|
||||
fun getRoles(citizen: CitizenI): Collection<Role> = members.getRoles(citizen)
|
||||
}
|
||||
|
||||
interface WorkgroupWithMembersI<Z : CitizenI> : WorkgroupI {
|
||||
sealed interface WorkgroupWithMembersI<Z : CitizenI> : WorkgroupI {
|
||||
val members: List<Member<Z>>
|
||||
|
||||
class Member<C : CitizenI>(
|
||||
@@ -90,24 +90,24 @@ interface WorkgroupWithMembersI<Z : CitizenI> : WorkgroupI {
|
||||
}
|
||||
}
|
||||
|
||||
fun List<CitizenI>.hasCitizen(citizen: CitizenI): Boolean = this.map { it.id }.contains(citizen.id)
|
||||
fun Collection<CitizenI>.hasCitizen(citizen: CitizenI): Boolean = this.map { it.id }.contains(citizen.id)
|
||||
|
||||
fun <Z : CitizenWithUserI> List<Member<Z>>.isMember(user: UserI): Boolean =
|
||||
fun <Z : CitizenWithUserI> Collection<Member<Z>>.isMember(user: UserI): Boolean =
|
||||
map { it.citizen.user.id }.contains(user.id)
|
||||
|
||||
fun <Z : CitizenI> List<Member<Z>>.isMember(citizen: CitizenI): Boolean =
|
||||
fun <Z : CitizenI> Collection<Member<Z>>.isMember(citizen: CitizenI): Boolean =
|
||||
map { it.citizen.id }.contains(citizen.id)
|
||||
|
||||
fun <Z : CitizenI> List<Member<Z>>.hasRole(expectedRole: Role, citizen: CitizenI): Boolean =
|
||||
fun <Z : CitizenI> Collection<Member<Z>>.hasRole(expectedRole: Role, citizen: CitizenI): Boolean =
|
||||
any { member -> member.citizen.id == citizen.id && member.roles.any { it == expectedRole } }
|
||||
|
||||
fun <Z : CitizenWithUserI> List<Member<Z>>.hasRole(expectedRole: Role, user: UserI): Boolean =
|
||||
fun <Z : CitizenWithUserI> Collection<Member<Z>>.hasRole(expectedRole: Role, user: UserI): Boolean =
|
||||
any { member -> member.citizen.user.id == user.id && member.roles.any { it == expectedRole } }
|
||||
|
||||
fun <Z : CitizenWithUserI> List<Member<Z>>.getRoles(user: UserI): List<Role> =
|
||||
fun <Z : CitizenWithUserI> Collection<Member<Z>>.getRoles(user: UserI): Collection<Role> =
|
||||
firstOrNull { it.citizen.user.id == user.id }?.roles ?: emptyList()
|
||||
|
||||
fun <Z : CitizenWithUserI> List<Member<Z>>.getRoles(citizen: CitizenI): List<Role> =
|
||||
fun <Z : CitizenWithUserI> Collection<Member<Z>>.getRoles(citizen: CitizenI): Collection<Role> =
|
||||
firstOrNull { it.citizen.id == citizen.id }?.roles ?: emptyList()
|
||||
|
||||
interface WorkgroupI : EntityI
|
||||
|
||||
@@ -66,7 +66,7 @@ object CreateWorkgroup {
|
||||
anonymous ?: true,
|
||||
)
|
||||
}.let { workgroup ->
|
||||
ac.assert { canCreate(workgroup, citizenOrNull) }
|
||||
ac.canCreate(workgroup, citizenOrNull).assert()
|
||||
repo.upsert(workgroup)
|
||||
}.let { w ->
|
||||
call.respond(
|
||||
|
||||
@@ -23,7 +23,7 @@ object DeleteWorkgroup {
|
||||
delete<DeleteWorkgroupRequest> {
|
||||
mustBeAuth()
|
||||
repo.findById(it.workgroupId)?.let { workgroup ->
|
||||
ac.assert { canDelete(workgroup, citizenOrNull) }
|
||||
ac.canDelete(workgroup, citizenOrNull).assert()
|
||||
repo.delete(workgroup)
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
} ?: call.respond(HttpStatusCode.NotFound)
|
||||
|
||||
@@ -65,7 +65,7 @@ object EditWorkgroup {
|
||||
deletedAt = old.deletedAt,
|
||||
members = old.members,
|
||||
).let { workgroup ->
|
||||
ac.assert { canUpdate(workgroup, citizenOrNull) }
|
||||
ac.canUpdate(workgroup, citizenOrNull).assert()
|
||||
repo.upsert(workgroup)
|
||||
}.let {
|
||||
call.respond(HttpStatusCode.OK, it.toOutput())
|
||||
|
||||
@@ -24,7 +24,7 @@ object GetWorkgroup {
|
||||
fun Route.getWorkgroup(repo: WorkgroupRepository, ac: WorkgroupAccessControl) {
|
||||
get<WorkgroupRequest> {
|
||||
repo.findById(it.workgroup.id)?.let { workgroup ->
|
||||
ac.assert { canView(workgroup, citizenOrNull) }
|
||||
ac.canView(workgroup, citizenOrNull).assert()
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
workgroup.toOutput()
|
||||
|
||||
@@ -69,7 +69,7 @@ object GetWorkgroups {
|
||||
it.search,
|
||||
WorkgroupRepository.Filter(createdById = it.createdBy, members = it.members)
|
||||
)
|
||||
ac.assert { canView(workgroups.result, citizenOrNull) }
|
||||
ac.canView(workgroups.result, citizenOrNull).assert()
|
||||
call.respond(
|
||||
HttpStatusCode.OK,
|
||||
workgroups.toOutput { it.toOutputListing() }
|
||||
|
||||
@@ -47,7 +47,7 @@ object AddMemberToWorkgroup {
|
||||
mustBeAuth()
|
||||
repo.findById(it.workgroupId)?.let { workgroup ->
|
||||
call.getMembersFromRequest().let { members ->
|
||||
ac.assert { canAddMembers(workgroup, citizenOrNull) }
|
||||
ac.canAddMembers(workgroup, citizenOrNull).assert()
|
||||
repo.addMembers(workgroup, members)
|
||||
}.let { members ->
|
||||
call.respond(
|
||||
|
||||
@@ -39,7 +39,7 @@ object DeleteMembersOfWorkgroup {
|
||||
repo.findById(it.workgroupId)?.let { workgroup ->
|
||||
call.getMembersFromRequest()
|
||||
.let { members ->
|
||||
ac.assert { canRemoveMembers(workgroup, citizenOrNull) }
|
||||
ac.canRemoveMembers(workgroup, citizenOrNull).assert()
|
||||
repo.removeMembers(workgroup, members)
|
||||
}.let { members ->
|
||||
call.respond(
|
||||
|
||||
@@ -45,7 +45,7 @@ object UpdateMemberOfWorkgroup {
|
||||
mustBeAuth()
|
||||
repo.findById(it.workgroupId)?.let { workgroup ->
|
||||
call.getMembersFromRequest().let { members ->
|
||||
ac.assert { canUpdateMembers(workgroup, citizenOrNull) }
|
||||
ac.canUpdateMembers(workgroup, citizenOrNull).assert()
|
||||
repo.updateMembers(workgroup, members)
|
||||
}.let { members ->
|
||||
call.respond(
|
||||
|
||||
@@ -20,8 +20,8 @@ import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import org.koin.ktor.ext.get
|
||||
import java.util.UUID
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
import kotlin.time.ExperimentalTime
|
||||
import kotlin.time.seconds
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
@ExperimentalCoroutinesApi
|
||||
@@ -78,7 +78,7 @@ class ViewTest {
|
||||
)
|
||||
|
||||
/* Retry because ES is not sync ! */
|
||||
retry(10, 0.3.seconds) {
|
||||
retry(10, seconds(0.3)) {
|
||||
/* Get view */
|
||||
val afterView = viewRepository.getViewsCount(article)
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ class `Check auth on all routes` : BaseTest() {
|
||||
/* Send request to check security */
|
||||
sendRequest(
|
||||
path.buildUrl(pathName, methodName, api.context), /* Replace route to real URL */
|
||||
HttpMethod.parse(methodName.toUpperCase()) /* Convert http method name to enum */
|
||||
HttpMethod.parse(methodName.lowercase()) /* Convert http method name to enum */
|
||||
)
|
||||
}
|
||||
}.let { requests ->
|
||||
|
||||
@@ -13,7 +13,7 @@ fun TestApplicationRequest.`authenticated as`(
|
||||
firstName: String,
|
||||
lastName: String,
|
||||
): Citizen {
|
||||
val username = "$firstName-$lastName".toLowerCase()
|
||||
val username = "$firstName-$lastName".lowercase()
|
||||
val repo: CitizenRepository by lazy<CitizenRepository> { GlobalContext.get().get() }
|
||||
val citizen = repo.findByUsername(username) ?: error("Citizen not exist with username $username")
|
||||
val algorithm = GlobalContext.get().get<JwtConfig>().algorithm
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.util.UUID
|
||||
fun TestApplicationEngine.`Given I have citizen`(
|
||||
firstName: String,
|
||||
lastName: String,
|
||||
email: String = ("$firstName-$lastName".toLowerCase()) + "@dc-project.fr",
|
||||
email: String = ("$firstName-$lastName".lowercase()) + "@dc-project.fr",
|
||||
id: String = UUID.randomUUID().toString(),
|
||||
callback: Citizen.() -> Unit = {}
|
||||
): Citizen? {
|
||||
@@ -22,7 +22,7 @@ fun TestApplicationEngine.`Given I have citizen`(
|
||||
|
||||
val user = UserForCreate(
|
||||
id = id.toUUID(),
|
||||
username = "$firstName-$lastName".toLowerCase(),
|
||||
username = "$firstName-$lastName".lowercase(),
|
||||
password = "Azerty123!",
|
||||
)
|
||||
val citizen = CitizenForCreate(
|
||||
|
||||
@@ -62,7 +62,7 @@ private fun createWorkgroup(
|
||||
val creatorName = createdBy ?: CitizenI.Name("Paul", "Langevin")
|
||||
val creator = citizenRepository.findByName(creatorName) ?: run {
|
||||
val username = ("username" + UUID.randomUUID().toString())
|
||||
.toLowerCase().replace(' ', '-')
|
||||
.lowercase().replace(' ', '-')
|
||||
val user = UserForCreate(
|
||||
username = username,
|
||||
password = "Azerty123!",
|
||||
|
||||
@@ -46,7 +46,7 @@ fun TestApplicationResponse.operation(route: String? = null, callback: Operation
|
||||
.firstOrNull { uri.matches(it.replace("""\{[^{}]+}""".toRegex(), "[^/]+").toRegex()) }
|
||||
|
||||
api.getPath(path)
|
||||
?.getOperation(httpMethod.value.toLowerCase())
|
||||
?.getOperation(httpMethod.value.lowercase())
|
||||
?.apply {
|
||||
this.callback(api, uri)
|
||||
}
|
||||
@@ -59,7 +59,7 @@ fun TestApplicationResponse.`And the schema response body must be valid`(content
|
||||
/* Validate Response */
|
||||
this.apply {
|
||||
val status = call.response.status()
|
||||
val httpMethod = call.request.httpMethod.value.toUpperCase()
|
||||
val httpMethod = call.request.httpMethod.value.lowercase()
|
||||
val responseContent: JsonNode = if (content != null)
|
||||
ObjectMapper().readTree(content)
|
||||
else TextNode("")
|
||||
@@ -79,7 +79,7 @@ fun TestApplicationResponse.`And the schema parameters must be valid`() {
|
||||
operation { api, uri ->
|
||||
/* Validate Request URL */
|
||||
this.apply {
|
||||
val methodName = call.request.httpMethod.value.toUpperCase()
|
||||
val methodName = call.request.httpMethod.value.lowercase()
|
||||
Url(call.request.uri).parameters.forEach { parameter: String, values: List<String> ->
|
||||
val schema = getParametersIn(api.context, "query")
|
||||
?.firstOrNull { it.name == parameter }?.schema
|
||||
@@ -103,7 +103,7 @@ fun TestApplicationResponse.`And the schema parameters must be valid`() {
|
||||
* Validate request body
|
||||
*/
|
||||
fun TestApplicationResponse.`And the schema request body must be valid`(body: String) {
|
||||
operation { api, uri ->
|
||||
operation { api, _ ->
|
||||
requestBody
|
||||
.getContentMediaType(call.request.contentType().toString())
|
||||
.schema
|
||||
|
||||
@@ -15,15 +15,15 @@ import io.ktor.server.testing.TestApplicationRequest
|
||||
import io.ktor.server.testing.setBody
|
||||
|
||||
enum class Validate(override val bit: Long) : BitMaskI {
|
||||
NONE(0),
|
||||
REQUEST_BODY(1),
|
||||
REQUEST_PARAM(2),
|
||||
REQUEST_HEADER(4),
|
||||
REQUEST(1 + 2 + 4),
|
||||
RESPONSE_BODY(8),
|
||||
RESPONSE_HEADER(16),
|
||||
RESPONSE(8 + 16),
|
||||
ALL((1 + 2 + 4) + (8 + 16));
|
||||
NONE(0L),
|
||||
REQUEST_BODY(1L),
|
||||
REQUEST_PARAM(2L),
|
||||
REQUEST_HEADER(4L),
|
||||
REQUEST(1L + 2L + 4L),
|
||||
RESPONSE_BODY(8L),
|
||||
RESPONSE_HEADER(16L),
|
||||
RESPONSE(8L + 16L),
|
||||
ALL((1L + 2L + 4L) + (8L + 16L));
|
||||
|
||||
operator fun unaryMinus(): BitMaskI = ALL - BitMask(this.bit)
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ internal class `Article Access Control` {
|
||||
private val einstein = CitizenCart(
|
||||
user = User(
|
||||
username = "albert-einstein",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
roles = setOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
name = CitizenI.Name("Albert", "Einstein")
|
||||
)
|
||||
|
||||
@@ -23,14 +23,14 @@ internal class `Citizen Access Control` {
|
||||
private val tesla = CitizenCart(
|
||||
user = User(
|
||||
username = "nicolas-tesla",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
roles = setOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
name = CitizenI.Name("Nicolas", "Tesla")
|
||||
)
|
||||
private val einstein = CitizenCart(
|
||||
user = User(
|
||||
username = "albert-einstein",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
roles = setOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
name = CitizenI.Name("Albert", "Einstein")
|
||||
)
|
||||
@@ -38,7 +38,7 @@ internal class `Citizen Access Control` {
|
||||
private val curie = CitizenCart(
|
||||
user = User(
|
||||
username = "marie-curie",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
roles = setOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
name = CitizenI.Name("Marie", "Curie"),
|
||||
deletedAt = DateTime.now()
|
||||
|
||||
@@ -30,7 +30,7 @@ internal class `Comment Access Control` {
|
||||
private val tesla = Citizen(
|
||||
user = User(
|
||||
username = "nicolas-tesla",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
roles = setOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "tesla@best.com",
|
||||
@@ -40,7 +40,7 @@ internal class `Comment Access Control` {
|
||||
id = UUID.fromString("319f1226-8f47-4df3-babd-2c7671ad0fbc"),
|
||||
user = User(
|
||||
username = "albert-einstein",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
roles = setOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "einstein@best.com",
|
||||
|
||||
@@ -36,7 +36,7 @@ internal class `Follow Access Control` {
|
||||
private val tesla2 = Citizen(
|
||||
user = User(
|
||||
username = "nicolas-tesla",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
roles = setOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "tesla@best.com",
|
||||
@@ -67,7 +67,7 @@ internal class `Follow Access Control` {
|
||||
id = UUID.fromString("319f1226-8f47-4df3-babd-2c7671ad0fbc"),
|
||||
user = User(
|
||||
username = "albert-einstein",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
roles = setOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "einstein@best.com",
|
||||
|
||||
@@ -30,7 +30,7 @@ internal class `Vote Access Control` {
|
||||
id = UUID.fromString("a1e35c99-9d33-4fb4-9201-58d7071243bb"),
|
||||
user = User(
|
||||
username = "nicolas-tesla",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
roles = setOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "tesla@best.com",
|
||||
@@ -51,7 +51,7 @@ internal class `Vote Access Control` {
|
||||
id = UUID.fromString("319f1226-8f47-4df3-babd-2c7671ad0fbc"),
|
||||
user = User(
|
||||
username = "albert-einstein",
|
||||
roles = listOf(UserI.Roles.ROLE_USER)
|
||||
roles = setOf(UserI.Roles.ROLE_USER)
|
||||
),
|
||||
birthday = DateTime.now(),
|
||||
email = "einstein@best.com",
|
||||
|
||||
@@ -15,15 +15,15 @@ fi
|
||||
case $opt in
|
||||
"RESET DB")
|
||||
awk 'FNR==1{print "--------------------"}1' \
|
||||
../../main/resources/sql/migrations/*.down.sql \
|
||||
../../main/resources/sql/migrations/*.up.sql > ./allSQL.sql
|
||||
../../../main/resources/sql/migrations/*.down.sql \
|
||||
../../../main/resources/sql/migrations/*.up.sql > ./allSQL.sql
|
||||
docker exec -i dc-project_postgresql_test psql test test -q -b -v "ON_ERROR_STOP=1" < ./allSQL.sql
|
||||
rm ./allSQL.sql
|
||||
;;
|
||||
"All")
|
||||
echo "Start ALL tests"
|
||||
awk 'FNR==1{print "--------------------"}1' \
|
||||
../../main/resources/sql/functions/*/*.sql \
|
||||
../../../main/resources/sql/functions/*/*.sql \
|
||||
./fixtures/*.sql \
|
||||
./*.sql > ./allSQL.sql
|
||||
docker exec -i dc-project_postgresql_test psql test test -q -b -v "ON_ERROR_STOP=1" < ./allSQL.sql
|
||||
@@ -34,7 +34,7 @@ case $opt in
|
||||
*)
|
||||
echo "Start tests $opt"
|
||||
awk 'FNR==1{print "--------------------"}1' \
|
||||
../../main/resources/sql/functions/*/*.sql \
|
||||
../../../main/resources/sql/functions/*/*.sql \
|
||||
./fixtures/*.sql \
|
||||
./"$opt".sql > ./allSQL.sql
|
||||
docker exec -i dc-project_postgresql_test psql test test -q -b -v "ON_ERROR_STOP=1" < ./allSQL.sql
|
||||
|
||||
Reference in New Issue
Block a user