add content

This commit is contained in:
InsanusMokrassar 2021-11-24 20:25:05 +06:00
parent fffe99adaa
commit 58b7e973be
24 changed files with 398 additions and 176 deletions

View File

@ -20,6 +20,7 @@ kotlin {
api project(":postssystem.features.auth.client") api project(":postssystem.features.auth.client")
api project(":postssystem.features.roles.client") api project(":postssystem.features.roles.client")
api project(":postssystem.features.roles.manager.client") api project(":postssystem.features.roles.manager.client")
api project(":postssystem.features.content.client")
api "dev.inmo:micro_utils.fsm.common:$microutils_version" api "dev.inmo:micro_utils.fsm.common:$microutils_version"
api "dev.inmo:micro_utils.fsm.repos.common:$microutils_version" api "dev.inmo:micro_utils.fsm.repos.common:$microutils_version"
api "dev.inmo:micro_utils.crypto:$microutils_version" api "dev.inmo:micro_utils.crypto:$microutils_version"

View File

@ -24,13 +24,19 @@ import dev.inmo.postssystem.client.settings.DefaultSettings
import dev.inmo.postssystem.client.settings.Settings import dev.inmo.postssystem.client.settings.Settings
import dev.inmo.postssystem.client.settings.auth.AuthSettings import dev.inmo.postssystem.client.settings.auth.AuthSettings
import dev.inmo.postssystem.client.settings.auth.DefaultAuthSettings import dev.inmo.postssystem.client.settings.auth.DefaultAuthSettings
import dev.inmo.postssystem.features.common.common.SerializersModuleConfigurator
import dev.inmo.postssystem.features.common.common.singleWithRandomQualifier
import dev.inmo.postssystem.features.content.common.ContentSerializersModuleConfigurator
import dev.inmo.postssystem.features.content.common.OtherContentSerializerModuleConfigurator
import dev.inmo.postssystem.features.status.client.StatusFeatureClient import dev.inmo.postssystem.features.status.client.StatusFeatureClient
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.serialization.BinaryFormat import kotlinx.serialization.BinaryFormat
import kotlinx.serialization.StringFormat import kotlinx.serialization.StringFormat
import kotlinx.serialization.cbor.Cbor
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule
import org.koin.core.Koin import org.koin.core.Koin
import org.koin.core.context.startKoin import org.koin.core.context.startKoin
import org.koin.core.module.Module import org.koin.core.module.Module
@ -41,7 +47,6 @@ import org.koin.dsl.module
val UIScopeQualifier = StringQualifier("CoroutineScopeUI") val UIScopeQualifier = StringQualifier("CoroutineScopeUI")
val SettingsQualifier = StringQualifier("Settings") val SettingsQualifier = StringQualifier("Settings")
val UserRolesQualifier = StringQualifier("UserRoles") val UserRolesQualifier = StringQualifier("UserRoles")
private val DBDropperQualifier = StringQualifier("DBDropper")
private val FSMHandlersBuilderQualifier = StringQualifier("FSMHandlersBuilder") private val FSMHandlersBuilderQualifier = StringQualifier("FSMHandlersBuilder")
val defaultSerialFormat = Json { val defaultSerialFormat = Json {
@ -61,7 +66,18 @@ fun baseKoin(
): Koin = startKoin { ): Koin = startKoin {
modules( modules(
module { module {
single<StringFormat> { defaultSerialFormat } singleWithRandomQualifier<ContentSerializersModuleConfigurator.Element> { OtherContentSerializerModuleConfigurator }
singleWithRandomQualifier<SerializersModuleConfigurator.Element> { ContentSerializersModuleConfigurator(getAll()) }
single { SerializersModuleConfigurator(getAll()) }
single {
Json {
ignoreUnknownKeys = true
serializersModule = SerializersModule { get<SerializersModuleConfigurator>().apply { invoke() } }
}
}
single<StringFormat> { get<Json>() }
single(SettingsQualifier) { settingsFactory() } single(SettingsQualifier) { settingsFactory() }
single { DBDropper(get(SettingsQualifier)) } single { DBDropper(get(SettingsQualifier)) }
single(FSMHandlersBuilderQualifier) { handlersSetter } single(FSMHandlersBuilderQualifier) { handlersSetter }
@ -102,7 +118,11 @@ fun getAuthorizedFeaturesDIModule(
} }
single(credsQualifier) { initialAuthKey } single(credsQualifier) { initialAuthKey }
single(serverUrlQualifier) { serverUrl } single(serverUrlQualifier) { serverUrl }
single<BinaryFormat> { standardKtorSerialFormat } single<BinaryFormat> {
Cbor {
serializersModule = SerializersModule { get<SerializersModuleConfigurator>().apply { invoke() } }
}
}
single { UnifiedRequester(get(), get()) } single { UnifiedRequester(get(), get()) }
single { StatusFeatureClient(get(serverUrlQualifier), get()) } single { StatusFeatureClient(get(serverUrlQualifier), get()) }

View File

@ -5,9 +5,8 @@ import dev.inmo.postssystem.features.auth.server.tokens.AuthTokensService
import dev.inmo.postssystem.features.common.server.sessions.ApplicationAuthenticationConfigurator import dev.inmo.postssystem.features.common.server.sessions.ApplicationAuthenticationConfigurator
import dev.inmo.postssystem.features.users.common.User import dev.inmo.postssystem.features.users.common.User
import dev.inmo.micro_utils.coroutines.safely import dev.inmo.micro_utils.coroutines.safely
import dev.inmo.micro_utils.ktor.server.*
import dev.inmo.micro_utils.ktor.server.configurators.* import dev.inmo.micro_utils.ktor.server.configurators.*
import dev.inmo.micro_utils.ktor.server.unianswer
import dev.inmo.micro_utils.ktor.server.uniload
import io.ktor.application.* import io.ktor.application.*
import io.ktor.auth.* import io.ktor.auth.*
import io.ktor.http.HttpStatusCode import io.ktor.http.HttpStatusCode
@ -25,81 +24,84 @@ fun User.principal() = AuthUserPrincipal(this)
class AuthenticationRoutingConfigurator( class AuthenticationRoutingConfigurator(
private val authFeature: AuthFeature, private val authFeature: AuthFeature,
private val authTokensService: AuthTokensService private val authTokensService: AuthTokensService,
private val unifiedRouter: UnifiedRouter
) : ApplicationRoutingConfigurator.Element, ApplicationAuthenticationConfigurator.Element { ) : ApplicationRoutingConfigurator.Element, ApplicationAuthenticationConfigurator.Element {
override fun Route.invoke() { override fun Route.invoke() {
route(authRootPathPart) { unifiedRouter.apply {
post(authAuthPathPart) { route(authRootPathPart) {
safely( post(authAuthPathPart) {
{ safely(
// TODO:: add error info {
it.printStackTrace() // TODO:: add error info
call.respond( it.printStackTrace()
HttpStatusCode.InternalServerError, call.respond(
"Something went wrong" HttpStatusCode.InternalServerError,
) "Something went wrong"
} )
) { }
val creds = call.uniload(AuthCreds.serializer()) ) {
val creds = uniload(AuthCreds.serializer())
val tokenInfo = authFeature.auth(creds)
val tokenInfo = authFeature.auth(creds)
if (tokenInfo == null) {
if (call.response.status() == null) { if (tokenInfo == null) {
call.respond(HttpStatusCode.Forbidden) if (call.response.status() == null) {
call.respond(HttpStatusCode.Forbidden)
}
} else {
call.sessions.set(tokenSessionKey, tokenInfo.token)
unianswer(
AuthTokenInfo.serializer().nullable,
tokenInfo
)
} }
} else {
call.sessions.set(tokenSessionKey, tokenInfo.token)
call.unianswer(
AuthTokenInfo.serializer().nullable,
tokenInfo
)
} }
} }
} post(authRefreshPathPart) {
post(authRefreshPathPart) { safely(
safely( {
{ // TODO:: add error info
// TODO:: add error info call.respond(
call.respond( HttpStatusCode.InternalServerError,
HttpStatusCode.InternalServerError, "Something went wrong"
"Something went wrong" )
) }
} ) {
) { val refreshToken = uniload(RefreshToken.serializer())
val refreshToken = call.uniload(RefreshToken.serializer())
val tokenInfo = authFeature.refresh(refreshToken)
val tokenInfo = authFeature.refresh(refreshToken)
if (tokenInfo == null) {
if (tokenInfo == null) { if (call.response.status() == null) {
if (call.response.status() == null) { call.respond(HttpStatusCode.Forbidden)
call.respond(HttpStatusCode.Forbidden) }
} else {
call.sessions.set(tokenSessionKey, tokenInfo.token)
unianswer(
AuthTokenInfo.serializer().nullable,
tokenInfo
)
} }
} else {
call.sessions.set(tokenSessionKey, tokenInfo.token)
call.unianswer(
AuthTokenInfo.serializer().nullable,
tokenInfo
)
} }
} }
} post(authGetMePathPart) {
post(authGetMePathPart) { safely(
safely( {
{ // TODO:: add error info
// TODO:: add error info call.respond(
call.respond( HttpStatusCode.InternalServerError,
HttpStatusCode.InternalServerError, "Something went wrong"
"Something went wrong" )
}
) {
unianswer(
User.serializer().nullable,
authFeature.getMe(
uniload(AuthToken.serializer())
)
) )
} }
) {
call.unianswer(
User.serializer().nullable,
authFeature.getMe(
call.uniload(AuthToken.serializer())
)
)
} }
} }
} }

View File

@ -0,0 +1,16 @@
package dev.inmo.postssystem.features.common.common
import com.benasher44.uuid.uuid4
import org.koin.core.definition.Definition
import org.koin.core.instance.InstanceFactory
import org.koin.core.module.Module
import org.koin.core.qualifier.StringQualifier
/**
* Will be useful in case you need to declare some singles with one type several types, but need to separate them and do
* not care about how :)
*/
inline fun <reified T : Any> Module.singleWithRandomQualifier(
createdAtStart: Boolean = false,
noinline definition: Definition<T>
) = single(uuid4().toString(), createdAtStart, definition)

View File

@ -0,0 +1,11 @@
package dev.inmo.postssystem.features.common.common
import org.koin.core.definition.Definition
import org.koin.core.module.Module
import org.koin.core.qualifier.StringQualifier
inline fun <reified T : Any> Module.single(
qualifier: String,
createdAtStart: Boolean = false,
noinline definition: Definition<T>
) = single(StringQualifier(qualifier), createdAtStart, definition)

View File

@ -0,0 +1,14 @@
package dev.inmo.postssystem.features.common.common
import kotlinx.serialization.modules.SerializersModuleBuilder
class SerializersModuleConfigurator(
private val elements: List<Element>
) {
fun interface Element {
operator fun SerializersModuleBuilder.invoke()
}
operator fun SerializersModuleBuilder.invoke() {
elements.forEach { it.apply { invoke() } }
}
}

View File

@ -11,6 +11,6 @@ inline fun <reified T : Any> Module.singleWithBinds(
qualifier: Qualifier? = null, qualifier: Qualifier? = null,
createdAtStart: Boolean = false, createdAtStart: Boolean = false,
noinline definition: Definition<T> noinline definition: Definition<T>
): Pair<Module, InstanceFactory<*>> { ): Pair<Module, InstanceFactory<T>> {
return single(qualifier, createdAtStart, definition) binds (T::class.allSuperclasses.toTypedArray()) return single(qualifier, createdAtStart, definition)
} }

View File

@ -0,0 +1,18 @@
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library"
}
apply from: "$mppProjectWithSerializationPresetPath"
kotlin {
sourceSets {
commonMain {
dependencies {
api project(":postssystem.features.content.common")
api project(":postssystem.features.common.client")
}
}
}
}

View File

@ -0,0 +1 @@
<manifest package="dev.inmo.postssystem.features.content.client"/>

View File

@ -0,0 +1,17 @@
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library"
}
apply from: "$mppProjectWithSerializationPresetPath"
kotlin {
sourceSets {
commonMain {
dependencies {
api project(":postssystem.features.common.common")
}
}
}
}

View File

@ -0,0 +1,24 @@
package dev.inmo.postssystem.features.content.common
import kotlinx.serialization.Serializable
typealias ContentId = String
/**
* Content which is planned to be registered in database
*
* @see ContentSerializersModuleConfigurator.Element
* @see ContentSerializersModuleConfigurator
*/
interface Content
/**
* Content which is already registered in database. Using its [id] you can retrieve all known
* [dev.inmo.postssystem.core.post.RegisteredPost]s by using
* [dev.inmo.postssystem.core.post.repo.ReadPostsRepo.getPostsByContent]
*/
@Serializable
data class RegisteredContent(
val id: ContentId,
val content: Content
)

View File

@ -0,0 +1,18 @@
package dev.inmo.postssystem.features.content.common
import dev.inmo.postssystem.features.common.common.SerializersModuleConfigurator
import kotlinx.serialization.modules.*
class ContentSerializersModuleConfigurator(
private val subconfigurators: List<Element>
) : SerializersModuleConfigurator.Element {
fun interface Element {
operator fun PolymorphicModuleBuilder<Content>.invoke()
}
override fun SerializersModuleBuilder.invoke() {
polymorphic(Content::class) {
subconfigurators.forEach { it.apply { invoke() } }
}
}
}

View File

@ -0,0 +1,19 @@
package dev.inmo.postssystem.features.content.common
import kotlinx.serialization.Serializable
import kotlinx.serialization.modules.PolymorphicModuleBuilder
/**
* That is a content which in fact just a link to another content. It would be useful in case when user wish to reuse
* some content
*/
@Serializable
data class OtherContentLinkContent(
val otherId: ContentId
) : Content
object OtherContentSerializerModuleConfigurator : ContentSerializersModuleConfigurator.Element {
override fun PolymorphicModuleBuilder<Content>.invoke() {
subclass(OtherContentLinkContent::class, OtherContentLinkContent.serializer())
}
}

View File

@ -0,0 +1 @@
<manifest package="dev.inmo.postssystem.features.content.common"/>

View File

@ -0,0 +1,17 @@
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
}
apply from: "$mppJavaProjectPresetPath"
kotlin {
sourceSets {
commonMain {
dependencies {
api project(":postssystem.features.content.common")
api project(":postssystem.features.common.server")
}
}
}
}

View File

@ -14,9 +14,10 @@ import kotlinx.serialization.builtins.nullable
class FilesRoutingConfigurator( class FilesRoutingConfigurator(
private val filesStorage: FilesStorage, private val filesStorage: FilesStorage,
private val writeFilesStorage: WriteFilesStorage? private val writeFilesStorage: WriteFilesStorage?,
private val unifierRouter: UnifiedRouter
) : ApplicationRoutingConfigurator.Element { ) : ApplicationRoutingConfigurator.Element {
constructor(fullFilesStorage: FullFilesStorage) : this(fullFilesStorage, fullFilesStorage) constructor(fullFilesStorage: FullFilesStorage, unifierRouter: UnifiedRouter) : this(fullFilesStorage, fullFilesStorage, unifierRouter)
override fun Route.invoke() { override fun Route.invoke() {
authenticate { authenticate {
@ -25,7 +26,8 @@ class FilesRoutingConfigurator(
filesStorage, filesStorage,
MetaFileInfoStorageWrapper.serializer(), MetaFileInfoStorageWrapper.serializer(),
MetaFileInfoStorageWrapper.serializer().nullable, MetaFileInfoStorageWrapper.serializer().nullable,
FileId.serializer() FileId.serializer(),
unifierRouter
) )
writeFilesStorage ?.let { writeFilesStorage ?.let {
configureWriteStandardCrudRepoRoutes( configureWriteStandardCrudRepoRoutes(
@ -33,23 +35,27 @@ class FilesRoutingConfigurator(
FullFileInfoStorageWrapper.serializer(), FullFileInfoStorageWrapper.serializer(),
FullFileInfoStorageWrapper.serializer().nullable, FullFileInfoStorageWrapper.serializer().nullable,
FullFileInfo.serializer(), FullFileInfo.serializer(),
FileId.serializer() FileId.serializer(),
unifierRouter
) )
} }
post(filesGetFilesPathPart) {
call.respondBytes( unifierRouter.apply {
filesStorage.getBytes( post(filesGetFilesPathPart) {
call.uniload(FileId.serializer()) call.respondBytes(
filesStorage.getBytes(
uniload(FileId.serializer())
)
) )
) }
} get(filesGetFullFileInfoPathPart) {
get(filesGetFullFileInfoPathPart) { unianswer(
call.unianswer( FullFileInfoStorageWrapper.serializer().nullable,
FullFileInfoStorageWrapper.serializer().nullable, filesStorage.getFullFileInfo(
filesStorage.getFullFileInfo( decodeUrlQueryValueOrSendError(filesFileIdParameter, FileId.serializer()) ?: return@get
call.decodeUrlQueryValueOrSendError(filesFileIdParameter, FileId.serializer()) ?: return@get )
) )
) }
} }
} }
} }

View File

@ -1,5 +1,6 @@
package dev.inmo.postssystem.features.roles.manager.server package dev.inmo.postssystem.features.roles.manager.server
import dev.inmo.micro_utils.ktor.server.UnifiedRouter
import dev.inmo.postssystem.features.roles.common.UsersRolesStorage import dev.inmo.postssystem.features.roles.common.UsersRolesStorage
import dev.inmo.postssystem.features.roles.manager.common.RolesManagerRole import dev.inmo.postssystem.features.roles.manager.common.RolesManagerRole
import dev.inmo.postssystem.features.roles.manager.common.RolesManagerRoleSerializer import dev.inmo.postssystem.features.roles.manager.common.RolesManagerRoleSerializer
@ -7,9 +8,11 @@ import dev.inmo.postssystem.features.roles.server.UsersRolesStorageWriteServerRo
import dev.inmo.micro_utils.ktor.server.configurators.ApplicationRoutingConfigurator import dev.inmo.micro_utils.ktor.server.configurators.ApplicationRoutingConfigurator
class RolesManagerUsersRolesStorageServerRoutesConfigurator( class RolesManagerUsersRolesStorageServerRoutesConfigurator(
storage: UsersRolesStorage<RolesManagerRole> storage: UsersRolesStorage<RolesManagerRole>,
unifiedRouter: UnifiedRouter
) : ApplicationRoutingConfigurator.Element by UsersRolesStorageWriteServerRoutesConfigurator( ) : ApplicationRoutingConfigurator.Element by UsersRolesStorageWriteServerRoutesConfigurator(
storage, storage,
RolesManagerRoleSerializer, RolesManagerRoleSerializer,
RolesManagerRolesChecker.key RolesManagerRolesChecker.key,
unifiedRouter = unifiedRouter
) )

View File

@ -15,7 +15,7 @@ import io.ktor.response.respond
class UsersRolesAuthenticationConfigurator<T : UserRole>( class UsersRolesAuthenticationConfigurator<T : UserRole>(
private val usersRolesStorage: UsersRolesStorage<T>, private val usersRolesStorage: UsersRolesStorage<T>,
private val authTokensService: AuthTokensService, private val authTokensService: AuthTokensService,
private val rolesCheckers: List<RolesChecker<T>> private val rolesCheckers: List<RolesChecker<T>>,
) : ApplicationAuthenticationConfigurator.Element { ) : ApplicationAuthenticationConfigurator.Element {
override fun Authentication.Configuration.invoke() { override fun Authentication.Configuration.invoke() {
rolesCheckers.forEach { checker -> rolesCheckers.forEach { checker ->

View File

@ -13,59 +13,61 @@ import kotlinx.serialization.builtins.serializer
class UsersRolesStorageReadServerRoutesConfigurator<T : UserRole>( class UsersRolesStorageReadServerRoutesConfigurator<T : UserRole>(
private val storage: ReadUsersRolesStorage<T>, private val storage: ReadUsersRolesStorage<T>,
private val serializer: KSerializer<T> private val serializer: KSerializer<T>,
private val unifiedRouter: UnifiedRouter
) : ApplicationRoutingConfigurator.Element { ) : ApplicationRoutingConfigurator.Element {
private val userRolesSerializer = ListSerializer(serializer) private val userRolesSerializer = ListSerializer(serializer)
override fun Route.invoke() { override fun Route.invoke() {
authenticate { unifiedRouter.apply {
route(usersRolesRootPathPart) { authenticate {
get(usersRolesGetUsersPathPart) { route(usersRolesRootPathPart) {
val userRole = call.decodeUrlQueryValueOrSendError(usersRolesUserRoleQueryParameterName, serializer) get(usersRolesGetUsersPathPart) {
?: return@get val userRole = decodeUrlQueryValueOrSendError(usersRolesUserRoleQueryParameterName, serializer)
call.unianswer(
UsersIdsSerializer,
storage.getUsers(userRole)
)
}
get(usersRolesGetRolesPathPart) {
val userId =
call.decodeUrlQueryValueOrSendError(usersRolesUserIdQueryParameterName, UserId.serializer())
?: return@get ?: return@get
call.unianswer( unianswer(
userRolesSerializer, UsersIdsSerializer,
storage.getRoles(userId) storage.getUsers(userRole)
) )
} }
get(usersRolesContainsPathPart) { get(usersRolesGetRolesPathPart) {
val userId = call.decodeUrlQueryValueOrSendError( val userId = decodeUrlQueryValueOrSendError(usersRolesUserIdQueryParameterName, UserId.serializer())
usersRolesUserIdQueryParameterName, ?: return@get
UserId.serializer() unianswer(
) ?: return@get userRolesSerializer,
val userRole = call.decodeUrlQueryValueOrSendError( storage.getRoles(userId)
usersRolesUserRoleQueryParameterName, )
serializer }
) ?: return@get
call.unianswer(
Boolean.serializer(),
storage.contains(userId, userRole)
)
}
get(usersRolesContainsAnyPathPart) { get(usersRolesContainsPathPart) {
val userId = call.decodeUrlQueryValueOrSendError( val userId = decodeUrlQueryValueOrSendError(
usersRolesUserIdQueryParameterName, usersRolesUserIdQueryParameterName,
UserId.serializer() UserId.serializer()
) ?: return@get ) ?: return@get
val userRoles = call.decodeUrlQueryValueOrSendError( val userRole = decodeUrlQueryValueOrSendError(
usersRolesUserRoleQueryParameterName, usersRolesUserRoleQueryParameterName,
userRolesSerializer serializer
) ?: return@get ) ?: return@get
call.unianswer( unianswer(
Boolean.serializer(), Boolean.serializer(),
storage.containsAny(userId, userRoles) storage.contains(userId, userRole)
) )
}
get(usersRolesContainsAnyPathPart) {
val userId = decodeUrlQueryValueOrSendError(
usersRolesUserIdQueryParameterName,
UserId.serializer()
) ?: return@get
val userRoles = decodeUrlQueryValueOrSendError(
usersRolesUserRoleQueryParameterName,
userRolesSerializer
) ?: return@get
unianswer(
Boolean.serializer(),
storage.containsAny(userId, userRoles)
)
}
} }
} }
} }

View File

@ -13,37 +13,40 @@ class UsersRolesStorageWriteServerRoutesConfigurator<T : UserRole>(
private val storage: WriteUsersRolesStorage<T>, private val storage: WriteUsersRolesStorage<T>,
private val serializer: KSerializer<T>, private val serializer: KSerializer<T>,
private val includeAuthKey: String, private val includeAuthKey: String,
private val excludeAuthKey: String = includeAuthKey private val excludeAuthKey: String = includeAuthKey,
private val unifiedRouter: UnifiedRouter
) : ApplicationRoutingConfigurator.Element { ) : ApplicationRoutingConfigurator.Element {
override fun Route.invoke() { override fun Route.invoke() {
route(usersRolesRootPathPart) { unifiedRouter.apply {
val wrapperSerializer = UserRolesStorageIncludeExcludeWrapper.serializer( route(usersRolesRootPathPart) {
serializer val wrapperSerializer = UserRolesStorageIncludeExcludeWrapper.serializer(
) serializer
authenticate(includeAuthKey) { )
post(usersRolesIncludePathPart) { authenticate(includeAuthKey) {
val wrapper = call.uniload(wrapperSerializer) post(usersRolesIncludePathPart) {
val wrapper = uniload(wrapperSerializer)
call.unianswer( unianswer(
Boolean.serializer(), Boolean.serializer(),
storage.include( storage.include(
wrapper.userId, wrapper.userId,
wrapper.userRole wrapper.userRole
)
) )
) }
} }
} authenticate(excludeAuthKey) {
authenticate(excludeAuthKey) { post(usersRolesExcludePathPart) {
post(usersRolesExcludePathPart) { val wrapper = uniload(wrapperSerializer)
val wrapper = call.uniload(wrapperSerializer)
call.unianswer( unianswer(
Boolean.serializer(), Boolean.serializer(),
storage.exclude( storage.exclude(
wrapper.userId, wrapper.userId,
wrapper.userRole wrapper.userRole
)
) )
) }
} }
} }
} }

View File

@ -1,5 +1,6 @@
package dev.inmo.postssystem.features.users.server package dev.inmo.postssystem.features.users.server
import dev.inmo.micro_utils.ktor.server.UnifiedRouter
import dev.inmo.postssystem.features.users.common.* import dev.inmo.postssystem.features.users.common.*
import dev.inmo.micro_utils.ktor.server.configurators.ApplicationRoutingConfigurator import dev.inmo.micro_utils.ktor.server.configurators.ApplicationRoutingConfigurator
import dev.inmo.micro_utils.repos.ktor.server.crud.configureReadStandardCrudRepoRoutes import dev.inmo.micro_utils.repos.ktor.server.crud.configureReadStandardCrudRepoRoutes
@ -9,7 +10,8 @@ import io.ktor.routing.route
import kotlinx.serialization.builtins.nullable import kotlinx.serialization.builtins.nullable
class UsersStorageServerRoutesConfigurator( class UsersStorageServerRoutesConfigurator(
private val usersStorage: ReadUsersStorage private val usersStorage: ReadUsersStorage,
private val unifiedRouter: UnifiedRouter
) : ApplicationRoutingConfigurator.Element { ) : ApplicationRoutingConfigurator.Element {
override fun Route.invoke() { override fun Route.invoke() {
authenticate { authenticate {
@ -18,7 +20,8 @@ class UsersStorageServerRoutesConfigurator(
usersStorage, usersStorage,
User.serializer(), User.serializer(),
User.serializer().nullable, User.serializer().nullable,
UserId.serializer() UserId.serializer(),
unifiedRouter
) )
} }
} }

View File

@ -18,6 +18,7 @@ dependencies {
api project(":postssystem.features.auth.server") api project(":postssystem.features.auth.server")
api project(":postssystem.features.roles.server") api project(":postssystem.features.roles.server")
api project(":postssystem.features.roles.manager.server") api project(":postssystem.features.roles.manager.server")
api project(":postssystem.features.content.server")
api "io.ktor:ktor-server-netty:$ktor_version" api "io.ktor:ktor-server-netty:$ktor_version"
api "io.ktor:ktor-websockets:$ktor_version" api "io.ktor:ktor-websockets:$ktor_version"
api "org.jetbrains.exposed:exposed-jdbc:$kotlin_exposed_version" api "org.jetbrains.exposed:exposed-jdbc:$kotlin_exposed_version"

View File

@ -3,8 +3,6 @@ package dev.inmo.postssystem.server
import dev.inmo.postssystem.features.auth.server.AuthenticationRoutingConfigurator import dev.inmo.postssystem.features.auth.server.AuthenticationRoutingConfigurator
import dev.inmo.postssystem.features.auth.server.SessionAuthenticationConfigurator import dev.inmo.postssystem.features.auth.server.SessionAuthenticationConfigurator
import dev.inmo.postssystem.features.auth.server.tokens.* import dev.inmo.postssystem.features.auth.server.tokens.*
import dev.inmo.postssystem.features.common.common.getAllDistinct
import dev.inmo.postssystem.features.common.common.singleWithBinds
import dev.inmo.postssystem.features.common.server.sessions.ApplicationAuthenticationConfigurator import dev.inmo.postssystem.features.common.server.sessions.ApplicationAuthenticationConfigurator
import dev.inmo.postssystem.features.files.common.* import dev.inmo.postssystem.features.files.common.*
import dev.inmo.postssystem.features.files.common.storage.* import dev.inmo.postssystem.features.files.common.storage.*
@ -21,10 +19,15 @@ import dev.inmo.postssystem.features.status.server.StatusRoutingConfigurator
import dev.inmo.postssystem.features.users.common.ExposedUsersStorage import dev.inmo.postssystem.features.users.common.ExposedUsersStorage
import dev.inmo.postssystem.features.users.server.UsersStorageServerRoutesConfigurator import dev.inmo.postssystem.features.users.server.UsersStorageServerRoutesConfigurator
import dev.inmo.micro_utils.coroutines.LinkedSupervisorScope import dev.inmo.micro_utils.coroutines.LinkedSupervisorScope
import dev.inmo.micro_utils.ktor.common.standardKtorSerialFormat
import dev.inmo.micro_utils.ktor.server.UnifiedRouter
import dev.inmo.micro_utils.ktor.server.configurators.* import dev.inmo.micro_utils.ktor.server.configurators.*
import dev.inmo.micro_utils.ktor.server.createKtorServer import dev.inmo.micro_utils.ktor.server.createKtorServer
import dev.inmo.micro_utils.repos.exposed.keyvalue.ExposedKeyValueRepo import dev.inmo.micro_utils.repos.exposed.keyvalue.ExposedKeyValueRepo
import dev.inmo.micro_utils.repos.exposed.onetomany.ExposedOneToManyKeyValueRepo import dev.inmo.micro_utils.repos.exposed.onetomany.ExposedOneToManyKeyValueRepo
import dev.inmo.postssystem.features.common.common.*
import dev.inmo.postssystem.features.content.common.ContentSerializersModuleConfigurator
import dev.inmo.postssystem.features.content.common.OtherContentSerializerModuleConfigurator
import io.ktor.application.featureOrNull import io.ktor.application.featureOrNull
import io.ktor.application.log import io.ktor.application.log
import io.ktor.routing.Route import io.ktor.routing.Route
@ -33,8 +36,11 @@ import io.ktor.server.engine.ApplicationEngine
import io.ktor.server.netty.Netty import io.ktor.server.netty.Netty
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.serialization.BinaryFormat
import kotlinx.serialization.StringFormat import kotlinx.serialization.StringFormat
import kotlinx.serialization.cbor.Cbor
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule
import org.jetbrains.exposed.sql.Database import org.jetbrains.exposed.sql.Database
import org.koin.core.module.Module import org.koin.core.module.Module
import org.koin.core.parameter.ParametersHolder import org.koin.core.parameter.ParametersHolder
@ -54,21 +60,36 @@ fun getDIModule(
vararg args: String, vararg args: String,
baseScope: CoroutineScope = CoroutineScope(Dispatchers.IO) baseScope: CoroutineScope = CoroutineScope(Dispatchers.IO)
): Module { ): Module {
val json = Json { val configJson = Json {
ignoreUnknownKeys = true ignoreUnknownKeys = true
} }
val config = json.decodeFromString(Config.serializer(), File(args.first()).readText()) val config = configJson.decodeFromString(Config.serializer(), File(args.first()).readText())
val originalFilesMetasKeyValueRepoQualifier = StringQualifier("OriginalFilesMetaKV") val originalFilesMetasKeyValueRepoQualifier = StringQualifier("OriginalFilesMetaKV")
val filesMetasKeyValueRepoQualifier = StringQualifier("FilesMetaKV") val filesMetasKeyValueRepoQualifier = StringQualifier("FilesMetaKV")
val filesFolderQualifier = StringQualifier("filesFolder") val filesFolderQualifier = StringQualifier("filesFolder")
val reviewVersionsQualifier = StringQualifier("reviewVersions")
val releaseVersionsQualifier = StringQualifier("releaseVersions")
val usersRolesKeyValueFactoryQualifier = StringQualifier("usersRolesKeyValueFactory") val usersRolesKeyValueFactoryQualifier = StringQualifier("usersRolesKeyValueFactory")
return module { return module {
single { json } singleWithRandomQualifier<ContentSerializersModuleConfigurator.Element> { OtherContentSerializerModuleConfigurator }
singleWithRandomQualifier<SerializersModuleConfigurator.Element> { ContentSerializersModuleConfigurator(getAll()) }
single { SerializersModuleConfigurator(getAll()) }
single {
Json {
ignoreUnknownKeys = true
serializersModule = SerializersModule { get<SerializersModuleConfigurator>().apply { invoke() } }
}
}
single<StringFormat> { get<Json>() } single<StringFormat> { get<Json>() }
single<BinaryFormat> {
Cbor {
serializersModule = SerializersModule { get<SerializersModuleConfigurator>().apply { invoke() } }
}
}
single { UnifiedRouter(get()) }
singleWithBinds { config } singleWithBinds { config }
singleWithBinds { get<Config>().databaseConfig } singleWithBinds { get<Config>().databaseConfig }
singleWithBinds { get<Config>().authConfig } singleWithBinds { get<Config>().authConfig }
@ -111,11 +132,11 @@ fun getDIModule(
factory<CoroutineScope> { baseScope.LinkedSupervisorScope() } factory<CoroutineScope> { baseScope.LinkedSupervisorScope() }
// Routing configurators // Routing configurators
singleWithBinds { FilesRoutingConfigurator(get(), null) } singleWithBinds { FilesRoutingConfigurator(get(), null, get()) }
singleWithBinds { StatusRoutingConfigurator } singleWithBinds { StatusRoutingConfigurator }
singleWithBinds { UsersStorageServerRoutesConfigurator(get()) } singleWithBinds { UsersStorageServerRoutesConfigurator(get(), get()) }
singleWithBinds { UsersRolesStorageReadServerRoutesConfigurator<UserRole>(get(), UserRoleSerializer) } singleWithBinds { UsersRolesStorageReadServerRoutesConfigurator<UserRole>(get(), UserRoleSerializer, get()) }
singleWithBinds { RolesManagerUsersRolesStorageServerRoutesConfigurator(get()) } singleWithBinds { RolesManagerUsersRolesStorageServerRoutesConfigurator(get(), get()) }
singleWithBinds { ClientStaticRoutingConfiguration(get<Config>().clientStatic) } singleWithBinds { ClientStaticRoutingConfiguration(get<Config>().clientStatic) }
singleWithBinds { singleWithBinds {
@ -137,7 +158,7 @@ fun getDIModule(
get() get()
) )
} }
singleWithBinds { AuthenticationRoutingConfigurator(get(), get()) } singleWithBinds { AuthenticationRoutingConfigurator(get(), get(), get()) }
if (config.debugMode) { if (config.debugMode) {
single<ApplicationRoutingConfigurator.Element>(StringQualifier("Tracer")) { ApplicationRoutingConfigurator.Element {(this as Routing).trace { application.log.trace(it.buildText()) } } } single<ApplicationRoutingConfigurator.Element>(StringQualifier("Tracer")) { ApplicationRoutingConfigurator.Element {(this as Routing).trace { application.log.trace(it.buildText()) } } }

View File

@ -29,6 +29,10 @@ String[] includes = [
":features:auth:client", ":features:auth:client",
":features:auth:server", ":features:auth:server",
":features:content:common",
":features:content:client",
":features:content:server",
":server", ":server",
":client", ":client",
] ]