diff --git a/config/keri/cf/inception-config.json b/config/keri/inception-config.json similarity index 99% rename from config/keri/cf/inception-config.json rename to config/keri/inception-config.json index b60b409..850aca0 100644 --- a/config/keri/cf/inception-config.json +++ b/config/keri/inception-config.json @@ -10,4 +10,4 @@ "ncount": 1, "isith": "1", "nsith": "1" -} \ No newline at end of file +} diff --git a/src/main/kotlin/id/walt/service/dto/KeriUserManagementObjects.kt b/src/main/kotlin/id/walt/service/dto/KeriUserManagementObjects.kt index 24ad3b7..f56566d 100644 --- a/src/main/kotlin/id/walt/service/dto/KeriUserManagementObjects.kt +++ b/src/main/kotlin/id/walt/service/dto/KeriUserManagementObjects.kt @@ -12,3 +12,15 @@ data class KeriCreateDbResponse ( val salt: String, val witnesses: List ) + +@Serializable +data class KeriInceptionRequest ( + val alias: String, + val passcode: String +) +@Serializable +data class KeriInceptionResponse ( + val aid: String, + val did: String, + val publicKeys: List +) diff --git a/src/main/kotlin/id/walt/service/keri/KeriInceptionService.kt b/src/main/kotlin/id/walt/service/keri/KeriInceptionService.kt new file mode 100644 index 0000000..9ffb778 --- /dev/null +++ b/src/main/kotlin/id/walt/service/keri/KeriInceptionService.kt @@ -0,0 +1,73 @@ +package id.walt.service.keri + +import id.walt.service.dto.KeriInceptionResponse +import id.walt.service.keri.interfaces.KeriInceptionInterface +import java.io.BufferedReader +import java.io.IOException +import java.io.InputStreamReader + +class KeriInceptionService: KeriInceptionInterface { + + private val CONFIG_DIR = "config" + private val INCEPTION_FILE = "inception-config.json" + override fun inceptController(name: String, alias: String, passcode: String): KeriInceptionResponse { + var prefix = "" + val publicKeys = mutableListOf() + + val inceptCommand: List = listOf( + "kli", "incept", + "--name" ,name, + "--alias", alias, + "--passcode", passcode, + "--file", "$CONFIG_DIR/keri/$INCEPTION_FILE" + ) + + // kli status --name waltid --alias waltid-alias | awk '/Identifier:/ {print $2}' + val statusCommand: List = listOf( + "kli", "status", + "--name" ,name, + "--alias", alias, + "--passcode", passcode + ) + + try { + val processBuilder = ProcessBuilder(inceptCommand) + val process = processBuilder.start() + process.waitFor() + + val statusProcessBuilder = ProcessBuilder(statusCommand) + val statusProcess = statusProcessBuilder.start() + + val prefixInputReader = BufferedReader(InputStreamReader(statusProcess.inputStream)) + + var line: String? + var capturingPublicKeys = false + while (prefixInputReader.readLine().also { line = it } != null) { + if (line?.contains("Identifier:") == true) { + prefix = line!!.split(" ")[1] + } + + if (line?.startsWith("Public Keys:") == true) { + capturingPublicKeys = true + continue + } + + if (capturingPublicKeys && line?.isNotBlank() == true) { + publicKeys.add(line!!.trim().split(" ")[1]) + } else if (capturingPublicKeys && line?.isBlank() == true) { + break + } + } + + statusProcess.waitFor() + + } catch(e: IOException) { + e.printStackTrace() + } catch (e: InterruptedException) { + e.printStackTrace() + } + + return KeriInceptionResponse(prefix, "did:keri:$prefix", publicKeys) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/id/walt/service/keri/interfaces/KeriInceptionInterface.kt b/src/main/kotlin/id/walt/service/keri/interfaces/KeriInceptionInterface.kt new file mode 100644 index 0000000..574950f --- /dev/null +++ b/src/main/kotlin/id/walt/service/keri/interfaces/KeriInceptionInterface.kt @@ -0,0 +1,7 @@ +package id.walt.service.keri.interfaces + +import id.walt.service.dto.KeriInceptionResponse + +interface KeriInceptionInterface { + fun inceptController(name: String, alias: String, passcode: String): KeriInceptionResponse; +} \ No newline at end of file diff --git a/src/main/kotlin/id/walt/web/controllers/KeriController.kt b/src/main/kotlin/id/walt/web/controllers/KeriController.kt index 78dce7d..13578e2 100644 --- a/src/main/kotlin/id/walt/web/controllers/KeriController.kt +++ b/src/main/kotlin/id/walt/web/controllers/KeriController.kt @@ -2,6 +2,9 @@ package id.walt.web.controllers import id.walt.service.dto.KeriCreateDbRequest import id.walt.service.dto.KeriCreateDbResponse +import id.walt.service.dto.KeriInceptionRequest +import id.walt.service.dto.KeriInceptionResponse +import id.walt.service.keri.KeriInceptionService import id.walt.service.keri.KeriInitService import io.github.smiley4.ktorswaggerui.dsl.post import io.github.smiley4.ktorswaggerui.dsl.route @@ -54,5 +57,43 @@ fun Application.keri() = walletRoute { } + post("incept/{name}", { + summary = "Create an inception event to initiate a controller" + + request { + pathParameter("name") { + description = "keystore name and file location of KERI keystore" + example = "waltid" + } + + body { + description = "Required data for the inception of a controller" + example("application/json", KeriInceptionRequest(alias = "waltid-alias", passcode = "0123456789abcdefghijk")) + } + + } + response { + HttpStatusCode.Created to { + body { + description = "The identifiers of the controller. An AID, DID and public keys" + example("application/json", KeriInceptionResponse(aid = "EPjNBI4spoZ3lU5OCtNO4QgJmhIw7P1T-JOtwit36do4", did = "did:keri:EPjNBI4spoZ3lU5OCtNO4QgJmhIw7P1T-JOtwit36do4", publicKeys = listOf( + "DOERpUwwYCSyWH8e8yLJDKZpvEly_oJ8QJPw2wH3qRVQ" + ))) { + summary = "Example of creating an inception event (First event in a Key Event Log (KEL))" + } + } + } + } + }) { + val name = call.parameters["name"] ?: return@post call.respond(HttpStatusCode.BadRequest) + val dto = call.receive() + val response = KeriInceptionService().inceptController(name, dto.alias, dto.passcode) + + + call.respond(HttpStatusCode.Created, response) + + + } + } } \ No newline at end of file