add content
This commit is contained in:
parent
fffe99adaa
commit
58b7e973be
@ -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"
|
||||||
|
@ -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()) }
|
||||||
|
@ -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())
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
@ -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)
|
@ -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() } }
|
||||||
|
}
|
||||||
|
}
|
@ -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)
|
||||||
}
|
}
|
||||||
|
18
features/content/client/build.gradle
Normal file
18
features/content/client/build.gradle
Normal 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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
features/content/client/src/main/AndroidManifest.xml
Normal file
1
features/content/client/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1 @@
|
|||||||
|
<manifest package="dev.inmo.postssystem.features.content.client"/>
|
17
features/content/common/build.gradle
Normal file
17
features/content/common/build.gradle
Normal 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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
)
|
@ -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() } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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())
|
||||||
|
}
|
||||||
|
}
|
1
features/content/common/src/main/AndroidManifest.xml
Normal file
1
features/content/common/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1 @@
|
|||||||
|
<manifest package="dev.inmo.postssystem.features.content.common"/>
|
17
features/content/server/build.gradle
Normal file
17
features/content/server/build.gradle
Normal 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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
)
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
)
|
)
|
||||||
|
@ -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 ->
|
||||||
|
@ -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)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
|
@ -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()) } } }
|
||||||
|
@ -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",
|
||||||
]
|
]
|
||||||
|
Loading…
Reference in New Issue
Block a user