2022-05-03 13:33:43 +03:00
|
|
|
package ru.mipt.spc
|
|
|
|
|
|
|
|
import io.ktor.http.HttpStatusCode
|
2022-05-06 15:54:59 +03:00
|
|
|
import io.ktor.server.application.Application
|
2022-05-03 13:33:43 +03:00
|
|
|
import io.ktor.server.application.install
|
2022-05-06 15:54:59 +03:00
|
|
|
import io.ktor.server.application.log
|
2022-05-03 13:33:43 +03:00
|
|
|
import io.ktor.server.engine.embeddedServer
|
|
|
|
import io.ktor.server.netty.Netty
|
|
|
|
import io.ktor.server.plugins.statuspages.StatusPages
|
|
|
|
import io.ktor.server.response.respond
|
|
|
|
import kotlinx.css.CssBuilder
|
|
|
|
import kotlinx.html.CommonAttributeGroupFacade
|
|
|
|
import kotlinx.html.style
|
|
|
|
import ru.mipt.spc.magprog.magProgPage
|
|
|
|
import space.kscience.dataforge.context.Context
|
|
|
|
import space.kscience.snark.SnarkPlugin
|
|
|
|
import java.net.URI
|
2022-05-06 15:54:59 +03:00
|
|
|
import java.nio.file.FileSystems
|
|
|
|
import java.nio.file.Files
|
|
|
|
import java.nio.file.Path
|
2022-05-03 17:15:07 +03:00
|
|
|
import kotlin.io.path.createDirectories
|
|
|
|
import kotlin.io.path.isRegularFile
|
|
|
|
import kotlin.io.path.relativeTo
|
2022-05-03 13:33:43 +03:00
|
|
|
|
|
|
|
fun CommonAttributeGroupFacade.css(block: CssBuilder.() -> Unit) {
|
|
|
|
style = CssBuilder().block().toString()
|
|
|
|
}
|
|
|
|
|
|
|
|
class AuthenticationException : RuntimeException()
|
|
|
|
class AuthorizationException : RuntimeException()
|
|
|
|
|
2022-05-06 15:54:59 +03:00
|
|
|
private fun Application.resolveData(uri: URI, targetPath: Path): Path {
|
|
|
|
if (Files.isDirectory(targetPath)) {
|
|
|
|
log.info("Using existing data directory at $targetPath.")
|
|
|
|
} else {
|
|
|
|
log.info("Copying data from $uri into $targetPath.")
|
|
|
|
targetPath.createDirectories()
|
2022-05-03 17:15:07 +03:00
|
|
|
//Copy everything into a temporary directory
|
2022-05-03 13:33:43 +03:00
|
|
|
FileSystems.newFileSystem(uri, emptyMap<String, Any>()).use { fs ->
|
2022-05-03 17:15:07 +03:00
|
|
|
val rootPath: Path = fs.provider().getPath(uri)
|
|
|
|
Files.walk(rootPath).forEach { source: Path ->
|
|
|
|
if (source.isRegularFile()) {
|
|
|
|
val relative = source.relativeTo(rootPath).toString()
|
2022-05-06 15:54:59 +03:00
|
|
|
val destination: Path = targetPath.resolve(relative)
|
2022-05-03 17:15:07 +03:00
|
|
|
destination.parent.createDirectories()
|
|
|
|
Files.copy(source, destination)
|
|
|
|
}
|
|
|
|
}
|
2022-05-03 13:33:43 +03:00
|
|
|
}
|
|
|
|
}
|
2022-05-06 15:54:59 +03:00
|
|
|
return targetPath
|
2022-05-03 13:33:43 +03:00
|
|
|
}
|
|
|
|
|
2022-05-03 17:15:07 +03:00
|
|
|
|
2022-05-03 13:33:43 +03:00
|
|
|
fun main() {
|
|
|
|
val context = Context("spc-site") {
|
|
|
|
plugin(SnarkPlugin)
|
|
|
|
}
|
2022-05-06 15:54:59 +03:00
|
|
|
|
|
|
|
val dataPath = Path.of("data")
|
|
|
|
|
|
|
|
embeddedServer(Netty, port = 7080, watchPaths = listOf("classes")) {
|
2022-05-03 17:15:07 +03:00
|
|
|
install(StatusPages) {
|
|
|
|
exception<AuthenticationException> { call, _ ->
|
|
|
|
call.respond(HttpStatusCode.Unauthorized)
|
|
|
|
}
|
|
|
|
exception<AuthorizationException> { call, _ ->
|
|
|
|
call.respond(HttpStatusCode.Forbidden)
|
2022-05-03 13:33:43 +03:00
|
|
|
}
|
2022-05-03 17:15:07 +03:00
|
|
|
}
|
2022-05-06 15:54:59 +03:00
|
|
|
|
|
|
|
val magProgDataPath = resolveData(
|
|
|
|
javaClass.getResource("/magprog")!!.toURI(),
|
|
|
|
dataPath.resolve("magprog")
|
|
|
|
)
|
|
|
|
|
|
|
|
magProgPage(context, rootPath = magProgDataPath)
|
|
|
|
|
2022-05-03 13:33:43 +03:00
|
|
|
}.start(wait = true)
|
|
|
|
|
|
|
|
}
|