com.lightningkite.lightningserver.files.UploadEarlyEndpoint.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of server-core Show documentation
Show all versions of server-core Show documentation
A set of tools to fill in/replace what Ktor is lacking in.
The newest version!
package com.lightningkite.lightningserver.files
import com.lightningkite.lightningdb.*
import com.lightningkite.lightningserver.auth.JwtSigner
import com.lightningkite.lightningserver.core.ServerPath
import com.lightningkite.lightningserver.core.ServerPathGroup
import com.lightningkite.lightningserver.exceptions.UnauthorizedException
import com.lightningkite.lightningserver.schedule.schedule
import com.lightningkite.lightningserver.typed.typed
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.time.Duration
import java.time.Instant
class UploadEarlyEndpoint(
path: ServerPath,
val files: () -> FileSystem,
val database: () -> Database,
val signer: () -> JwtSigner,
val filePath: String = ExternalServerFileSerializer.uploadPath,
val expiration: Duration = Duration.ofDays(1)
) : ServerPathGroup(path) {
companion object {
var default: UploadEarlyEndpoint? = null
}
init {
prepareModels()
ExternalServerFileSerializer.fileValidators += this::validateFile
ExternalServerFileSerializer.fileSystem = files
default = this
}
val endpoint = get.typed(
summary = "Upload File for Request",
description = "Upload a file to make a request later. Times out in around 10 minutes.",
errorCases = listOf(),
implementation = { user: Unit, nothing: Unit ->
val newFile = files().root.resolve(filePath).resolveRandom("file", "file")
val newItem = UploadForNextRequest(
expires = Instant.now().plus(expiration),
file = ServerFile(newFile.url)
)
database().collection().insertOne(newItem)
UploadInformation(
uploadUrl = newFile.uploadUrl(expiration),
futureCallToken = newFile.url + "?token=" + signer().token(newFile.url, expiration)
)
}
)
val cleanupSchedule = schedule("cleanupUploads", Duration.ofDays(1)) {
database().collection().deleteMany(condition { it.expires lt Instant.now() }).forEach {
try {
it.file.fileObject.delete()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
@OptIn(DelicateCoroutinesApi::class)
fun validateFile(url: String, params: Map): Boolean {
return params["token"]?.let { token ->
try {
val tokenUrl = signer().verify(token)
if (url == tokenUrl) {
GlobalScope.launch {
database().collection()
.deleteMany(condition { it.file eq ServerFile(url) })
}
true
} else false
} catch (e: UnauthorizedException) {
false
}
} ?: false
}
}