package world.respect.server import io.ktor.client.HttpClient import io.ktor.client.engine.okhttp.OkHttp import io.ktor.client.plugins.contentnegotiation.ContentNegotiation import io.ktor.client.request.header import io.ktor.client.request.post import io.ktor.client.request.setBody import io.ktor.http.ContentType import io.ktor.http.HttpHeaders import io.ktor.http.Url import io.ktor.http.contentType import io.ktor.serialization.kotlinx.json.json import io.ktor.util.encodeBase64 import kotlinx.coroutines.runBlocking import kotlinx.serialization.json.Json import net.sourceforge.argparse4j.inf.Namespace import nl.adaptivity.xmlutil.core.XmlVersion import nl.adaptivity.xmlutil.serialization.XML import world.respect.datalayer.respect.model.SchoolDirectoryEntry import world.respect.lib.opds.model.LangMapStringValue import world.respect.libutil.ext.appendEndpointSegments import world.respect.libutil.ext.sanitizedForFilename import world.respect.server.domain.school.add.AddSchoolUseCase import world.respect.server.domain.school.add.AddSchoolUseCase.Companion.DEFAULT_ADMIN_USERNAME import world.respect.server.domain.school.demoapp.MakeDemoAppCollectionUseCase import world.respect.server.domain.school.demoapp.MakeDemoAppGradeCollectionsUseCase import world.respect.server.domain.school.demoapp.MakeDemoAppLearningUnitHtmlUseCase import world.respect.server.domain.school.demoapp.MakeDemoAppLearningUnitManifestUseCase import world.respect.server.domain.school.demoapp.MakeDemoAppLearningUnitTinCanXmlUseCase import world.respect.server.domain.school.demoapp.MakeDemoAppManifestUseCase import world.respect.server.domain.school.demoapp.SaveDemoAppToStaticFilesUseCase import java.io.File import java.util.Properties import kotlin.system.exitProcess import kotlin.time.Clock fun managerServerMain(ns: Namespace) { val json = Json { encodeDefaults = false } val httpClient = HttpClient(OkHttp) { install(ContentNegotiation) { json(json = json) } } val xml = XML.v1 { recommended_1_0_0() xmlVersion = XmlVersion.XML10 } val dataDir = ns.getString("datadir")?.let { File(it) } ?: File("${ktorAppHomeDir().absolutePath}/$DEFAULT_DATA_DIR_NAME") println("DataDir=$dataDir") val serverPropertiesFile = ktorServerPropertiesFile(dataDir = dataDir) if(!serverPropertiesFile.exists()) { println("Error: Server is not running: server.properties does not exist") exitProcess(1) } val serverProperties = Properties() serverPropertiesFile.reader().use { serverPropertiesReader -> serverProperties.load(serverPropertiesReader) } val port = serverProperties.getProperty(SERVER_PROPERTIES_KEY_PORT) val systemConfigAuth = File(dataDir, DIRECTORY_ADMIN_FILENAME).readText().trim() println("Connect to $port using auth $systemConfigAuth") val serverUrl = Url("http://localhost:$port/") val authHeader = "Basic ${"admin:$systemConfigAuth".encodeBase64()}" runBlocking { when(ns.getString("subparser_name")) { CMD_ADD_SCHOOL -> { val schoolBaseUrl = Url(ns.getString("url")) val rpId = ns.getString("rpId") ?: schoolBaseUrl.host val nsDirUrl: String? = ns.getString("inDirectoryUrl") val response = httpClient.post( serverUrl.appendEndpointSegments("api/directory/school") ) { header(HttpHeaders.Authorization, authHeader) contentType(ContentType.Application.Json) setBody( listOf( AddSchoolUseCase.AddSchoolRequest( school = SchoolDirectoryEntry( name = LangMapStringValue(ns.getString("name")), self = schoolBaseUrl, xapi = schoolBaseUrl.appendEndpointSegments("api/school/xapi"), oneRoster = schoolBaseUrl.appendEndpointSegments("api/school/oneroster"), respectExt = schoolBaseUrl.appendEndpointSegments("api/school/respect"), //Will be set on server rpId = rpId, lastModified = Clock.System.now(), stored = Clock.System.now(), inDirectoryUrl = nsDirUrl?.let { Url(it) }, ), dbUrl = ns.getString("dburl") ?: schoolBaseUrl.sanitizedForFilename(), adminUsername = ns.getString("adminusername") ?: DEFAULT_ADMIN_USERNAME, adminPassword = ns.getString("adminpassword"), ) ) ) } println("Response: ${response.status}") } CMD_MAKE_DEMO_APP -> { val baseUrl = Url(ns.getString("url")) val destDir = File(ns.getString("dir")) val saveDemoAppToStaticFilesUseCase = SaveDemoAppToStaticFilesUseCase( makeDemoAppManifestUseCase = MakeDemoAppManifestUseCase(), makeDemoAppCollectionUseCase = MakeDemoAppCollectionUseCase(), makeDemoAppGradeCollectionsUseCase = MakeDemoAppGradeCollectionsUseCase(), makeDemoAppLearningUnitManifestUseCase = MakeDemoAppLearningUnitManifestUseCase(), makeDemoAppLearningUnitTinCanXmlUseCase = MakeDemoAppLearningUnitTinCanXmlUseCase(), makeDemoAppLearningUnitHtmlUseCase = MakeDemoAppLearningUnitHtmlUseCase(), xml = xml, json = json, ) saveDemoAppToStaticFilesUseCase( destDir = destDir, baseUrl = baseUrl, ) } } exitProcess(0) } }