start migration onto ktor-based serialization of data

This commit is contained in:
2022-06-12 18:54:28 +06:00
parent 399405a4fb
commit ff973e63fc
19 changed files with 201 additions and 257 deletions
features
auth
server
src
jvmMain
kotlin
dev
inmo
postssystem
content
common
src
commonMain
kotlin
dev
inmo
postssystem
features
content
files
client
src
commonMain
kotlin
dev
inmo
postssystem
features
server
src
jvmMain
kotlin
dev
inmo
postssystem
features
roles
client
common
src
commonMain
kotlin
dev
inmo
postssystem
features
roles
common
manager
server
src
jvmMain
kotlin
dev
inmo
server
users
client
src
commonMain
kotlin
dev
inmo
postssystem
features
server
src
jvmMain
kotlin
dev
inmo
postssystem
publicators/simple/client/src/commonMain/kotlin/dev/inmo/postssystem/publicators/simple/client
server/src/main/java/dev/inmo/postssystem/server
services/posts
client
src
commonMain
server
src
jvmMain
kotlin
dev
inmo
postssystem

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

@ -1,7 +1,6 @@
package dev.inmo.postssystem.features.content.common
import dev.inmo.micro_utils.common.FileName
import dev.inmo.micro_utils.common.MPPFile
import dev.inmo.micro_utils.common.*
import dev.inmo.micro_utils.mime_types.MimeType
import dev.inmo.postssystem.features.common.common.SimpleInputProvider
import kotlinx.serialization.PolymorphicSerializer
@ -30,6 +29,18 @@ data class BinaryContent(
) : Content
val ContentSerializer = PolymorphicSerializer(Content::class)
@Serializable
data class ContentWrapper(
val content: Content
)
@Serializable
data class ContentsWrapper(
val content: List<Content>
)
@Serializable
data class ContentsEithersWrapper(
val content: List<Either<ContentId, Content>>
)
/**
* Content which is already registered in database. Using its [id] you can retrieve all known

@ -25,7 +25,6 @@ class ClientReadFilesStorage(
MetaFileInfoStorageWrapper.serializer().nullable,
FileId.serializer()
) {
private val unifiedRequester = UnifiedRequester(client, serialFormat)
private val fullFilesPath = buildStandardUrl(baseUrl, filesRootPathPart)
private val fullFilesGetBytesPath = buildStandardUrl(
fullFilesPath,

@ -4,10 +4,13 @@ import dev.inmo.postssystem.features.files.common.*
import dev.inmo.postssystem.features.files.common.storage.*
import dev.inmo.micro_utils.ktor.server.*
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.configureWriteStandardCrudRepoRoutes
import dev.inmo.micro_utils.repos.ktor.server.crud.*
import io.ktor.http.HttpStatusCode
import io.ktor.http.decodeURLQueryComponent
import io.ktor.server.application.call
import io.ktor.server.auth.authenticate
import io.ktor.server.request.receive
import io.ktor.server.response.respond
import io.ktor.server.response.respondBytes
import io.ktor.server.routing.*
import kotlinx.serialization.builtins.nullable
@ -15,47 +18,33 @@ import kotlinx.serialization.builtins.nullable
class FilesRoutingConfigurator(
private val filesStorage: ReadFilesStorage,
private val writeFilesStorage: WriteFilesStorage?,
private val unifierRouter: UnifiedRouter
) : ApplicationRoutingConfigurator.Element {
constructor(filesStorage: FilesStorage, unifierRouter: UnifiedRouter) : this(filesStorage, filesStorage, unifierRouter)
constructor(filesStorage: FilesStorage) : this(filesStorage, filesStorage)
override fun Route.invoke() {
authenticate {
route(filesRootPathPart) {
configureReadStandardCrudRepoRoutes(
configureReadCRUDRepoRoutes(
filesStorage,
MetaFileInfoStorageWrapper.serializer(),
MetaFileInfoStorageWrapper.serializer().nullable,
FileId.serializer(),
unifierRouter
::FileId
)
writeFilesStorage ?.let {
configureWriteStandardCrudRepoRoutes(
writeFilesStorage,
FullFileInfoStorageWrapper.serializer(),
FullFileInfoStorageWrapper.serializer().nullable,
FullFileInfo.serializer(),
FileId.serializer(),
unifierRouter
)
configureWriteCRUDRepoRoutes(writeFilesStorage)
}
unifierRouter.apply {
post(filesGetFilesPathPart) {
call.respondBytes(
filesStorage.getBytes(
uniload(FileId.serializer())
)
post(filesGetFilesPathPart) {
call.respondBytes(
filesStorage.getBytes(
call.receive()
)
}
get(filesGetFullFileInfoPathPart) {
unianswer(
FullFileInfoStorageWrapper.serializer().nullable,
filesStorage.getFullFileInfo(
decodeUrlQueryValueOrSendError(filesFileIdParameter, FileId.serializer()) ?: return@get
)
)
}
)
}
get(filesGetFullFileInfoPathPart) {
call.respond(
filesStorage.getFullFileInfo(
FileId(call.getParameterOrSendError(filesFileIdParameter) ?.decodeURLQueryComponent() ?: return@get)
) ?: HttpStatusCode.NoContent
)
}
}
}

@ -6,12 +6,12 @@ import kotlinx.serialization.KSerializer
class ClientRolesStorage<T : Role>(
private val baseUrl: String,
private val unifiedRequester: UnifiedRequester,
private val client: HttpClient,
private val serializer: KSerializer<T>
) : RolesStorage<T>,
ReadRolesStorage<T> by ReadClientRolesStorage(
baseUrl, unifiedRequester, serializer
baseUrl, client, serializer
),
WriteRolesStorage<T> by WriteClientRolesStorage(
baseUrl, unifiedRequester, serializer
baseUrl, client, serializer
)

@ -3,13 +3,15 @@ package dev.inmo.postssystem.features.roles.client
import dev.inmo.postssystem.features.roles.common.*
import dev.inmo.micro_utils.ktor.client.UnifiedRequester
import dev.inmo.micro_utils.ktor.common.buildStandardUrl
import io.ktor.client.HttpClient
import io.ktor.client.request.get
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.builtins.serializer
class ReadClientRolesStorage<T : Role>(
private val baseUrl: String,
private val unifiedRequester: UnifiedRequester,
private val client: HttpClient,
private val serializer: KSerializer<T>
) : ReadRolesStorage<T> {
private val userRolesSerializer = ListSerializer(serializer)
@ -21,14 +23,13 @@ class ReadClientRolesStorage<T : Role>(
override suspend fun getSubjects(
role: T
): List<RoleSubject> = unifiedRequester.uniget(
): List<RoleSubject> = client.get(
buildStandardUrl(
userRolesFullUrl,
usersRolesGetSubjectsPathPart,
usersRolesRoleQueryParameterName to unifiedRequester.encodeUrlQueryValue(serializer, role)
),
RoleSubjectsSerializer
)
)
).body()
override suspend fun getRoles(
subject: RoleSubject

@ -8,7 +8,7 @@ import kotlinx.serialization.builtins.serializer
class WriteClientRolesStorage<T : Role>(
private val baseUrl: String,
private val unifiedRequester: UnifiedRequester,
private val client: HttpClient,
private val serializer: KSerializer<T>
) : WriteRolesStorage<T> {
private val wrapperSerializer = RolesStorageIncludeExcludeWrapper.serializer(

@ -6,7 +6,7 @@ import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.*
import kotlinx.serialization.json.*
@Serializable(RoleSerializer::class)
@Polymorphic
interface Role {
companion object {
fun serializer(): KSerializer<Role> = RoleSerializer

@ -1,17 +1,14 @@
package dev.inmo.postssystem.features.roles.manager.server
import dev.inmo.micro_utils.ktor.server.UnifiedRouter
import dev.inmo.postssystem.features.roles.common.RolesStorage
import dev.inmo.postssystem.features.roles.manager.common.RolesManagerRole
import dev.inmo.postssystem.features.roles.server.RolesStorageWriteServerRoutesConfigurator
import dev.inmo.micro_utils.ktor.server.configurators.ApplicationRoutingConfigurator
class RolesManagerRolesStorageServerRoutesConfigurator(
storage: RolesStorage<RolesManagerRole>,
unifiedRouter: UnifiedRouter
storage: RolesStorage<RolesManagerRole>
) : ApplicationRoutingConfigurator.Element by RolesStorageWriteServerRoutesConfigurator(
storage,
RolesManagerRole.serializer(),
RolesManagerRolesChecker.key,
unifiedRouter = unifiedRouter
RolesManagerRolesChecker.key
)

@ -12,8 +12,7 @@ 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
private val excludeAuthKey: String = includeAuthKey
) : ApplicationRoutingConfigurator.Element {
override fun Route.invoke() {
route(usersRolesRootPathPart) {

@ -11,8 +11,7 @@ import kotlinx.serialization.builtins.serializer
class RolesStorageReadServerRoutesConfigurator<T : Role>(
private val storage: ReadRolesStorage<T>,
private val serializer: KSerializer<T>,
private val unifiedRouter: UnifiedRouter
private val serializer: KSerializer<T>
) : ApplicationRoutingConfigurator.Element {
private val userRolesSerializer = ListSerializer(serializer)
override fun Route.invoke() {

@ -9,10 +9,10 @@ import kotlinx.serialization.builtins.nullable
class UsersStorageKtorClient(
baseUrl: String,
unifiedRequester: UnifiedRequester
client: HttpClient
) : ReadUsersStorage, ReadCRUDRepo<User, UserId> by KtorReadStandardCrudRepo(
buildStandardUrl(baseUrl, usersServerPathPart),
unifiedRequester,
client,
User.serializer(),
User.serializer().nullable,
UserId.serializer()

@ -1,28 +1,21 @@
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.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.configureReadCRUDRepoRoutes
import io.ktor.server.auth.authenticate
import io.ktor.server.routing.Route
import io.ktor.server.routing.route
import kotlinx.serialization.builtins.nullable
class UsersStorageServerRoutesConfigurator(
private val usersStorage: ReadUsersStorage,
private val unifiedRouter: UnifiedRouter
private val usersStorage: ReadUsersStorage
) : ApplicationRoutingConfigurator.Element {
override fun Route.invoke() {
authenticate {
route(usersServerPathPart) {
configureReadStandardCrudRepoRoutes(
usersStorage,
User.serializer(),
User.serializer().nullable,
UserId.serializer(),
unifiedRouter
)
configureReadCRUDRepoRoutes(
usersStorage
) { UserId(it.toLong()) }
}
}
}

@ -10,7 +10,7 @@ import kotlinx.serialization.builtins.serializer
class SimplePublicatorServiceClient(
baseUrl: String,
private val unifiedRequester: UnifiedRequester
private val client: HttpClient
) : SimplePublicatorService {
private val fullUrl = buildStandardUrl(
baseUrl,

@ -18,11 +18,10 @@ import dev.inmo.postssystem.features.status.server.StatusRoutingConfigurator
import dev.inmo.postssystem.features.users.common.ExposedUsersStorage
import dev.inmo.postssystem.features.users.server.UsersStorageServerRoutesConfigurator
import dev.inmo.micro_utils.coroutines.LinkedSupervisorScope
import dev.inmo.micro_utils.ktor.server.UnifiedRouter
import dev.inmo.micro_utils.ktor.server.configurators.*
import dev.inmo.micro_utils.ktor.server.createKtorServer
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.ExposedKeyValuesRepo
import dev.inmo.postssystem.features.common.common.*
import dev.inmo.postssystem.features.common.server.Qualifiers
import dev.inmo.postssystem.features.content.common.*
@ -88,8 +87,6 @@ fun getDIModule(
}
}
single { UnifiedRouter(get()) }
singleWithBinds { config }
singleWithBinds { get<Config>().databaseConfig }
singleWithBinds { get<Config>().authConfig }
@ -101,7 +98,7 @@ fun getDIModule(
singleWithBinds { exposedUsersAuthenticator(get(), get()) }
factory<KeyValuesRolesOriginalRepo>(Qualifiers.usersRolesKeyValueFactoryQualifier) { (tableName: String) ->
ExposedOneToManyKeyValueRepo(get(), { text("subject") }, { text("role") }, tableName)
ExposedKeyValuesRepo(get(), { text("subject") }, { text("role") }, tableName)
}
single {
RolesManagerRoleStorage(get(Qualifiers.usersRolesKeyValueFactoryQualifier) { ParametersHolder(mutableListOf("rolesManager")) })
@ -154,12 +151,12 @@ fun getDIModule(
}
// Routing configurators
singleWithBinds { FilesRoutingConfigurator(get(), null, get()) }
singleWithBinds { FilesRoutingConfigurator(get(), null) }
singleWithBinds { StatusRoutingConfigurator }
singleWithBinds { UsersStorageServerRoutesConfigurator(get(), get()) }
singleWithBinds { RolesStorageReadServerRoutesConfigurator<Role>(get(), RoleSerializer, get()) }
singleWithBinds { RolesManagerRolesStorageServerRoutesConfigurator(get(), get()) }
singleWithBinds { ServerPostsServiceRoutingConfigurator(get(), get(), get(), get()) }
singleWithBinds { UsersStorageServerRoutesConfigurator(get()) }
singleWithBinds { RolesStorageReadServerRoutesConfigurator<Role>(get(), RoleSerializer) }
singleWithBinds { RolesManagerRolesStorageServerRoutesConfigurator(get()) }
singleWithBinds { ServerPostsServiceRoutingConfigurator(get(), get(), get()) }
singleWithBinds { ClientStaticRoutingConfiguration("web") }
singleWithBinds {
@ -181,7 +178,7 @@ fun getDIModule(
get()
)
}
singleWithBinds { AuthenticationRoutingConfigurator(get(), get(), get()) }
singleWithBinds { AuthenticationRoutingConfigurator(get(), get()) }
singleWithBinds { NotFoundStatusPageRedirectToIndex("/") }
if (config.debugMode) {

@ -5,7 +5,7 @@ import dev.inmo.postssystem.services.posts.common.*
class ClientPostsService(
baseUrl: String,
unifiedRequester: UnifiedRequester
client: HttpClient
) : PostsService,
ReadPostsService by ClientReadPostsService(baseUrl, unifiedRequester),
WritePostsService by ClientWritePostsService(baseUrl, unifiedRequester)
ReadPostsService by ClientReadPostsService(baseUrl, client),
WritePostsService by ClientWritePostsService(baseUrl, client)

@ -12,10 +12,10 @@ import kotlinx.serialization.builtins.nullable
class ClientReadPostsService(
private val baseUrl: String,
private val unifiedRequester: UnifiedRequester
private val client: HttpClient
) : ReadPostsService, ReadCRUDRepo<RegisteredPost, PostId> by KtorReadStandardCrudRepo(
buildStandardUrl(baseUrl, postsRootPath),
unifiedRequester,
client,
RegisteredPost.serializer(),
RegisteredPost.serializer().nullable,
PostId.serializer()

@ -25,17 +25,17 @@ import kotlinx.serialization.modules.polymorphic
class ClientWritePostsService(
private val baseUrl: String,
unifiedRequester: UnifiedRequester
client: HttpClient
) : WritePostsService {
private val root = buildStandardUrl(baseUrl, postsRootPath)
private val unifiedRequester = UnifiedRequester(
unifiedRequester.client,
unifiedRequester.serialFormat.createWithSerializerModuleExtension {
polymorphic(Content::class) {
subclass(BinaryContent::class, BinaryContentSerializer(TempFileIdentifierInputProvider::class, TempFileIdentifierInputProvider.serializer()))
}
}
)
// private val unifiedRequester = UnifiedRequester(
// unifiedRequester.client,
// unifiedRequester.serialFormat.createWithSerializerModuleExtension {
// polymorphic(Content::class) {
// subclass(BinaryContent::class, BinaryContentSerializer(TempFileIdentifierInputProvider::class, TempFileIdentifierInputProvider.serializer()))
// }
// }
// )
private val contentEitherSerializer = EitherSerializer(ContentId.serializer(), ContentSerializer)
private val contentsEitherSerializer = ListSerializer(contentEitherSerializer)
@ -58,7 +58,7 @@ class ClientWritePostsService(
return (content as? BinaryContent) ?.let {
when (val provider = it.inputProvider) {
is FileBasedInputProvider -> {
val fileId = unifiedRequester.tempUpload(
val fileId = client.tempUpload(
tempUploadFullPath,
provider.file
)

@ -10,7 +10,7 @@ import dev.inmo.micro_utils.mime_types.findBuiltinMimeType
import dev.inmo.micro_utils.repos.ktor.common.crud.createRouting
import dev.inmo.micro_utils.repos.ktor.common.crud.updateRouting
import dev.inmo.micro_utils.repos.ktor.common.one_to_many.removeRoute
import dev.inmo.micro_utils.repos.ktor.server.crud.configureReadStandardCrudRepoRoutes
import dev.inmo.micro_utils.repos.ktor.server.crud.configureReadCRUDRepoRoutes
import dev.inmo.postssystem.features.common.common.FileBasedInputProvider
import dev.inmo.postssystem.features.content.common.*
import dev.inmo.postssystem.features.files.common.FileId
@ -22,6 +22,7 @@ import io.ktor.http.content.streamProvider
import io.ktor.server.application.ApplicationCall
import io.ktor.server.application.call
import io.ktor.server.auth.authenticate
import io.ktor.server.request.receive
import io.ktor.server.request.receiveMultipart
import io.ktor.server.response.respond
import io.ktor.server.routing.*
@ -32,8 +33,6 @@ import io.ktor.utils.io.streams.asInput
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.serialization.builtins.*
import kotlinx.serialization.modules.polymorphic
import java.io.File
import java.nio.file.Files
import java.nio.file.attribute.FileTime
@ -42,19 +41,8 @@ import java.util.concurrent.TimeUnit
class ServerPostsServiceRoutingConfigurator(
private val readPostsService: ReadPostsService,
private val writePostsService: WritePostsService? = readPostsService as? WritePostsService,
private val scope: CoroutineScope,
unifiedRouter: UnifiedRouter
private val scope: CoroutineScope
) : ApplicationRoutingConfigurator.Element {
private val unifiedRouter = UnifiedRouter(
serialFormat = unifiedRouter.serialFormat.createWithSerializerModuleExtension {
polymorphic(Content::class) {
subclass(BinaryContent::class, BinaryContentSerializer(TempFileIdentifierInputProvider::class, TempFileIdentifierInputProvider.serializer()))
}
}
)
private val contentEitherSerializer = EitherSerializer(ContentId.serializer(), ContentSerializer)
private val contentsEitherSerializer = ListSerializer(contentEitherSerializer)
private val contentsSerializer = ListSerializer(ContentSerializer)
private val temporalFilesMap = mutableMapOf<FileId, MPPFile>()
private val temporalFilesMutex = Mutex()
@ -97,20 +85,16 @@ class ServerPostsServiceRoutingConfigurator(
}
private suspend fun PipelineContext<Unit, ApplicationCall>.receiveContents(): List<Content> {
return unifiedRouter.run {
uniload(contentsSerializer).mapNotNull {
mapBinary(it as? BinaryContent ?: return@mapNotNull it)
}
return call.receive<ContentsWrapper>().content.mapNotNull {
mapBinary(it as? BinaryContent ?: return@mapNotNull it)
}
}
private suspend fun PipelineContext<Unit, ApplicationCall>.receiveContentsEithers(): List<Either<ContentId, Content>> {
return unifiedRouter.run {
uniload(contentsEitherSerializer).mapNotNull {
it.mapOnSecond {
mapBinary(it as? BinaryContent ?: return@mapOnSecond null) ?.either()
} ?: it
}
return call.receive<ContentsEithersWrapper>().content.mapNotNull {
it.mapOnSecond {
mapBinary(it as? BinaryContent ?: return@mapOnSecond null) ?.either()
} ?: it
}
}
@ -119,84 +103,70 @@ class ServerPostsServiceRoutingConfigurator(
override fun Route.invoke() {
authenticate {
route(postsRootPath) {
configureReadStandardCrudRepoRoutes(
readPostsService,
RegisteredPost.serializer(),
RegisteredPost.serializer().nullable,
PostId.serializer(),
unifiedRouter
)
configureReadCRUDRepoRoutes(
readPostsService
) { PostId(it.toLong()) }
writePostsService ?.let {
unifiedRouter.apply {
post(createRouting) {
val data = receiveContents()
post(createRouting) {
val data = receiveContents()
call.respond(
writePostsService.create(FullNewPost(data)) ?: HttpStatusCode.NoContent
)
}
unianswer(
RegisteredPost.serializer().nullable,
writePostsService.create(FullNewPost(data))
post(updateRouting) {
call.respond(
writePostsService.update(
call.getQueryParameterOrSendError(postsPostIdParameter)?.toLong()?.let(::PostId) ?: return@post,
receiveContentsEithers()
) ?: HttpStatusCode.NoContent
)
}
post(removeRoute) {
call.respond(
writePostsService.remove(
call.receive()
)
}
)
}
post(updateRouting) {
val postId = call.decodeUrlQueryValueOrSendError(postsPostIdParameter, PostId.serializer()) ?: return@post
val data = receiveContentsEithers()
post(postsCreateTempPathPart) {
val multipart = call.receiveMultipart()
unianswer(
RegisteredPost.serializer().nullable,
writePostsService.update(
postId,
data
)
)
}
post(removeRoute) {
val postId = uniload(PostId.serializer())
unianswer(
Unit.serializer(),
writePostsService.remove(postId)
)
}
post(postsCreateTempPathPart) {
val multipart = call.receiveMultipart()
var fileInfo: Pair<FileId, MPPFile>? = null
var part = multipart.readPart()
while (part != null) {
if (part is PartData.FileItem) {
break
}
part = multipart.readPart()
var fileInfo: Pair<FileId, MPPFile>? = null
var part = multipart.readPart()
while (part != null) {
if (part is PartData.FileItem) {
break
}
part ?.let {
if (it is PartData.FileItem) {
val fileId = FileId(uuid4().toString())
val fileName = it.originalFileName ?.let { FileName(it) } ?: return@let
fileInfo = fileId to File.createTempFile(fileId.string, ".${fileName.extension}").apply {
outputStream().use { outputStream ->
it.streamProvider().use {
it.copyTo(outputStream)
}
part = multipart.readPart()
}
part ?.let {
if (it is PartData.FileItem) {
val fileId = FileId(uuid4().toString())
val fileName = it.originalFileName ?.let { FileName(it) } ?: return@let
fileInfo = fileId to File.createTempFile(fileId.string, ".${fileName.extension}").apply {
outputStream().use { outputStream ->
it.streamProvider().use {
it.copyTo(outputStream)
}
deleteOnExit()
}
deleteOnExit()
}
}
fileInfo ?.also { (fileId, file) ->
temporalFilesMutex.withLock {
temporalFilesMap[fileId] = file
}
call.respond(fileId.string)
} ?: call.respond(HttpStatusCode.BadRequest)
}
fileInfo ?.also { (fileId, file) ->
temporalFilesMutex.withLock {
temporalFilesMap[fileId] = file
}
call.respond(fileId.string)
} ?: call.respond(HttpStatusCode.BadRequest)
}
}