roles update and gradle scripts fixes
This commit is contained in:
client/src/commonMain/kotlin/dev/inmo/postssystem/client
features/roles
client
src
commonMain
kotlin
dev
inmo
postssystem
common
src
commonMain
kotlin
dev
inmo
manager
common
src
commonMain
kotlin
dev
inmo
postssystem
features
roles
manager
server
src
jvmMain
kotlin
dev
inmo
postssystem
features
server
src
jvmMain
server/src/main/java/dev/inmo/postssystem/server
12
features/roles/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/roles/server/RolesChecker.kt
12
features/roles/server/src/jvmMain/kotlin/dev/inmo/postssystem/features/roles/server/RolesChecker.kt
@ -4,24 +4,24 @@ import dev.inmo.postssystem.features.roles.common.*
|
||||
import dev.inmo.postssystem.features.users.common.User
|
||||
import io.ktor.application.ApplicationCall
|
||||
|
||||
interface RolesChecker<T : UserRole> {
|
||||
interface RolesChecker<T : Role> {
|
||||
val key: String
|
||||
|
||||
suspend operator fun ApplicationCall.invoke(
|
||||
usersRolesStorage: ReadUsersRolesStorage<T>,
|
||||
usersRolesStorage: ReadRolesStorage<T>,
|
||||
user: User
|
||||
): Boolean
|
||||
|
||||
companion object {
|
||||
fun <T : UserRole> default(
|
||||
fun default(
|
||||
key: String,
|
||||
role: T
|
||||
): RolesChecker<T> = object : RolesChecker<T> {
|
||||
role: Role
|
||||
): RolesChecker<Role> = object : RolesChecker<Role> {
|
||||
override val key: String
|
||||
get() = key
|
||||
|
||||
override suspend fun ApplicationCall.invoke(
|
||||
usersRolesStorage: ReadUsersRolesStorage<T>,
|
||||
usersRolesStorage: ReadRolesStorage<Role>,
|
||||
user: User
|
||||
): Boolean = usersRolesStorage.contains(user.id, role)
|
||||
}
|
||||
|
@ -9,19 +9,19 @@ import io.ktor.routing.*
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
|
||||
class UsersRolesStorageWriteServerRoutesConfigurator<T : UserRole>(
|
||||
private val storage: WriteUsersRolesStorage<T>,
|
||||
class RolesStorageWriteServerRoutesConfigurator<T : Role>(
|
||||
private val storage: WriteRolesStorage<T>,
|
||||
private val serializer: KSerializer<T>,
|
||||
private val includeAuthKey: String,
|
||||
private val excludeAuthKey: String = includeAuthKey,
|
||||
private val unifiedRouter: UnifiedRouter
|
||||
) : ApplicationRoutingConfigurator.Element {
|
||||
override fun Route.invoke() {
|
||||
unifiedRouter.apply {
|
||||
route(usersRolesRootPathPart) {
|
||||
val wrapperSerializer = UserRolesStorageIncludeExcludeWrapper.serializer(
|
||||
serializer
|
||||
)
|
||||
route(usersRolesRootPathPart) {
|
||||
val wrapperSerializer = RolesStorageIncludeExcludeWrapper.serializer(
|
||||
serializer
|
||||
)
|
||||
unifiedRouter.apply {
|
||||
authenticate(includeAuthKey) {
|
||||
post(usersRolesIncludePathPart) {
|
||||
val wrapper = uniload(wrapperSerializer)
|
||||
@ -29,7 +29,7 @@ class UsersRolesStorageWriteServerRoutesConfigurator<T : UserRole>(
|
||||
unianswer(
|
||||
Boolean.serializer(),
|
||||
storage.include(
|
||||
wrapper.userId,
|
||||
wrapper.subject,
|
||||
wrapper.userRole
|
||||
)
|
||||
)
|
||||
@ -42,7 +42,7 @@ class UsersRolesStorageWriteServerRoutesConfigurator<T : UserRole>(
|
||||
unianswer(
|
||||
Boolean.serializer(),
|
||||
storage.exclude(
|
||||
wrapper.userId,
|
||||
wrapper.subject,
|
||||
wrapper.userRole
|
||||
)
|
||||
)
|
@ -1,39 +1,37 @@
|
||||
package dev.inmo.postssystem.features.roles.server
|
||||
|
||||
import dev.inmo.postssystem.features.roles.common.UserRole
|
||||
import dev.inmo.postssystem.features.roles.common.UsersRolesStorage
|
||||
import dev.inmo.postssystem.features.users.common.UserId
|
||||
import dev.inmo.postssystem.features.roles.common.*
|
||||
|
||||
class UsersRolesAggregator(
|
||||
private val otherStorages: List<UsersRolesStorageHolder<*>>
|
||||
) : UsersRolesStorage<UserRole> {
|
||||
class RolesAggregator(
|
||||
private val otherStorages: List<RolesStorageHolder<*>>
|
||||
) : RolesStorage<Role> {
|
||||
private val otherStoragesByClass = otherStorages.associateBy { it.kclass }
|
||||
|
||||
override suspend fun getUsers(userRole: UserRole): List<UserId> {
|
||||
return otherStoragesByClass[userRole::class] ?.getUsers(userRole) ?: emptyList()
|
||||
override suspend fun getSubjects(role: Role): List<RoleSubject> {
|
||||
return otherStoragesByClass[role::class] ?.getUsers(role) ?: emptyList()
|
||||
}
|
||||
|
||||
override suspend fun getRoles(userId: UserId): List<UserRole> = otherStorages.flatMap { it.getRoles(userId) }
|
||||
override suspend fun getRoles(subject: RoleSubject): List<Role> = otherStorages.flatMap { it.getRoles(subject) }
|
||||
|
||||
override suspend fun contains(userId: UserId, userRole: UserRole): Boolean {
|
||||
return otherStoragesByClass[userRole::class] ?.contains(userId, userRole) ?: false
|
||||
override suspend fun contains(subject: RoleSubject, role: Role): Boolean {
|
||||
return otherStoragesByClass[role::class] ?.contains(subject, role) ?: false
|
||||
}
|
||||
|
||||
override suspend fun containsAny(userId: UserId, userRoles: List<UserRole>): Boolean {
|
||||
return userRoles.any {
|
||||
contains(userId, it)
|
||||
override suspend fun containsAny(subject: RoleSubject, roles: List<Role>): Boolean {
|
||||
return roles.any {
|
||||
contains(subject, it)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun include(
|
||||
userId: UserId,
|
||||
userRole: UserRole
|
||||
): Boolean = otherStoragesByClass[userRole::class] ?.include(userId, userRole) ?: false
|
||||
subject: RoleSubject,
|
||||
role: Role
|
||||
): Boolean = otherStoragesByClass[role::class] ?.include(subject, role) ?: false
|
||||
|
||||
override suspend fun exclude(
|
||||
userId: UserId,
|
||||
userRole: UserRole
|
||||
subject: RoleSubject,
|
||||
role: Role
|
||||
): Boolean {
|
||||
return otherStoragesByClass[userRole::class] ?.exclude(userId, userRole) ?: false
|
||||
return otherStoragesByClass[role::class] ?.exclude(subject, role) ?: false
|
||||
}
|
||||
}
|
||||
|
@ -4,18 +4,18 @@ import dev.inmo.postssystem.features.auth.common.AuthToken
|
||||
import dev.inmo.postssystem.features.auth.server.principal
|
||||
import dev.inmo.postssystem.features.auth.server.tokens.AuthTokensService
|
||||
import dev.inmo.postssystem.features.common.server.sessions.ApplicationAuthenticationConfigurator
|
||||
import dev.inmo.postssystem.features.roles.common.UserRole
|
||||
import dev.inmo.postssystem.features.roles.common.UsersRolesStorage
|
||||
import dev.inmo.postssystem.features.roles.common.Role
|
||||
import dev.inmo.postssystem.features.roles.common.RolesStorage
|
||||
import io.ktor.application.call
|
||||
import io.ktor.auth.Authentication
|
||||
import io.ktor.auth.session
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.response.respond
|
||||
|
||||
class UsersRolesAuthenticationConfigurator<T : UserRole>(
|
||||
private val usersRolesStorage: UsersRolesStorage<T>,
|
||||
class RolesAuthenticationConfigurator<T : Role>(
|
||||
private val usersRolesStorage: RolesStorage<T>,
|
||||
private val authTokensService: AuthTokensService,
|
||||
private val rolesCheckers: List<RolesChecker<T>>,
|
||||
private val rolesCheckers: List<RolesChecker<T>>
|
||||
) : ApplicationAuthenticationConfigurator.Element {
|
||||
override fun Authentication.Configuration.invoke() {
|
||||
rolesCheckers.forEach { checker ->
|
||||
|
@ -1,42 +1,40 @@
|
||||
package dev.inmo.postssystem.features.roles.server
|
||||
|
||||
import dev.inmo.postssystem.features.roles.common.UserRole
|
||||
import dev.inmo.postssystem.features.roles.common.UsersRolesStorage
|
||||
import dev.inmo.postssystem.features.users.common.UserId
|
||||
import dev.inmo.postssystem.features.roles.common.*
|
||||
import dev.inmo.micro_utils.common.*
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
data class UsersRolesStorageHolder<T : UserRole>(
|
||||
data class RolesStorageHolder<T : Role>(
|
||||
val kclass: KClass<T>,
|
||||
val storage: UsersRolesStorage<T>
|
||||
val storage: RolesStorage<T>
|
||||
) {
|
||||
private suspend fun <R> doIfRelevant(
|
||||
userRole: UserRole,
|
||||
role: Role,
|
||||
block: suspend (T) -> R
|
||||
): Optional<R> = if (kclass.isInstance(userRole)) {
|
||||
block(userRole as T).optional
|
||||
): Optional<R> = if (kclass.isInstance(role)) {
|
||||
block(role as T).optional
|
||||
} else {
|
||||
Optional.absent()
|
||||
}
|
||||
|
||||
suspend fun getUsers(userRole: UserRole): List<UserId>? = doIfRelevant(userRole) {
|
||||
storage.getUsers(it)
|
||||
suspend fun getUsers(role: Role): List<RoleSubject>? = doIfRelevant(role) {
|
||||
storage.getSubjects(it)
|
||||
}.dataOrNull()
|
||||
|
||||
suspend fun getRoles(userId: UserId): List<UserRole> = storage.getRoles(userId)
|
||||
suspend fun getRoles(subject: RoleSubject): List<Role> = storage.getRoles(subject)
|
||||
|
||||
suspend fun contains(userId: UserId, userRole: UserRole): Boolean? = doIfRelevant(userRole) {
|
||||
storage.contains(userId, it)
|
||||
suspend fun contains(subject: RoleSubject, role: Role): Boolean? = doIfRelevant(role) {
|
||||
storage.contains(subject, it)
|
||||
}.dataOrNull()
|
||||
|
||||
suspend fun include(
|
||||
userId: UserId,
|
||||
userRole: UserRole
|
||||
): Boolean? = doIfRelevant(userRole) {
|
||||
storage.include(userId, it)
|
||||
subject: RoleSubject,
|
||||
role: Role
|
||||
): Boolean? = doIfRelevant(role) {
|
||||
storage.include(subject, it)
|
||||
}.dataOrNull()
|
||||
|
||||
suspend fun exclude(userId: UserId, userRole: UserRole): Boolean? = doIfRelevant(userRole) {
|
||||
storage.exclude(userId, it)
|
||||
suspend fun exclude(subject: RoleSubject, role: Role): Boolean? = doIfRelevant(role) {
|
||||
storage.exclude(subject, it)
|
||||
}.dataOrNull()
|
||||
}
|
||||
|
@ -1,18 +1,16 @@
|
||||
package dev.inmo.postssystem.features.roles.server
|
||||
|
||||
import dev.inmo.postssystem.features.roles.common.*
|
||||
import dev.inmo.postssystem.features.users.common.UserId
|
||||
import dev.inmo.micro_utils.ktor.server.*
|
||||
import dev.inmo.micro_utils.ktor.server.configurators.ApplicationRoutingConfigurator
|
||||
import io.ktor.application.call
|
||||
import io.ktor.auth.authenticate
|
||||
import io.ktor.routing.*
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.builtins.ListSerializer
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
|
||||
class UsersRolesStorageReadServerRoutesConfigurator<T : UserRole>(
|
||||
private val storage: ReadUsersRolesStorage<T>,
|
||||
class RolesStorageReadServerRoutesConfigurator<T : Role>(
|
||||
private val storage: ReadRolesStorage<T>,
|
||||
private val serializer: KSerializer<T>,
|
||||
private val unifiedRouter: UnifiedRouter
|
||||
) : ApplicationRoutingConfigurator.Element {
|
||||
@ -21,51 +19,53 @@ class UsersRolesStorageReadServerRoutesConfigurator<T : UserRole>(
|
||||
unifiedRouter.apply {
|
||||
authenticate {
|
||||
route(usersRolesRootPathPart) {
|
||||
get(usersRolesGetUsersPathPart) {
|
||||
val userRole = decodeUrlQueryValueOrSendError(usersRolesUserRoleQueryParameterName, serializer)
|
||||
get(usersRolesGetSubjectsPathPart) {
|
||||
val role = decodeUrlQueryValueOrSendError(usersRolesRoleQueryParameterName, serializer)
|
||||
?: return@get
|
||||
unianswer(
|
||||
UsersIdsSerializer,
|
||||
storage.getUsers(userRole)
|
||||
RoleSubjectsSerializer,
|
||||
storage.getSubjects(role)
|
||||
)
|
||||
}
|
||||
|
||||
get(usersRolesGetRolesPathPart) {
|
||||
val userId = decodeUrlQueryValueOrSendError(usersRolesUserIdQueryParameterName, UserId.serializer())
|
||||
?: return@get
|
||||
val subject = decodeUrlQueryValueOrSendError(
|
||||
usersRolesRoleSubjectQueryParameterName,
|
||||
RoleSubject.serializer()
|
||||
) ?: return@get
|
||||
unianswer(
|
||||
userRolesSerializer,
|
||||
storage.getRoles(userId)
|
||||
storage.getRoles(subject)
|
||||
)
|
||||
}
|
||||
|
||||
get(usersRolesContainsPathPart) {
|
||||
val userId = decodeUrlQueryValueOrSendError(
|
||||
usersRolesUserIdQueryParameterName,
|
||||
UserId.serializer()
|
||||
val subject = decodeUrlQueryValueOrSendError(
|
||||
usersRolesRoleSubjectQueryParameterName,
|
||||
RoleSubject.serializer()
|
||||
) ?: return@get
|
||||
val userRole = decodeUrlQueryValueOrSendError(
|
||||
usersRolesUserRoleQueryParameterName,
|
||||
val role = decodeUrlQueryValueOrSendError(
|
||||
usersRolesRoleQueryParameterName,
|
||||
serializer
|
||||
) ?: return@get
|
||||
unianswer(
|
||||
Boolean.serializer(),
|
||||
storage.contains(userId, userRole)
|
||||
storage.contains(subject, role)
|
||||
)
|
||||
}
|
||||
|
||||
get(usersRolesContainsAnyPathPart) {
|
||||
val userId = decodeUrlQueryValueOrSendError(
|
||||
usersRolesUserIdQueryParameterName,
|
||||
UserId.serializer()
|
||||
val subject = decodeUrlQueryValueOrSendError(
|
||||
usersRolesRoleSubjectQueryParameterName,
|
||||
RoleSubject.serializer()
|
||||
) ?: return@get
|
||||
val userRoles = decodeUrlQueryValueOrSendError(
|
||||
usersRolesUserRoleQueryParameterName,
|
||||
usersRolesRoleQueryParameterName,
|
||||
userRolesSerializer
|
||||
) ?: return@get
|
||||
unianswer(
|
||||
Boolean.serializer(),
|
||||
storage.containsAny(userId, userRoles)
|
||||
storage.containsAny(subject, userRoles)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user