Refactors Citizen into component
Refactor CitizenVoter Split citizens routes
This commit is contained in:
@@ -12,6 +12,10 @@ import fr.dcproject.component.article.route.findArticleVersions
|
|||||||
import fr.dcproject.component.article.route.upsertArticle
|
import fr.dcproject.component.article.route.upsertArticle
|
||||||
import fr.dcproject.component.article.routes.findArticles
|
import fr.dcproject.component.article.routes.findArticles
|
||||||
import fr.dcproject.component.article.routes.getOneArticle
|
import fr.dcproject.component.article.routes.getOneArticle
|
||||||
|
import fr.dcproject.component.citizen.routes.changeMyPassword
|
||||||
|
import fr.dcproject.component.citizen.routes.findCitizen
|
||||||
|
import fr.dcproject.component.citizen.routes.getCurrentCitizen
|
||||||
|
import fr.dcproject.component.citizen.routes.getOneCitizen
|
||||||
import fr.dcproject.elasticsearch.configElasticIndexes
|
import fr.dcproject.elasticsearch.configElasticIndexes
|
||||||
import fr.dcproject.entity.User
|
import fr.dcproject.entity.User
|
||||||
import fr.dcproject.event.EventNotification
|
import fr.dcproject.event.EventNotification
|
||||||
@@ -71,7 +75,6 @@ fun Application.module(env: Env = PROD) {
|
|||||||
install(AuthorizationVoter) {
|
install(AuthorizationVoter) {
|
||||||
voters = listOf(
|
voters = listOf(
|
||||||
ConstitutionVoter(),
|
ConstitutionVoter(),
|
||||||
CitizenVoter(),
|
|
||||||
CommentVoter(),
|
CommentVoter(),
|
||||||
VoteVoter(),
|
VoteVoter(),
|
||||||
FollowVoter(),
|
FollowVoter(),
|
||||||
@@ -151,12 +154,18 @@ fun Application.module(env: Env = PROD) {
|
|||||||
install(Routing.Feature) {
|
install(Routing.Feature) {
|
||||||
// trace { application.log.trace(it.buildText()) }
|
// trace { application.log.trace(it.buildText()) }
|
||||||
authenticate(optional = true) {
|
authenticate(optional = true) {
|
||||||
|
/* Article */
|
||||||
findArticles(get(), get())
|
findArticles(get(), get())
|
||||||
getOneArticle(get(), get())
|
getOneArticle(get(), get())
|
||||||
upsertArticle(get(), get(), get())
|
upsertArticle(get(), get(), get())
|
||||||
findArticleVersions(get(), get())
|
findArticleVersions(get(), get())
|
||||||
|
/* Citizen */
|
||||||
|
findCitizen(get(), get())
|
||||||
|
getOneCitizen(get())
|
||||||
|
getCurrentCitizen(get())
|
||||||
|
changeMyPassword(get(), get())
|
||||||
|
|
||||||
auth(get(), get(), get())
|
auth(get(), get(), get())
|
||||||
citizen(get(), get())
|
|
||||||
constitution(get())
|
constitution(get())
|
||||||
followArticle(get())
|
followArticle(get())
|
||||||
followConstitution(get())
|
followConstitution(get())
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package fr.dcproject
|
package fr.dcproject
|
||||||
|
|
||||||
|
import fr.dcproject.component.citizen.CitizenRepository
|
||||||
import fr.dcproject.entity.User
|
import fr.dcproject.entity.User
|
||||||
import fr.dcproject.entity.UserI
|
import fr.dcproject.entity.UserI
|
||||||
import io.ktor.application.*
|
import io.ktor.application.*
|
||||||
@@ -7,8 +8,7 @@ import io.ktor.auth.*
|
|||||||
import io.ktor.util.*
|
import io.ktor.util.*
|
||||||
import io.ktor.util.pipeline.*
|
import io.ktor.util.pipeline.*
|
||||||
import org.koin.core.context.GlobalContext
|
import org.koin.core.context.GlobalContext
|
||||||
import fr.dcproject.entity.Citizen as CitizenEntity
|
import fr.dcproject.component.citizen.Citizen as CitizenEntity
|
||||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
|
||||||
|
|
||||||
class ForbiddenException(message: String) : Exception(message)
|
class ForbiddenException(message: String) : Exception(message)
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,13 @@ package fr.dcproject
|
|||||||
import fr.dcproject.component.article.ArticleForView
|
import fr.dcproject.component.article.ArticleForView
|
||||||
import fr.dcproject.component.article.ArticleRef
|
import fr.dcproject.component.article.ArticleRef
|
||||||
import fr.dcproject.component.article.ArticleRepository
|
import fr.dcproject.component.article.ArticleRepository
|
||||||
import fr.dcproject.entity.*
|
import fr.dcproject.component.citizen.Citizen
|
||||||
|
import fr.dcproject.component.citizen.CitizenBasic
|
||||||
|
import fr.dcproject.component.citizen.CitizenRef
|
||||||
|
import fr.dcproject.entity.CommentRef
|
||||||
|
import fr.dcproject.entity.Constitution
|
||||||
|
import fr.dcproject.entity.ConstitutionRef
|
||||||
|
import fr.dcproject.entity.WorkgroupRef
|
||||||
import fr.dcproject.repository.OpinionChoice
|
import fr.dcproject.repository.OpinionChoice
|
||||||
import fr.dcproject.repository.Workgroup
|
import fr.dcproject.repository.Workgroup
|
||||||
import io.ktor.features.*
|
import io.ktor.features.*
|
||||||
@@ -78,7 +84,7 @@ val converters: ConverterDeclaration = {
|
|||||||
decode { values, _ ->
|
decode { values, _ ->
|
||||||
val id = values.singleOrNull()?.let { UUID.fromString(it) }
|
val id = values.singleOrNull()?.let { UUID.fromString(it) }
|
||||||
?: throw InternalError("Cannot convert $values to UUID")
|
?: throw InternalError("Cannot convert $values to UUID")
|
||||||
get<fr.dcproject.repository.Citizen>().findById(id) ?: throw NotFoundException("Citizen $values not found")
|
get<fr.dcproject.component.citizen.CitizenRepository>().findById(id) ?: throw NotFoundException("Citizen $values not found")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import com.rabbitmq.client.ConnectionFactory
|
|||||||
import fr.dcproject.component.article.ArticleRepository
|
import fr.dcproject.component.article.ArticleRepository
|
||||||
import fr.dcproject.component.article.ArticleViewManager
|
import fr.dcproject.component.article.ArticleViewManager
|
||||||
import fr.dcproject.component.article.ArticleVoter
|
import fr.dcproject.component.article.ArticleVoter
|
||||||
|
import fr.dcproject.component.citizen.CitizenRepository
|
||||||
|
import fr.dcproject.component.citizen.CitizenVoter
|
||||||
import fr.dcproject.event.publisher.Publisher
|
import fr.dcproject.event.publisher.Publisher
|
||||||
import fr.dcproject.messages.Mailer
|
import fr.dcproject.messages.Mailer
|
||||||
import fr.dcproject.messages.NotificationEmailSender
|
import fr.dcproject.messages.NotificationEmailSender
|
||||||
@@ -27,7 +29,6 @@ import org.apache.http.HttpHost
|
|||||||
import org.elasticsearch.client.RestClient
|
import org.elasticsearch.client.RestClient
|
||||||
import org.koin.core.qualifier.named
|
import org.koin.core.qualifier.named
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
|
||||||
import fr.dcproject.repository.CommentArticle as CommentArticleRepository
|
import fr.dcproject.repository.CommentArticle as CommentArticleRepository
|
||||||
import fr.dcproject.repository.CommentConstitution as CommentConstitutionRepository
|
import fr.dcproject.repository.CommentConstitution as CommentConstitutionRepository
|
||||||
import fr.dcproject.repository.CommentGeneric as CommentGenericRepository
|
import fr.dcproject.repository.CommentGeneric as CommentGenericRepository
|
||||||
@@ -117,6 +118,7 @@ val KoinModule = module {
|
|||||||
|
|
||||||
// Voters
|
// Voters
|
||||||
single { ArticleVoter(get()) }
|
single { ArticleVoter(get()) }
|
||||||
|
single { CitizenVoter() }
|
||||||
|
|
||||||
// Elasticsearch Client
|
// Elasticsearch Client
|
||||||
single<RestClient> {
|
single<RestClient> {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package fr.dcproject.component.article
|
package fr.dcproject.component.article
|
||||||
|
|
||||||
|
import fr.dcproject.component.citizen.*
|
||||||
import fr.dcproject.entity.*
|
import fr.dcproject.entity.*
|
||||||
import fr.postgresjson.entity.*
|
import fr.postgresjson.entity.*
|
||||||
import org.joda.time.DateTime
|
import org.joda.time.DateTime
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package fr.dcproject.component.article
|
package fr.dcproject.component.article
|
||||||
|
|
||||||
import fr.dcproject.entity.CitizenI
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
import fr.dcproject.entity.ViewAggregation
|
import fr.dcproject.entity.ViewAggregation
|
||||||
import fr.dcproject.utils.contentToString
|
import fr.dcproject.utils.contentToString
|
||||||
import fr.dcproject.utils.getJsonField
|
import fr.dcproject.utils.getJsonField
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package fr.dcproject.component.article
|
package fr.dcproject.component.article
|
||||||
|
|
||||||
import fr.dcproject.entity.CitizenI
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
import fr.dcproject.entity.CreatedBy
|
import fr.dcproject.entity.CreatedBy
|
||||||
import fr.dcproject.entity.VersionableRef
|
import fr.dcproject.entity.VersionableRef
|
||||||
import fr.dcproject.voter.Voter
|
import fr.dcproject.voter.Voter
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package fr.dcproject.entity
|
package fr.dcproject.component.citizen
|
||||||
|
|
||||||
import fr.dcproject.entity.CitizenI.Name
|
import fr.dcproject.component.citizen.CitizenI.Name
|
||||||
|
import fr.dcproject.entity.User
|
||||||
|
import fr.dcproject.entity.UserI
|
||||||
|
import fr.dcproject.entity.UserRef
|
||||||
|
import fr.dcproject.entity.WorkgroupSimple
|
||||||
import fr.postgresjson.entity.*
|
import fr.postgresjson.entity.*
|
||||||
import org.joda.time.DateTime
|
import org.joda.time.DateTime
|
||||||
import java.util.*
|
import java.util.*
|
||||||
49
src/main/kotlin/component/citizen/CitizenRepository.kt
Normal file
49
src/main/kotlin/component/citizen/CitizenRepository.kt
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package fr.dcproject.component.citizen
|
||||||
|
|
||||||
|
import fr.dcproject.entity.UserI
|
||||||
|
import fr.postgresjson.connexion.Paginated
|
||||||
|
import fr.postgresjson.connexion.Requester
|
||||||
|
import fr.postgresjson.repository.RepositoryI
|
||||||
|
import net.pearx.kasechange.toSnakeCase
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class CitizenRepository(override var requester: Requester) : RepositoryI {
|
||||||
|
fun findById(id: UUID): Citizen? = requester
|
||||||
|
.getFunction("find_citizen_by_id_with_user_and_workgroups")
|
||||||
|
.selectOne("id" to id)
|
||||||
|
|
||||||
|
fun findByUser(user: UserI): Citizen? = requester
|
||||||
|
.getFunction("find_citizen_by_user_id")
|
||||||
|
.selectOne("user_id" to user.id)
|
||||||
|
|
||||||
|
fun findByUsername(unsername: String): Citizen? = requester
|
||||||
|
.getFunction("find_citizen_by_username")
|
||||||
|
.selectOne("username" to unsername)
|
||||||
|
|
||||||
|
fun findByEmail(email: String): Citizen? = requester
|
||||||
|
.getFunction("find_citizen_by_email")
|
||||||
|
.selectOne("email" to email)
|
||||||
|
|
||||||
|
fun find(
|
||||||
|
page: Int = 1,
|
||||||
|
limit: Int = 50,
|
||||||
|
sort: String? = null,
|
||||||
|
direction: RepositoryI.Direction? = null,
|
||||||
|
search: String? = null
|
||||||
|
): Paginated<CitizenBasic> = requester
|
||||||
|
.getFunction("find_citizens")
|
||||||
|
.select(
|
||||||
|
page, limit,
|
||||||
|
"sort" to sort?.toSnakeCase(),
|
||||||
|
"direction" to direction,
|
||||||
|
"search" to search
|
||||||
|
)
|
||||||
|
|
||||||
|
fun upsert(citizen: CitizenFull): Citizen? = requester
|
||||||
|
.getFunction("upsert_citizen")
|
||||||
|
.selectOne("resource" to citizen)
|
||||||
|
|
||||||
|
fun insertWithUser(citizen: CitizenFull): Citizen? = requester
|
||||||
|
.getFunction("insert_citizen_with_user")
|
||||||
|
.selectOne("resource" to citizen)
|
||||||
|
}
|
||||||
26
src/main/kotlin/component/citizen/CitizenVoter.kt
Normal file
26
src/main/kotlin/component/citizen/CitizenVoter.kt
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package fr.dcproject.component.citizen
|
||||||
|
|
||||||
|
import fr.dcproject.voter.Voter
|
||||||
|
import fr.dcproject.voter.VoterResponse
|
||||||
|
import fr.postgresjson.entity.EntityDeletedAt
|
||||||
|
|
||||||
|
class CitizenVoter : Voter() {
|
||||||
|
fun <S> canView(subjects: List<S>, connectedCitizen: CitizenI?): VoterResponse where S : CitizenI, S: EntityDeletedAt =
|
||||||
|
canAll(subjects) { canView(it, connectedCitizen) }
|
||||||
|
|
||||||
|
fun <S> canView(subject: S, connectedCitizen: CitizenI?): VoterResponse where S : CitizenI, S: EntityDeletedAt {
|
||||||
|
if (connectedCitizen == null) return denied("You must be connected to view citizen", "citizen.view.connected")
|
||||||
|
return if (subject.isDeleted()) denied("You cannot view a deleted citizen", "citizen.view.deleted")
|
||||||
|
else granted()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <S: CitizenI> canUpdate(subject: S, connectedCitizen: CitizenI?): VoterResponse {
|
||||||
|
if (connectedCitizen == null) return denied("You must be connected to update Citizen", "citizen.update.notConnected")
|
||||||
|
return if (subject.id == connectedCitizen.id) granted() else denied("You can only update your citizen", "citizen.update.notYours")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <S: CitizenI> canChangePassword(subject: S, connectedCitizen: CitizenI?): VoterResponse {
|
||||||
|
if (connectedCitizen == null) return denied("You must be connected to change your password", "citizen.changePassword.notConnected")
|
||||||
|
return if (subject.id == connectedCitizen.id) granted() else denied("You can only change your password", "citizen.password.notYours")
|
||||||
|
}
|
||||||
|
}
|
||||||
45
src/main/kotlin/component/citizen/routes/ChangeMyPassword.kt
Normal file
45
src/main/kotlin/component/citizen/routes/ChangeMyPassword.kt
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package fr.dcproject.component.citizen.routes
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException
|
||||||
|
import fr.dcproject.citizen
|
||||||
|
import fr.dcproject.citizenOrNull
|
||||||
|
import fr.dcproject.component.citizen.Citizen
|
||||||
|
import fr.dcproject.component.citizen.CitizenVoter
|
||||||
|
import fr.dcproject.repository.User
|
||||||
|
import fr.dcproject.voter.assert
|
||||||
|
import io.ktor.application.*
|
||||||
|
import io.ktor.auth.*
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.locations.*
|
||||||
|
import io.ktor.request.*
|
||||||
|
import io.ktor.response.*
|
||||||
|
import io.ktor.routing.*
|
||||||
|
|
||||||
|
@KtorExperimentalLocationsAPI
|
||||||
|
|
||||||
|
@Location("/citizens/{citizen}/password/change")
|
||||||
|
class ChangePasswordCitizenRequest(val citizen: Citizen) {
|
||||||
|
data class Input(val oldPassword: String, val newPassword: String)
|
||||||
|
}
|
||||||
|
|
||||||
|
@KtorExperimentalLocationsAPI
|
||||||
|
fun Route.changeMyPassword(voter: CitizenVoter, userRepository: User) {
|
||||||
|
put<ChangePasswordCitizenRequest> {
|
||||||
|
voter.assert { canChangePassword(it.citizen, citizenOrNull) }
|
||||||
|
try {
|
||||||
|
val content = call.receive<ChangePasswordCitizenRequest.Input>()
|
||||||
|
val currentUser = userRepository.findByCredentials(UserPasswordCredential(citizen.user.username, content.oldPassword))
|
||||||
|
val user = it.citizen.user
|
||||||
|
if (currentUser == null || currentUser.id != user.id) {
|
||||||
|
call.respond(HttpStatusCode.BadRequest, "Bad password")
|
||||||
|
} else {
|
||||||
|
user.plainPassword = content.newPassword
|
||||||
|
userRepository.changePassword(user)
|
||||||
|
|
||||||
|
call.respond(HttpStatusCode.Created)
|
||||||
|
}
|
||||||
|
} catch (e: MissingKotlinParameterException) {
|
||||||
|
call.respond(HttpStatusCode.BadRequest, "Request format is not correct")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/main/kotlin/component/citizen/routes/FindCitizens.kt
Normal file
33
src/main/kotlin/component/citizen/routes/FindCitizens.kt
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package fr.dcproject.component.citizen.routes
|
||||||
|
|
||||||
|
import fr.dcproject.citizenOrNull
|
||||||
|
import fr.dcproject.component.citizen.CitizenRepository
|
||||||
|
import fr.dcproject.component.citizen.CitizenVoter
|
||||||
|
import fr.dcproject.voter.assert
|
||||||
|
import fr.postgresjson.repository.RepositoryI
|
||||||
|
import io.ktor.application.*
|
||||||
|
import io.ktor.locations.*
|
||||||
|
import io.ktor.response.*
|
||||||
|
import io.ktor.routing.*
|
||||||
|
|
||||||
|
@KtorExperimentalLocationsAPI
|
||||||
|
@Location("/citizens")
|
||||||
|
class CitizensRequest(
|
||||||
|
page: Int = 1,
|
||||||
|
limit: Int = 50,
|
||||||
|
val sort: String? = null,
|
||||||
|
val direction: RepositoryI.Direction? = null,
|
||||||
|
val search: String? = null
|
||||||
|
) {
|
||||||
|
val page: Int = if (page < 1) 1 else page
|
||||||
|
val limit: Int = if (limit > 50) 50 else if (limit < 1) 1 else limit
|
||||||
|
}
|
||||||
|
|
||||||
|
@KtorExperimentalLocationsAPI
|
||||||
|
fun Route.findCitizen(voter: CitizenVoter, repo: CitizenRepository) {
|
||||||
|
get<CitizensRequest> {
|
||||||
|
val citizens = repo.find(it.page, it.limit, it.sort, it.direction, it.search)
|
||||||
|
voter.assert { canView(citizens.result, citizenOrNull) }
|
||||||
|
call.respond(citizens)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package fr.dcproject.component.citizen.routes
|
||||||
|
|
||||||
|
import fr.dcproject.citizen
|
||||||
|
import fr.dcproject.citizenOrNull
|
||||||
|
import fr.dcproject.component.citizen.CitizenVoter
|
||||||
|
import fr.dcproject.voter.assert
|
||||||
|
import io.ktor.application.*
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.locations.*
|
||||||
|
import io.ktor.response.*
|
||||||
|
import io.ktor.routing.*
|
||||||
|
|
||||||
|
@KtorExperimentalLocationsAPI
|
||||||
|
@Location("/citizens/current")
|
||||||
|
class CurrentCitizenRequest
|
||||||
|
|
||||||
|
@KtorExperimentalLocationsAPI
|
||||||
|
fun Route.getCurrentCitizen(voter: CitizenVoter) {
|
||||||
|
get<CurrentCitizenRequest> {
|
||||||
|
val currentUser = citizenOrNull
|
||||||
|
if (currentUser === null) {
|
||||||
|
call.respond(HttpStatusCode.Unauthorized)
|
||||||
|
} else {
|
||||||
|
voter.assert { canView(currentUser, citizenOrNull) }
|
||||||
|
call.respond(citizen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/main/kotlin/component/citizen/routes/GetOneCitizen.kt
Normal file
23
src/main/kotlin/component/citizen/routes/GetOneCitizen.kt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package fr.dcproject.component.citizen.routes
|
||||||
|
|
||||||
|
import fr.dcproject.citizenOrNull
|
||||||
|
import fr.dcproject.component.citizen.Citizen
|
||||||
|
import fr.dcproject.component.citizen.CitizenVoter
|
||||||
|
import fr.dcproject.voter.assert
|
||||||
|
import io.ktor.application.*
|
||||||
|
import io.ktor.locations.*
|
||||||
|
import io.ktor.response.*
|
||||||
|
import io.ktor.routing.*
|
||||||
|
|
||||||
|
@KtorExperimentalLocationsAPI
|
||||||
|
@Location("/citizens/{citizen}")
|
||||||
|
class CitizenRequest(val citizen: Citizen)
|
||||||
|
|
||||||
|
@KtorExperimentalLocationsAPI
|
||||||
|
fun Route.getOneCitizen(voter: CitizenVoter) {
|
||||||
|
get<CitizenRequest> {
|
||||||
|
voter.assert { canView(it.citizen, citizenOrNull) }
|
||||||
|
|
||||||
|
call.respond(it.citizen)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package fr.dcproject.entity
|
package fr.dcproject.entity
|
||||||
|
|
||||||
|
import fr.dcproject.component.citizen.CitizenRef
|
||||||
import fr.postgresjson.entity.*
|
import fr.postgresjson.entity.*
|
||||||
import org.joda.time.DateTime
|
import org.joda.time.DateTime
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package fr.dcproject.entity
|
|||||||
|
|
||||||
import fr.dcproject.component.article.ArticleI
|
import fr.dcproject.component.article.ArticleI
|
||||||
import fr.dcproject.component.article.ArticleSimple
|
import fr.dcproject.component.article.ArticleSimple
|
||||||
|
import fr.dcproject.component.citizen.CitizenSimple
|
||||||
|
import fr.dcproject.component.citizen.CitizenWithUserI
|
||||||
import fr.postgresjson.entity.*
|
import fr.postgresjson.entity.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package fr.dcproject.entity
|
package fr.dcproject.entity
|
||||||
|
|
||||||
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
import fr.postgresjson.entity.EntityCreatedBy
|
import fr.postgresjson.entity.EntityCreatedBy
|
||||||
import fr.postgresjson.entity.EntityI
|
import fr.postgresjson.entity.EntityI
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package fr.dcproject.entity
|
package fr.dcproject.entity
|
||||||
|
|
||||||
import fr.dcproject.component.article.ArticleRef
|
import fr.dcproject.component.article.ArticleRef
|
||||||
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
import fr.postgresjson.entity.EntityCreatedAt
|
import fr.postgresjson.entity.EntityCreatedAt
|
||||||
import fr.postgresjson.entity.EntityCreatedBy
|
import fr.postgresjson.entity.EntityCreatedBy
|
||||||
import fr.postgresjson.entity.UuidEntity
|
import fr.postgresjson.entity.UuidEntity
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package fr.dcproject.entity
|
package fr.dcproject.entity
|
||||||
|
|
||||||
|
import fr.dcproject.component.citizen.CitizenBasic
|
||||||
|
import fr.dcproject.component.citizen.CitizenBasicI
|
||||||
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
import fr.postgresjson.entity.*
|
import fr.postgresjson.entity.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package fr.dcproject.entity
|
package fr.dcproject.entity
|
||||||
|
|
||||||
import fr.dcproject.component.article.ArticleRef
|
import fr.dcproject.component.article.ArticleRef
|
||||||
|
import fr.dcproject.component.citizen.CitizenBasic
|
||||||
|
import fr.dcproject.component.citizen.CitizenBasicI
|
||||||
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
|
import fr.dcproject.component.citizen.CitizenRef
|
||||||
import fr.postgresjson.entity.*
|
import fr.postgresjson.entity.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package fr.dcproject.entity
|
package fr.dcproject.entity
|
||||||
|
|
||||||
|
import fr.dcproject.component.citizen.CitizenBasic
|
||||||
|
import fr.dcproject.component.citizen.CitizenBasicI
|
||||||
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
import fr.postgresjson.entity.*
|
import fr.postgresjson.entity.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@Deprecated("")
|
@Deprecated("")
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package fr.dcproject.entity
|
package fr.dcproject.entity
|
||||||
|
|
||||||
|
import fr.dcproject.component.citizen.CitizenBasicI
|
||||||
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
|
import fr.dcproject.component.citizen.CitizenWithUserI
|
||||||
import fr.dcproject.entity.WorkgroupWithMembersI.Member
|
import fr.dcproject.entity.WorkgroupWithMembersI.Member
|
||||||
import fr.dcproject.entity.WorkgroupWithMembersI.Member.Role
|
import fr.dcproject.entity.WorkgroupWithMembersI.Member.Role
|
||||||
import fr.postgresjson.entity.*
|
import fr.postgresjson.entity.*
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import com.rabbitmq.client.*
|
|||||||
import com.rabbitmq.client.BuiltinExchangeType.DIRECT
|
import com.rabbitmq.client.BuiltinExchangeType.DIRECT
|
||||||
import fr.dcproject.Config
|
import fr.dcproject.Config
|
||||||
import fr.dcproject.component.article.ArticleForView
|
import fr.dcproject.component.article.ArticleForView
|
||||||
import fr.dcproject.entity.CitizenRef
|
import fr.dcproject.component.citizen.CitizenRef
|
||||||
import fr.dcproject.entity.FollowSimple
|
import fr.dcproject.entity.FollowSimple
|
||||||
import fr.dcproject.entity.TargetRef
|
import fr.dcproject.entity.TargetRef
|
||||||
import fr.dcproject.event.publisher.Publisher
|
import fr.dcproject.event.publisher.Publisher
|
||||||
|
|||||||
@@ -5,13 +5,13 @@ import com.sendgrid.helpers.mail.objects.Content
|
|||||||
import com.sendgrid.helpers.mail.objects.Email
|
import com.sendgrid.helpers.mail.objects.Email
|
||||||
import fr.dcproject.component.article.ArticleRepository
|
import fr.dcproject.component.article.ArticleRepository
|
||||||
import fr.dcproject.component.article.ArticleWithTitleI
|
import fr.dcproject.component.article.ArticleWithTitleI
|
||||||
import fr.dcproject.entity.CitizenBasicI
|
import fr.dcproject.component.citizen.CitizenBasicI
|
||||||
import fr.dcproject.entity.CitizenRef
|
import fr.dcproject.component.citizen.CitizenRef
|
||||||
|
import fr.dcproject.component.citizen.CitizenRepository
|
||||||
import fr.dcproject.entity.FollowSimple
|
import fr.dcproject.entity.FollowSimple
|
||||||
import fr.dcproject.entity.TargetRef
|
import fr.dcproject.entity.TargetRef
|
||||||
import fr.postgresjson.entity.UuidEntityI
|
import fr.postgresjson.entity.UuidEntityI
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
|
||||||
|
|
||||||
class NotificationEmailSender(
|
class NotificationEmailSender(
|
||||||
private val mailer: Mailer,
|
private val mailer: Mailer,
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import com.sendgrid.helpers.mail.Mail
|
|||||||
import com.sendgrid.helpers.mail.objects.Content
|
import com.sendgrid.helpers.mail.objects.Content
|
||||||
import com.sendgrid.helpers.mail.objects.Email
|
import com.sendgrid.helpers.mail.objects.Email
|
||||||
import fr.dcproject.JwtConfig
|
import fr.dcproject.JwtConfig
|
||||||
import fr.dcproject.entity.CitizenBasicI
|
import fr.dcproject.component.citizen.CitizenBasicI
|
||||||
import io.ktor.http.URLBuilder
|
import fr.dcproject.component.citizen.CitizenRepository
|
||||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
import io.ktor.http.*
|
||||||
|
|
||||||
class SsoManager(
|
class SsoManager(
|
||||||
private val mailer: Mailer,
|
private val mailer: Mailer,
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
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
|
|
||||||
import fr.postgresjson.repository.RepositoryI.Direction
|
|
||||||
import net.pearx.kasechange.toSnakeCase
|
|
||||||
import java.util.*
|
|
||||||
import fr.dcproject.entity.Citizen as CitizenEntity
|
|
||||||
|
|
||||||
class Citizen(override var requester: Requester) : RepositoryI {
|
|
||||||
fun findById(id: UUID): CitizenEntity? = requester
|
|
||||||
.getFunction("find_citizen_by_id_with_user_and_workgroups")
|
|
||||||
.selectOne("id" to id)
|
|
||||||
|
|
||||||
fun findByUser(user: UserI): CitizenEntity? = requester
|
|
||||||
.getFunction("find_citizen_by_user_id")
|
|
||||||
.selectOne("user_id" to user.id)
|
|
||||||
|
|
||||||
fun findByUsername(unsername: String): CitizenEntity? = requester
|
|
||||||
.getFunction("find_citizen_by_username")
|
|
||||||
.selectOne("username" to unsername)
|
|
||||||
|
|
||||||
fun findByEmail(email: String): CitizenEntity? = requester
|
|
||||||
.getFunction("find_citizen_by_email")
|
|
||||||
.selectOne("email" to email)
|
|
||||||
|
|
||||||
fun find(
|
|
||||||
page: Int = 1,
|
|
||||||
limit: Int = 50,
|
|
||||||
sort: String? = null,
|
|
||||||
direction: Direction? = null,
|
|
||||||
search: String? = null
|
|
||||||
): Paginated<CitizenBasic> = requester
|
|
||||||
.getFunction("find_citizens")
|
|
||||||
.select(
|
|
||||||
page, limit,
|
|
||||||
"sort" to sort?.toSnakeCase(),
|
|
||||||
"direction" to direction,
|
|
||||||
"search" to search
|
|
||||||
)
|
|
||||||
|
|
||||||
fun upsert(citizen: CitizenFull): CitizenEntity? = requester
|
|
||||||
.getFunction("upsert_citizen")
|
|
||||||
.selectOne("resource" to citizen)
|
|
||||||
|
|
||||||
fun insertWithUser(citizen: CitizenFull): CitizenEntity? = requester
|
|
||||||
.getFunction("insert_citizen_with_user")
|
|
||||||
.selectOne("resource" to citizen)
|
|
||||||
}
|
|
||||||
@@ -2,6 +2,8 @@ package fr.dcproject.repository
|
|||||||
|
|
||||||
import fr.dcproject.component.article.ArticleForView
|
import fr.dcproject.component.article.ArticleForView
|
||||||
import fr.dcproject.component.article.ArticleRef
|
import fr.dcproject.component.article.ArticleRef
|
||||||
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
|
import fr.dcproject.component.citizen.CitizenRef
|
||||||
import fr.dcproject.entity.*
|
import fr.dcproject.entity.*
|
||||||
import fr.postgresjson.connexion.Paginated
|
import fr.postgresjson.connexion.Paginated
|
||||||
import fr.postgresjson.connexion.Requester
|
import fr.postgresjson.connexion.Requester
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package fr.dcproject.repository
|
package fr.dcproject.repository
|
||||||
|
|
||||||
import fr.dcproject.component.article.ArticleRef
|
import fr.dcproject.component.article.ArticleRef
|
||||||
import fr.dcproject.entity.CitizenWithUserI
|
import fr.dcproject.component.citizen.CitizenWithUserI
|
||||||
import fr.dcproject.entity.ConstitutionSimple
|
import fr.dcproject.entity.ConstitutionSimple
|
||||||
import fr.postgresjson.connexion.Paginated
|
import fr.postgresjson.connexion.Paginated
|
||||||
import fr.postgresjson.connexion.Requester
|
import fr.postgresjson.connexion.Requester
|
||||||
|
|||||||
@@ -2,7 +2,12 @@ package fr.dcproject.repository
|
|||||||
|
|
||||||
import fr.dcproject.component.article.ArticleForView
|
import fr.dcproject.component.article.ArticleForView
|
||||||
import fr.dcproject.component.article.ArticleRef
|
import fr.dcproject.component.article.ArticleRef
|
||||||
import fr.dcproject.entity.*
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
|
import fr.dcproject.component.citizen.CitizenRef
|
||||||
|
import fr.dcproject.entity.ConstitutionRef
|
||||||
|
import fr.dcproject.entity.FollowForUpdate
|
||||||
|
import fr.dcproject.entity.FollowSimple
|
||||||
|
import fr.dcproject.entity.TargetRef
|
||||||
import fr.postgresjson.connexion.Paginated
|
import fr.postgresjson.connexion.Paginated
|
||||||
import fr.postgresjson.connexion.Requester
|
import fr.postgresjson.connexion.Requester
|
||||||
import fr.postgresjson.entity.UuidEntity
|
import fr.postgresjson.entity.UuidEntity
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package fr.dcproject.repository
|
|||||||
|
|
||||||
import com.fasterxml.jackson.core.type.TypeReference
|
import com.fasterxml.jackson.core.type.TypeReference
|
||||||
import fr.dcproject.component.article.ArticleRef
|
import fr.dcproject.component.article.ArticleRef
|
||||||
import fr.dcproject.entity.CitizenRef
|
import fr.dcproject.component.citizen.CitizenRef
|
||||||
import fr.dcproject.entity.OpinionChoiceRef
|
import fr.dcproject.entity.OpinionChoiceRef
|
||||||
import fr.dcproject.entity.OpinionForUpdate
|
import fr.dcproject.entity.OpinionForUpdate
|
||||||
import fr.dcproject.entity.TargetRef
|
import fr.dcproject.entity.TargetRef
|
||||||
@@ -11,7 +11,7 @@ import fr.postgresjson.connexion.Requester
|
|||||||
import fr.postgresjson.repository.RepositoryI
|
import fr.postgresjson.repository.RepositoryI
|
||||||
import net.pearx.kasechange.toSnakeCase
|
import net.pearx.kasechange.toSnakeCase
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import fr.dcproject.entity.Citizen as CitizenEntity
|
import fr.dcproject.component.citizen.Citizen as CitizenEntity
|
||||||
import fr.dcproject.entity.Opinion as OpinionEntity
|
import fr.dcproject.entity.Opinion as OpinionEntity
|
||||||
import fr.dcproject.entity.OpinionArticle as OpinionArticleEntity
|
import fr.dcproject.entity.OpinionArticle as OpinionArticleEntity
|
||||||
import fr.dcproject.entity.OpinionChoice as OpinionChoiceEntity
|
import fr.dcproject.entity.OpinionChoice as OpinionChoiceEntity
|
||||||
|
|||||||
@@ -2,13 +2,14 @@ package fr.dcproject.repository
|
|||||||
|
|
||||||
import com.fasterxml.jackson.core.type.TypeReference
|
import com.fasterxml.jackson.core.type.TypeReference
|
||||||
import fr.dcproject.component.article.ArticleForView
|
import fr.dcproject.component.article.ArticleForView
|
||||||
|
import fr.dcproject.component.citizen.CitizenRef
|
||||||
import fr.dcproject.entity.*
|
import fr.dcproject.entity.*
|
||||||
import fr.dcproject.entity.Constitution
|
import fr.dcproject.entity.Constitution
|
||||||
import fr.postgresjson.connexion.Paginated
|
import fr.postgresjson.connexion.Paginated
|
||||||
import fr.postgresjson.connexion.Requester
|
import fr.postgresjson.connexion.Requester
|
||||||
import fr.postgresjson.repository.RepositoryI
|
import fr.postgresjson.repository.RepositoryI
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import fr.dcproject.entity.Citizen as CitizenEntity
|
import fr.dcproject.component.citizen.Citizen as CitizenEntity
|
||||||
import fr.dcproject.entity.Vote as VoteEntity
|
import fr.dcproject.entity.Vote as VoteEntity
|
||||||
|
|
||||||
open class Vote<T : TargetI>(override var requester: Requester) : RepositoryI {
|
open class Vote<T : TargetI>(override var requester: Requester) : RepositoryI {
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
package fr.dcproject.repository
|
package fr.dcproject.repository
|
||||||
|
|
||||||
import fr.dcproject.entity.*
|
import fr.dcproject.component.citizen.CitizenBasic
|
||||||
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
|
import fr.dcproject.entity.WorkgroupI
|
||||||
|
import fr.dcproject.entity.WorkgroupRef
|
||||||
|
import fr.dcproject.entity.WorkgroupSimple
|
||||||
|
import fr.dcproject.entity.WorkgroupWithMembersI
|
||||||
import fr.dcproject.entity.WorkgroupWithMembersI.Member
|
import fr.dcproject.entity.WorkgroupWithMembersI.Member
|
||||||
import fr.postgresjson.connexion.Paginated
|
import fr.postgresjson.connexion.Paginated
|
||||||
import fr.postgresjson.connexion.Requester
|
import fr.postgresjson.connexion.Requester
|
||||||
|
|||||||
@@ -3,25 +3,22 @@ package fr.dcproject.routes
|
|||||||
import com.fasterxml.jackson.databind.exc.MismatchedInputException
|
import com.fasterxml.jackson.databind.exc.MismatchedInputException
|
||||||
import com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException
|
import com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException
|
||||||
import fr.dcproject.JwtConfig
|
import fr.dcproject.JwtConfig
|
||||||
|
import fr.dcproject.component.citizen.CitizenRepository
|
||||||
import fr.dcproject.entity.UserI.Roles.ROLE_USER
|
import fr.dcproject.entity.UserI.Roles.ROLE_USER
|
||||||
import fr.dcproject.messages.SsoManager
|
import fr.dcproject.messages.SsoManager
|
||||||
import fr.dcproject.routes.AuthPaths.LoginRequest
|
import fr.dcproject.routes.AuthPaths.LoginRequest
|
||||||
import fr.dcproject.routes.AuthPaths.RegisterRequest
|
import fr.dcproject.routes.AuthPaths.RegisterRequest
|
||||||
import fr.dcproject.routes.AuthPaths.SsoRequest
|
import fr.dcproject.routes.AuthPaths.SsoRequest
|
||||||
import io.ktor.application.call
|
import io.ktor.application.*
|
||||||
import io.ktor.auth.UserPasswordCredential
|
import io.ktor.auth.*
|
||||||
import io.ktor.features.BadRequestException
|
import io.ktor.features.*
|
||||||
import io.ktor.http.HttpStatusCode
|
import io.ktor.http.*
|
||||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
import io.ktor.locations.*
|
||||||
import io.ktor.locations.Location
|
import io.ktor.request.*
|
||||||
import io.ktor.locations.post
|
import io.ktor.response.*
|
||||||
import io.ktor.request.receive
|
import io.ktor.routing.*
|
||||||
import io.ktor.response.respond
|
import io.ktor.util.*
|
||||||
import io.ktor.response.respondText
|
import fr.dcproject.component.citizen.Citizen as CitizenEntity
|
||||||
import io.ktor.routing.Route
|
|
||||||
import io.ktor.util.KtorExperimentalAPI
|
|
||||||
import fr.dcproject.entity.Citizen as CitizenEntity
|
|
||||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
|
||||||
import fr.dcproject.repository.User as UserRepository
|
import fr.dcproject.repository.User as UserRepository
|
||||||
|
|
||||||
@KtorExperimentalLocationsAPI
|
@KtorExperimentalLocationsAPI
|
||||||
|
|||||||
@@ -1,96 +0,0 @@
|
|||||||
package fr.dcproject.routes
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException
|
|
||||||
import fr.dcproject.citizen
|
|
||||||
import fr.dcproject.citizenOrNull
|
|
||||||
import fr.dcproject.entity.Citizen
|
|
||||||
import fr.dcproject.routes.CitizenPaths.ChangePasswordCitizenRequest
|
|
||||||
import fr.dcproject.routes.CitizenPaths.CitizenRequest
|
|
||||||
import fr.dcproject.routes.CitizenPaths.CitizensRequest
|
|
||||||
import fr.dcproject.routes.CitizenPaths.CurrentCitizenRequest
|
|
||||||
import fr.dcproject.security.voter.CitizenVoter.Action.CHANGE_PASSWORD
|
|
||||||
import fr.dcproject.security.voter.CitizenVoter.Action.VIEW
|
|
||||||
import fr.ktorVoter.assertCan
|
|
||||||
import fr.ktorVoter.assertCanAll
|
|
||||||
import fr.postgresjson.repository.RepositoryI.Direction
|
|
||||||
import io.ktor.application.*
|
|
||||||
import io.ktor.auth.*
|
|
||||||
import io.ktor.http.*
|
|
||||||
import io.ktor.locations.*
|
|
||||||
import io.ktor.request.*
|
|
||||||
import io.ktor.response.*
|
|
||||||
import io.ktor.routing.*
|
|
||||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
|
||||||
import fr.dcproject.repository.User as UserRepository
|
|
||||||
|
|
||||||
@KtorExperimentalLocationsAPI
|
|
||||||
object CitizenPaths {
|
|
||||||
@Location("/citizens")
|
|
||||||
class CitizensRequest(
|
|
||||||
page: Int = 1,
|
|
||||||
limit: Int = 50,
|
|
||||||
val sort: String? = null,
|
|
||||||
val direction: Direction? = null,
|
|
||||||
val search: String? = null
|
|
||||||
) {
|
|
||||||
val page: Int = if (page < 1) 1 else page
|
|
||||||
val limit: Int = if (limit > 50) 50 else if (limit < 1) 1 else limit
|
|
||||||
}
|
|
||||||
|
|
||||||
@Location("/citizens/{citizen}")
|
|
||||||
class CitizenRequest(val citizen: Citizen)
|
|
||||||
|
|
||||||
@Location("/citizens/current")
|
|
||||||
class CurrentCitizenRequest
|
|
||||||
|
|
||||||
@Location("/citizens/{citizen}/password/change")
|
|
||||||
class ChangePasswordCitizenRequest(val citizen: Citizen) {
|
|
||||||
data class Content(val oldPassword: String, val newPassword: String)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@KtorExperimentalLocationsAPI
|
|
||||||
fun Route.citizen(
|
|
||||||
repo: CitizenRepository,
|
|
||||||
userRepository: UserRepository
|
|
||||||
) {
|
|
||||||
get<CitizensRequest> {
|
|
||||||
val citizens = repo.find(it.page, it.limit, it.sort, it.direction, it.search)
|
|
||||||
assertCanAll(VIEW, citizens.result)
|
|
||||||
call.respond(citizens)
|
|
||||||
}
|
|
||||||
|
|
||||||
get<CitizenRequest> {
|
|
||||||
assertCan(VIEW, it.citizen)
|
|
||||||
|
|
||||||
call.respond(it.citizen)
|
|
||||||
}
|
|
||||||
|
|
||||||
get<CurrentCitizenRequest> {
|
|
||||||
if (citizenOrNull === null) {
|
|
||||||
call.respond(HttpStatusCode.Unauthorized)
|
|
||||||
} else {
|
|
||||||
assertCan(VIEW, citizen)
|
|
||||||
call.respond(citizen)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
put<ChangePasswordCitizenRequest> {
|
|
||||||
assertCan(CHANGE_PASSWORD, it.citizen)
|
|
||||||
try {
|
|
||||||
val content = call.receive<ChangePasswordCitizenRequest.Content>()
|
|
||||||
val currentUser = userRepository.findByCredentials(UserPasswordCredential(citizen.user.username, content.oldPassword))
|
|
||||||
val user = it.citizen.user
|
|
||||||
if (currentUser == null || currentUser.id != user.id) {
|
|
||||||
call.respond(HttpStatusCode.BadRequest, "Bad password")
|
|
||||||
} else {
|
|
||||||
user.plainPassword = content.newPassword
|
|
||||||
userRepository.changePassword(user)
|
|
||||||
|
|
||||||
call.respond(HttpStatusCode.Created)
|
|
||||||
}
|
|
||||||
} catch (e: MissingKotlinParameterException) {
|
|
||||||
call.respond(HttpStatusCode.BadRequest, "Request format is not correct")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,7 @@ package fr.dcproject.routes
|
|||||||
import fr.dcproject.citizen
|
import fr.dcproject.citizen
|
||||||
import fr.dcproject.component.article.ArticleForView
|
import fr.dcproject.component.article.ArticleForView
|
||||||
import fr.dcproject.component.article.ArticleRef
|
import fr.dcproject.component.article.ArticleRef
|
||||||
import fr.dcproject.entity.Citizen
|
import fr.dcproject.component.citizen.Citizen
|
||||||
import fr.dcproject.entity.CommentForUpdate
|
import fr.dcproject.entity.CommentForUpdate
|
||||||
import fr.dcproject.repository.CommentArticle.Sort
|
import fr.dcproject.repository.CommentArticle.Sort
|
||||||
import fr.dcproject.security.voter.CommentVoter.Action.CREATE
|
import fr.dcproject.security.voter.CommentVoter.Action.CREATE
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package fr.dcproject.routes
|
package fr.dcproject.routes
|
||||||
|
|
||||||
import fr.dcproject.citizen
|
import fr.dcproject.citizen
|
||||||
import fr.dcproject.entity.Citizen
|
import fr.dcproject.component.citizen.Citizen
|
||||||
import fr.dcproject.entity.CommentForUpdate
|
import fr.dcproject.entity.CommentForUpdate
|
||||||
import fr.dcproject.entity.ConstitutionRef
|
import fr.dcproject.entity.ConstitutionRef
|
||||||
import fr.dcproject.security.voter.CommentVoter.Action.CREATE
|
import fr.dcproject.security.voter.CommentVoter.Action.CREATE
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package fr.dcproject.routes
|
|||||||
|
|
||||||
import fr.dcproject.citizen
|
import fr.dcproject.citizen
|
||||||
import fr.dcproject.component.article.ArticleRef
|
import fr.dcproject.component.article.ArticleRef
|
||||||
import fr.dcproject.entity.CitizenWithUserI
|
import fr.dcproject.component.citizen.CitizenWithUserI
|
||||||
import fr.dcproject.entity.ConstitutionSimple
|
import fr.dcproject.entity.ConstitutionSimple
|
||||||
import fr.dcproject.entity.ConstitutionSimple.TitleSimple
|
import fr.dcproject.entity.ConstitutionSimple.TitleSimple
|
||||||
import fr.dcproject.security.voter.ConstitutionVoter.Action.CREATE
|
import fr.dcproject.security.voter.ConstitutionVoter.Action.CREATE
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package fr.dcproject.routes
|
|||||||
|
|
||||||
import fr.dcproject.citizen
|
import fr.dcproject.citizen
|
||||||
import fr.dcproject.component.article.ArticleRef
|
import fr.dcproject.component.article.ArticleRef
|
||||||
import fr.dcproject.entity.Citizen
|
import fr.dcproject.component.citizen.Citizen
|
||||||
import fr.dcproject.entity.FollowForUpdate
|
import fr.dcproject.entity.FollowForUpdate
|
||||||
import fr.dcproject.security.voter.FollowVoter.Action.*
|
import fr.dcproject.security.voter.FollowVoter.Action.*
|
||||||
import fr.ktorVoter.assertCan
|
import fr.ktorVoter.assertCan
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package fr.dcproject.routes
|
package fr.dcproject.routes
|
||||||
|
|
||||||
import fr.dcproject.citizen
|
import fr.dcproject.citizen
|
||||||
import fr.dcproject.entity.CitizenRef
|
import fr.dcproject.component.citizen.CitizenRef
|
||||||
import fr.dcproject.entity.ConstitutionRef
|
import fr.dcproject.entity.ConstitutionRef
|
||||||
import fr.dcproject.entity.FollowForUpdate
|
import fr.dcproject.entity.FollowForUpdate
|
||||||
import fr.dcproject.security.voter.FollowVoter.Action.*
|
import fr.dcproject.security.voter.FollowVoter.Action.*
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package fr.dcproject.routes
|
|||||||
|
|
||||||
import fr.dcproject.citizen
|
import fr.dcproject.citizen
|
||||||
import fr.dcproject.component.article.ArticleForView
|
import fr.dcproject.component.article.ArticleForView
|
||||||
import fr.dcproject.entity.CitizenRef
|
import fr.dcproject.component.citizen.CitizenRef
|
||||||
import fr.dcproject.entity.OpinionChoiceRef
|
import fr.dcproject.entity.OpinionChoiceRef
|
||||||
import fr.dcproject.security.voter.OpinionVoter.Action.CREATE
|
import fr.dcproject.security.voter.OpinionVoter.Action.CREATE
|
||||||
import fr.dcproject.security.voter.OpinionVoter.Action.VIEW
|
import fr.dcproject.security.voter.OpinionVoter.Action.VIEW
|
||||||
@@ -19,7 +19,7 @@ import io.ktor.util.*
|
|||||||
import org.koin.core.KoinComponent
|
import org.koin.core.KoinComponent
|
||||||
import org.koin.core.get
|
import org.koin.core.get
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import fr.dcproject.entity.Citizen as CitizenEntity
|
import fr.dcproject.component.citizen.Citizen as CitizenEntity
|
||||||
import fr.dcproject.repository.OpinionArticle as OpinionArticleRepository
|
import fr.dcproject.repository.OpinionArticle as OpinionArticleRepository
|
||||||
|
|
||||||
@KtorExperimentalLocationsAPI
|
@KtorExperimentalLocationsAPI
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package fr.dcproject.routes
|
|||||||
|
|
||||||
import fr.dcproject.citizen
|
import fr.dcproject.citizen
|
||||||
import fr.dcproject.component.article.ArticleForView
|
import fr.dcproject.component.article.ArticleForView
|
||||||
import fr.dcproject.entity.Citizen
|
import fr.dcproject.component.citizen.Citizen
|
||||||
import fr.dcproject.entity.VoteForUpdate
|
import fr.dcproject.entity.VoteForUpdate
|
||||||
import fr.dcproject.repository.CommentGeneric
|
import fr.dcproject.repository.CommentGeneric
|
||||||
import fr.dcproject.repository.VoteComment
|
import fr.dcproject.repository.VoteComment
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package fr.dcproject.routes
|
package fr.dcproject.routes
|
||||||
|
|
||||||
import fr.dcproject.citizen
|
import fr.dcproject.citizen
|
||||||
import fr.dcproject.entity.Citizen
|
import fr.dcproject.component.citizen.Citizen
|
||||||
import fr.dcproject.entity.VoteForUpdate
|
import fr.dcproject.entity.VoteForUpdate
|
||||||
import fr.dcproject.routes.VoteConstitutionPaths.ConstitutionVoteRequest.Content
|
import fr.dcproject.routes.VoteConstitutionPaths.ConstitutionVoteRequest.Content
|
||||||
import fr.dcproject.security.voter.VoteVoter.Action.CREATE
|
import fr.dcproject.security.voter.VoteVoter.Action.CREATE
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package fr.dcproject.routes
|
package fr.dcproject.routes
|
||||||
|
|
||||||
import fr.dcproject.citizen
|
import fr.dcproject.citizen
|
||||||
import fr.dcproject.entity.CitizenRef
|
import fr.dcproject.component.citizen.CitizenRef
|
||||||
import fr.dcproject.entity.WorkgroupSimple
|
import fr.dcproject.entity.WorkgroupSimple
|
||||||
import fr.dcproject.entity.WorkgroupWithMembersI.Member
|
import fr.dcproject.entity.WorkgroupWithMembersI.Member
|
||||||
import fr.dcproject.entity.WorkgroupWithMembersI.Member.Role
|
import fr.dcproject.entity.WorkgroupWithMembersI.Member.Role
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package fr.dcproject.views
|
package fr.dcproject.views
|
||||||
|
|
||||||
import fr.dcproject.entity.CitizenI
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
import fr.dcproject.entity.ViewAggregation
|
import fr.dcproject.entity.ViewAggregation
|
||||||
import org.elasticsearch.client.Response
|
import org.elasticsearch.client.Response
|
||||||
import org.joda.time.DateTime
|
import org.joda.time.DateTime
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
package fr.dcproject.security.voter
|
|
||||||
|
|
||||||
import fr.dcproject.entity.CitizenBasicI
|
|
||||||
import fr.dcproject.entity.CitizenWithUserI
|
|
||||||
import fr.dcproject.user
|
|
||||||
import fr.dcproject.voter.NoRuleDefinedException
|
|
||||||
import fr.dcproject.voter.NoSubjectDefinedException
|
|
||||||
import fr.ktorVoter.*
|
|
||||||
import io.ktor.application.*
|
|
||||||
import io.ktor.locations.*
|
|
||||||
|
|
||||||
@KtorExperimentalLocationsAPI
|
|
||||||
class CitizenVoter : Voter<ApplicationCall> {
|
|
||||||
enum class Action : ActionI {
|
|
||||||
CREATE,
|
|
||||||
UPDATE,
|
|
||||||
VIEW,
|
|
||||||
DELETE,
|
|
||||||
CHANGE_PASSWORD
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun invoke(action: Any, context: ApplicationCall, subject: Any?): VoterResponseI {
|
|
||||||
if (!((action is Action)
|
|
||||||
&& (subject is CitizenBasicI?))) return abstain()
|
|
||||||
|
|
||||||
val user = context.user
|
|
||||||
if (action == Action.CREATE && user != null) {
|
|
||||||
return granted()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (action == Action.VIEW) {
|
|
||||||
if (user == null) return denied("You must be connected to view citizen", "citizen.view.connected")
|
|
||||||
if (subject is CitizenBasicI) {
|
|
||||||
return if (subject.isDeleted()) denied("You cannot view a deleted citizen", "citizen.view.deleted")
|
|
||||||
else granted()
|
|
||||||
}
|
|
||||||
throw NoRuleDefinedException(action)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (action == Action.DELETE) {
|
|
||||||
return denied("You can never deleted a citizen", "citizen.delete.never")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (action == Action.UPDATE) {
|
|
||||||
if (user == null) return denied("You must be connected to update Citizen", "citizen.update.notConnected")
|
|
||||||
if (subject !is CitizenWithUserI) throw NoSubjectDefinedException(action)
|
|
||||||
return if (subject.user.id == user.id) granted() else denied("You can only update your citizen", "citizen.update.notYours")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (action == Action.CHANGE_PASSWORD && user != null && subject is CitizenBasicI) {
|
|
||||||
val userToChange = subject.user
|
|
||||||
return if (user.id == userToChange.id) {
|
|
||||||
granted()
|
|
||||||
} else {
|
|
||||||
denied("You can only change your password", "citizen.password.notYours")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw NoRuleDefinedException(action)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package fr.dcproject.security.voter
|
package fr.dcproject.security.voter
|
||||||
|
|
||||||
import fr.dcproject.citizenOrNull
|
import fr.dcproject.citizenOrNull
|
||||||
import fr.dcproject.entity.CitizenI
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
import fr.dcproject.entity.FollowI
|
import fr.dcproject.entity.FollowI
|
||||||
import fr.dcproject.voter.NoSubjectDefinedException
|
import fr.dcproject.voter.NoSubjectDefinedException
|
||||||
import fr.ktorVoter.*
|
import fr.ktorVoter.*
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import fr.dcproject.Env
|
import fr.dcproject.Env
|
||||||
import fr.dcproject.component.article.ArticleRefVersioning
|
import fr.dcproject.component.article.ArticleRefVersioning
|
||||||
import fr.dcproject.component.article.ArticleViewManager
|
import fr.dcproject.component.article.ArticleViewManager
|
||||||
import fr.dcproject.entity.CitizenRef
|
import fr.dcproject.component.citizen.CitizenRef
|
||||||
import fr.dcproject.module
|
import fr.dcproject.module
|
||||||
import io.ktor.locations.*
|
import io.ktor.locations.*
|
||||||
import io.ktor.server.testing.*
|
import io.ktor.server.testing.*
|
||||||
|
|||||||
@@ -3,7 +3,11 @@ package feature
|
|||||||
import fr.dcproject.component.article.ArticleForUpdate
|
import fr.dcproject.component.article.ArticleForUpdate
|
||||||
import fr.dcproject.component.article.ArticleForView
|
import fr.dcproject.component.article.ArticleForView
|
||||||
import fr.dcproject.component.article.ArticleRepository
|
import fr.dcproject.component.article.ArticleRepository
|
||||||
import fr.dcproject.entity.*
|
import fr.dcproject.component.citizen.Citizen
|
||||||
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
|
import fr.dcproject.component.citizen.CitizenRepository
|
||||||
|
import fr.dcproject.entity.CommentForUpdate
|
||||||
|
import fr.dcproject.entity.WorkgroupRef
|
||||||
import fr.dcproject.repository.CommentArticle
|
import fr.dcproject.repository.CommentArticle
|
||||||
import fr.dcproject.utils.toUUID
|
import fr.dcproject.utils.toUUID
|
||||||
import io.cucumber.datatable.DataTable
|
import io.cucumber.datatable.DataTable
|
||||||
@@ -13,7 +17,6 @@ import org.koin.test.KoinTest
|
|||||||
import org.koin.test.get
|
import org.koin.test.get
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import fr.dcproject.entity.User as UserEntity
|
import fr.dcproject.entity.User as UserEntity
|
||||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
|
||||||
|
|
||||||
class ArticleSteps : En, KoinTest {
|
class ArticleSteps : En, KoinTest {
|
||||||
init {
|
init {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
package feature
|
package feature
|
||||||
|
|
||||||
import fr.dcproject.entity.Citizen
|
import fr.dcproject.component.citizen.Citizen
|
||||||
import fr.dcproject.entity.CitizenI
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
|
import fr.dcproject.component.citizen.CitizenRepository
|
||||||
import fr.dcproject.entity.User
|
import fr.dcproject.entity.User
|
||||||
import io.cucumber.datatable.DataTable
|
import io.cucumber.datatable.DataTable
|
||||||
import io.cucumber.java8.En
|
import io.cucumber.java8.En
|
||||||
@@ -9,7 +10,6 @@ import org.joda.time.DateTime
|
|||||||
import org.koin.test.KoinTest
|
import org.koin.test.KoinTest
|
||||||
import org.koin.test.get
|
import org.koin.test.get
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
|
||||||
|
|
||||||
class CitizenSteps : En, KoinTest {
|
class CitizenSteps : En, KoinTest {
|
||||||
init {
|
init {
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
package feature
|
package feature
|
||||||
|
|
||||||
import fr.dcproject.component.article.ArticleRef
|
import fr.dcproject.component.article.ArticleRef
|
||||||
import fr.dcproject.entity.*
|
import fr.dcproject.component.citizen.Citizen
|
||||||
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
|
import fr.dcproject.component.citizen.CitizenRepository
|
||||||
|
import fr.dcproject.component.citizen.CitizenWithUserI
|
||||||
|
import fr.dcproject.entity.CommentForUpdate
|
||||||
|
import fr.dcproject.entity.ConstitutionRef
|
||||||
|
import fr.dcproject.entity.ConstitutionSimple
|
||||||
import fr.dcproject.repository.CommentConstitution
|
import fr.dcproject.repository.CommentConstitution
|
||||||
import fr.dcproject.utils.toUUID
|
import fr.dcproject.utils.toUUID
|
||||||
import io.cucumber.datatable.DataTable
|
import io.cucumber.datatable.DataTable
|
||||||
@@ -11,7 +17,6 @@ import org.koin.test.KoinTest
|
|||||||
import org.koin.test.get
|
import org.koin.test.get
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import fr.dcproject.entity.User as UserEntity
|
import fr.dcproject.entity.User as UserEntity
|
||||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
|
||||||
import fr.dcproject.repository.Constitution as ConstitutionRepository
|
import fr.dcproject.repository.Constitution as ConstitutionRepository
|
||||||
|
|
||||||
class ConstitutionSteps : En, KoinTest {
|
class ConstitutionSteps : En, KoinTest {
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package feature
|
package feature
|
||||||
|
|
||||||
import fr.dcproject.component.article.ArticleRef
|
import fr.dcproject.component.article.ArticleRef
|
||||||
|
import fr.dcproject.component.citizen.CitizenRepository
|
||||||
import fr.dcproject.entity.ConstitutionRef
|
import fr.dcproject.entity.ConstitutionRef
|
||||||
import fr.dcproject.entity.FollowForUpdate
|
import fr.dcproject.entity.FollowForUpdate
|
||||||
import fr.dcproject.utils.toUUID
|
import fr.dcproject.utils.toUUID
|
||||||
import io.cucumber.java8.En
|
import io.cucumber.java8.En
|
||||||
import org.koin.test.KoinTest
|
import org.koin.test.KoinTest
|
||||||
import org.koin.test.get
|
import org.koin.test.get
|
||||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
|
||||||
import fr.dcproject.repository.FollowArticle as FollowArticleRepository
|
import fr.dcproject.repository.FollowArticle as FollowArticleRepository
|
||||||
import fr.dcproject.repository.FollowConstitution as FollowConstitutionRepository
|
import fr.dcproject.repository.FollowConstitution as FollowConstitutionRepository
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ package feature
|
|||||||
|
|
||||||
import com.auth0.jwt.JWT
|
import com.auth0.jwt.JWT
|
||||||
import fr.dcproject.JwtConfig
|
import fr.dcproject.JwtConfig
|
||||||
|
import fr.dcproject.component.citizen.CitizenRepository
|
||||||
import io.cucumber.java8.En
|
import io.cucumber.java8.En
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import org.koin.test.KoinTest
|
import org.koin.test.KoinTest
|
||||||
import org.koin.test.get
|
import org.koin.test.get
|
||||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
|
||||||
|
|
||||||
class KtorServerAuthSteps : En, KoinTest {
|
class KtorServerAuthSteps : En, KoinTest {
|
||||||
init {
|
init {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package feature
|
|||||||
|
|
||||||
import fr.dcproject.component.article.ArticleRef
|
import fr.dcproject.component.article.ArticleRef
|
||||||
import fr.dcproject.component.article.ArticleRepository
|
import fr.dcproject.component.article.ArticleRepository
|
||||||
|
import fr.dcproject.component.citizen.CitizenRepository
|
||||||
import fr.dcproject.entity.OpinionChoice
|
import fr.dcproject.entity.OpinionChoice
|
||||||
import fr.dcproject.entity.OpinionForUpdate
|
import fr.dcproject.entity.OpinionForUpdate
|
||||||
import fr.dcproject.utils.toUUID
|
import fr.dcproject.utils.toUUID
|
||||||
@@ -10,7 +11,6 @@ import io.cucumber.java8.En
|
|||||||
import org.koin.test.KoinTest
|
import org.koin.test.KoinTest
|
||||||
import org.koin.test.get
|
import org.koin.test.get
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
|
||||||
import fr.dcproject.repository.OpinionArticle as OpinionRepository
|
import fr.dcproject.repository.OpinionArticle as OpinionRepository
|
||||||
import fr.dcproject.repository.OpinionChoice as OpinionChoiceRepository
|
import fr.dcproject.repository.OpinionChoice as OpinionChoiceRepository
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package feature
|
package feature
|
||||||
|
|
||||||
import fr.dcproject.component.article.ArticleRepository
|
import fr.dcproject.component.article.ArticleRepository
|
||||||
|
import fr.dcproject.component.citizen.CitizenRepository
|
||||||
import fr.dcproject.entity.VoteForUpdate
|
import fr.dcproject.entity.VoteForUpdate
|
||||||
import fr.dcproject.utils.toUUID
|
import fr.dcproject.utils.toUUID
|
||||||
import io.cucumber.java8.En
|
import io.cucumber.java8.En
|
||||||
import org.koin.test.KoinTest
|
import org.koin.test.KoinTest
|
||||||
import org.koin.test.get
|
import org.koin.test.get
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
|
||||||
import fr.dcproject.repository.VoteArticle as VoteRepository
|
import fr.dcproject.repository.VoteArticle as VoteRepository
|
||||||
|
|
||||||
class VoteSteps : En, KoinTest {
|
class VoteSteps : En, KoinTest {
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
package feature
|
package feature
|
||||||
|
|
||||||
|
import fr.dcproject.component.citizen.Citizen
|
||||||
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
|
import fr.dcproject.component.citizen.CitizenRef
|
||||||
|
import fr.dcproject.component.citizen.CitizenRepository
|
||||||
import fr.dcproject.entity.*
|
import fr.dcproject.entity.*
|
||||||
import fr.dcproject.entity.WorkgroupWithMembersI.Member
|
import fr.dcproject.entity.WorkgroupWithMembersI.Member
|
||||||
import fr.dcproject.utils.toUUID
|
import fr.dcproject.utils.toUUID
|
||||||
@@ -10,7 +14,6 @@ import org.junit.Assert
|
|||||||
import org.koin.test.KoinTest
|
import org.koin.test.KoinTest
|
||||||
import org.koin.test.get
|
import org.koin.test.get
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import fr.dcproject.repository.Citizen as CitizenRepository
|
|
||||||
import fr.dcproject.repository.Workgroup as WorkgroupRepository
|
import fr.dcproject.repository.Workgroup as WorkgroupRepository
|
||||||
|
|
||||||
class WorkgroupSteps : En, KoinTest {
|
class WorkgroupSteps : En, KoinTest {
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ package fr.dcproject.security.voter
|
|||||||
|
|
||||||
import fr.dcproject.component.article.ArticleForView
|
import fr.dcproject.component.article.ArticleForView
|
||||||
import fr.dcproject.component.article.ArticleVoter
|
import fr.dcproject.component.article.ArticleVoter
|
||||||
import fr.dcproject.entity.CitizenCart
|
import fr.dcproject.component.citizen.CitizenCart
|
||||||
import fr.dcproject.entity.CitizenI
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
import fr.dcproject.entity.User
|
import fr.dcproject.entity.User
|
||||||
import fr.dcproject.entity.UserI
|
import fr.dcproject.entity.UserI
|
||||||
import fr.dcproject.voter.Vote.DENIED
|
import fr.dcproject.voter.Vote.DENIED
|
||||||
|
|||||||
@@ -1,22 +1,19 @@
|
|||||||
package fr.dcproject.security.voter
|
package fr.dcproject.security.voter
|
||||||
|
|
||||||
import fr.dcproject.entity.CitizenBasic
|
import fr.dcproject.component.citizen.CitizenBasic
|
||||||
import fr.dcproject.entity.CitizenI
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
|
import fr.dcproject.component.citizen.CitizenVoter
|
||||||
import fr.dcproject.entity.User
|
import fr.dcproject.entity.User
|
||||||
import fr.dcproject.entity.UserI
|
import fr.dcproject.entity.UserI
|
||||||
import fr.dcproject.user
|
import fr.dcproject.voter.Vote.DENIED
|
||||||
import fr.ktorVoter.*
|
import fr.dcproject.voter.Vote.GRANTED
|
||||||
import io.ktor.application.*
|
|
||||||
import io.ktor.locations.*
|
import io.ktor.locations.*
|
||||||
import io.mockk.every
|
|
||||||
import io.mockk.mockk
|
|
||||||
import io.mockk.mockkStatic
|
import io.mockk.mockkStatic
|
||||||
import org.amshove.kluent.`should be`
|
import org.amshove.kluent.`should be`
|
||||||
import org.joda.time.DateTime
|
import org.joda.time.DateTime
|
||||||
import org.junit.jupiter.api.Tag
|
import org.junit.jupiter.api.Tag
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.TestInstance
|
import org.junit.jupiter.api.TestInstance
|
||||||
import org.junit.jupiter.api.assertThrows
|
|
||||||
|
|
||||||
@KtorExperimentalLocationsAPI
|
@KtorExperimentalLocationsAPI
|
||||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||||
@@ -57,78 +54,51 @@ class CitizenVoterTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `support citizen`(): Unit = CitizenVoter().run {
|
fun `can be view the citizen`() {
|
||||||
val p = object : ActionI {}
|
CitizenVoter()
|
||||||
mockk<ApplicationCall> {
|
.canView(subject = einstein, connectedCitizen = tesla)
|
||||||
every { user } returns tesla.user
|
.vote `should be` GRANTED
|
||||||
}.let {
|
|
||||||
this(CitizenVoter.Action.VIEW, it, einstein).vote `should be` Vote.GRANTED
|
|
||||||
this(p, it, einstein).vote `should be` Vote.ABSTAIN
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `can be view the citizen`(): Unit = listOf(CitizenVoter()).run {
|
fun `can be view the citizen list`() {
|
||||||
mockk<ApplicationCall> {
|
CitizenVoter()
|
||||||
every { user } returns tesla.user
|
.canView(subjects = listOf(tesla, einstein), connectedCitizen = einstein)
|
||||||
}.let {
|
.vote `should be` GRANTED
|
||||||
can(CitizenVoter.Action.VIEW, it, einstein) `should be` true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `can be view the citizen list`(): Unit = listOf(CitizenVoter()).run {
|
fun `can not view deleted citizen`() {
|
||||||
mockk<ApplicationCall> {
|
CitizenVoter()
|
||||||
every { user } returns einstein.user
|
.canView(subject = curie, connectedCitizen = tesla)
|
||||||
}.let {
|
.vote `should be` DENIED
|
||||||
canAll(CitizenVoter.Action.VIEW, it, listOf(einstein, tesla)) `should be` true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `can not view deleted citizen`(): Unit = listOf(CitizenVoter()).run {
|
fun `can be update itself`() {
|
||||||
mockk<ApplicationCall> {
|
CitizenVoter()
|
||||||
every { user } returns tesla.user
|
.canUpdate(subject = einstein, connectedCitizen = einstein)
|
||||||
}.let {
|
.vote `should be` GRANTED
|
||||||
can(CitizenVoter.Action.VIEW, it, curie) `should be` false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `can be update itself`(): Unit = listOf(CitizenVoter()).run {
|
fun `can not be update other citizen`() {
|
||||||
mockk<ApplicationCall> {
|
CitizenVoter()
|
||||||
every { user } returns einstein.user
|
.canUpdate(subject = tesla, connectedCitizen = einstein)
|
||||||
}.let {
|
.vote `should be` DENIED
|
||||||
can(CitizenVoter.Action.UPDATE, it, einstein) `should be` true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `can not be update other citizen`(): Unit = listOf(CitizenVoter()).run {
|
fun `can be change password of itself`() {
|
||||||
mockk<ApplicationCall> {
|
CitizenVoter()
|
||||||
every { user } returns einstein.user
|
.canChangePassword(subject = einstein, connectedCitizen = einstein)
|
||||||
}.let {
|
.vote `should be` GRANTED
|
||||||
assertThrows<OneOrMoreVoterDeniedException> {
|
|
||||||
assertCan(CitizenVoter.Action.UPDATE, it, tesla)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `can be change password of itself`(): Unit = listOf(CitizenVoter()).run {
|
fun `can not be change password of other citizen`() {
|
||||||
mockk<ApplicationCall> {
|
CitizenVoter()
|
||||||
every { user } returns einstein.user
|
.canChangePassword(subject = tesla, connectedCitizen = einstein)
|
||||||
}.let {
|
.vote `should be` DENIED
|
||||||
can(CitizenVoter.Action.CHANGE_PASSWORD, it, einstein) `should be` true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `can not be change password of other citizen`(): Unit = listOf(CitizenVoter()).run {
|
|
||||||
mockk<ApplicationCall> {
|
|
||||||
every { user } returns einstein.user
|
|
||||||
}.let {
|
|
||||||
can(CitizenVoter.Action.CHANGE_PASSWORD, it, tesla) `should be` false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,10 +3,15 @@ package fr.dcproject.security.voter
|
|||||||
import fr.dcproject.citizenOrNull
|
import fr.dcproject.citizenOrNull
|
||||||
import fr.dcproject.component.article.ArticleForView
|
import fr.dcproject.component.article.ArticleForView
|
||||||
import fr.dcproject.component.article.ArticleRef
|
import fr.dcproject.component.article.ArticleRef
|
||||||
import fr.dcproject.entity.*
|
import fr.dcproject.component.citizen.Citizen
|
||||||
|
import fr.dcproject.component.citizen.CitizenCart
|
||||||
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
|
import fr.dcproject.entity.CommentForUpdate
|
||||||
|
import fr.dcproject.entity.CommentForView
|
||||||
|
import fr.dcproject.entity.User
|
||||||
|
import fr.dcproject.entity.UserI
|
||||||
import fr.dcproject.voter.NoSubjectDefinedException
|
import fr.dcproject.voter.NoSubjectDefinedException
|
||||||
import fr.ktorVoter.*
|
import fr.ktorVoter.*
|
||||||
import fr.ktorVoter.Vote
|
|
||||||
import fr.postgresjson.connexion.Paginated
|
import fr.postgresjson.connexion.Paginated
|
||||||
import io.ktor.application.*
|
import io.ktor.application.*
|
||||||
import io.ktor.locations.*
|
import io.ktor.locations.*
|
||||||
|
|||||||
@@ -2,7 +2,13 @@ package fr.dcproject.security.voter
|
|||||||
|
|
||||||
import fr.dcproject.citizenOrNull
|
import fr.dcproject.citizenOrNull
|
||||||
import fr.dcproject.component.article.ArticleForView
|
import fr.dcproject.component.article.ArticleForView
|
||||||
import fr.dcproject.entity.*
|
import fr.dcproject.component.citizen.Citizen
|
||||||
|
import fr.dcproject.component.citizen.CitizenBasic
|
||||||
|
import fr.dcproject.component.citizen.CitizenCart
|
||||||
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
|
import fr.dcproject.entity.Follow
|
||||||
|
import fr.dcproject.entity.User
|
||||||
|
import fr.dcproject.entity.UserI
|
||||||
import fr.dcproject.voter.NoSubjectDefinedException
|
import fr.dcproject.voter.NoSubjectDefinedException
|
||||||
import fr.ktorVoter.ActionI
|
import fr.ktorVoter.ActionI
|
||||||
import fr.ktorVoter.Vote
|
import fr.ktorVoter.Vote
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
package fr.dcproject.security.voter
|
package fr.dcproject.security.voter
|
||||||
|
|
||||||
import fr.dcproject.component.article.ArticleForView
|
import fr.dcproject.component.article.ArticleForView
|
||||||
import fr.dcproject.entity.*
|
import fr.dcproject.component.citizen.CitizenBasic
|
||||||
|
import fr.dcproject.component.citizen.CitizenCart
|
||||||
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
|
import fr.dcproject.entity.OpinionChoice
|
||||||
|
import fr.dcproject.entity.User
|
||||||
|
import fr.dcproject.entity.UserI
|
||||||
import fr.dcproject.user
|
import fr.dcproject.user
|
||||||
import fr.ktorVoter.ActionI
|
import fr.ktorVoter.ActionI
|
||||||
import fr.ktorVoter.Vote
|
import fr.ktorVoter.Vote
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
package fr.dcproject.security.voter
|
package fr.dcproject.security.voter
|
||||||
|
|
||||||
import fr.dcproject.component.article.ArticleForView
|
import fr.dcproject.component.article.ArticleForView
|
||||||
import fr.dcproject.entity.*
|
import fr.dcproject.component.citizen.CitizenBasic
|
||||||
|
import fr.dcproject.component.citizen.CitizenCart
|
||||||
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
|
import fr.dcproject.entity.Opinion
|
||||||
|
import fr.dcproject.entity.OpinionChoice
|
||||||
|
import fr.dcproject.entity.User
|
||||||
|
import fr.dcproject.entity.UserI
|
||||||
import fr.dcproject.user
|
import fr.dcproject.user
|
||||||
import fr.dcproject.voter.NoSubjectDefinedException
|
import fr.dcproject.voter.NoSubjectDefinedException
|
||||||
import fr.ktorVoter.*
|
import fr.ktorVoter.*
|
||||||
import fr.ktorVoter.Vote
|
|
||||||
import io.ktor.application.*
|
import io.ktor.application.*
|
||||||
import io.ktor.locations.*
|
import io.ktor.locations.*
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
|
|||||||
@@ -3,7 +3,13 @@ package fr.dcproject.security.voter
|
|||||||
import fr.dcproject.citizenOrNull
|
import fr.dcproject.citizenOrNull
|
||||||
import fr.dcproject.component.article.ArticleForView
|
import fr.dcproject.component.article.ArticleForView
|
||||||
import fr.dcproject.component.article.ArticleRef
|
import fr.dcproject.component.article.ArticleRef
|
||||||
import fr.dcproject.entity.*
|
import fr.dcproject.component.citizen.Citizen
|
||||||
|
import fr.dcproject.component.citizen.CitizenBasic
|
||||||
|
import fr.dcproject.component.citizen.CitizenCart
|
||||||
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
|
import fr.dcproject.entity.User
|
||||||
|
import fr.dcproject.entity.UserI
|
||||||
|
import fr.dcproject.entity.VoteForUpdate
|
||||||
import fr.dcproject.voter.NoSubjectDefinedException
|
import fr.dcproject.voter.NoSubjectDefinedException
|
||||||
import fr.ktorVoter.ActionI
|
import fr.ktorVoter.ActionI
|
||||||
import fr.ktorVoter.Vote
|
import fr.ktorVoter.Vote
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
package fr.dcproject.security.voter
|
package fr.dcproject.security.voter
|
||||||
|
|
||||||
import fr.dcproject.component.article.ArticleForView
|
import fr.dcproject.component.article.ArticleForView
|
||||||
import fr.dcproject.entity.*
|
import fr.dcproject.component.citizen.CitizenBasic
|
||||||
|
import fr.dcproject.component.citizen.CitizenCart
|
||||||
|
import fr.dcproject.component.citizen.CitizenI
|
||||||
|
import fr.dcproject.entity.User
|
||||||
|
import fr.dcproject.entity.UserI
|
||||||
|
import fr.dcproject.entity.WorkgroupRef
|
||||||
|
import fr.dcproject.entity.WorkgroupWithMembersI
|
||||||
import fr.dcproject.user
|
import fr.dcproject.user
|
||||||
import fr.dcproject.voter.NoSubjectDefinedException
|
import fr.dcproject.voter.NoSubjectDefinedException
|
||||||
import fr.ktorVoter.ActionI
|
import fr.ktorVoter.ActionI
|
||||||
|
|||||||
Reference in New Issue
Block a user