diff --git a/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/controllers/SubordinateController.kt b/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/controllers/SubordinateController.kt index eb5ec554..29ece8c9 100644 --- a/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/controllers/SubordinateController.kt +++ b/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/controllers/SubordinateController.kt @@ -2,6 +2,7 @@ package com.sphereon.oid.fed.server.admin.controllers import com.sphereon.oid.fed.openapi.models.CreateSubordinateDTO import com.sphereon.oid.fed.openapi.models.SubordinateAdminDTO +import com.sphereon.oid.fed.openapi.models.SubordinateAdminJwkDto import com.sphereon.oid.fed.openapi.models.SubordinateStatement import com.sphereon.oid.fed.persistence.models.Subordinate import com.sphereon.oid.fed.persistence.models.SubordinateJwk @@ -48,7 +49,7 @@ class SubordinateController { fun getSubordinateJwks( @PathVariable accountUsername: String, @PathVariable id: Int - ): Array { + ): Array { return subordinateService.getSubordinateJwks(accountUsername, id) } diff --git a/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/controllers/SubordinateMetadataController.kt b/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/controllers/SubordinateMetadataController.kt new file mode 100644 index 00000000..6989d433 --- /dev/null +++ b/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/controllers/SubordinateMetadataController.kt @@ -0,0 +1,49 @@ +package com.sphereon.oid.fed.server.admin.controllers + +import com.sphereon.oid.fed.openapi.models.CreateMetadataDTO +import com.sphereon.oid.fed.openapi.models.SubordinateMetadataDTO +import com.sphereon.oid.fed.services.SubordinateService +import org.springframework.web.bind.annotation.DeleteMapping +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/accounts/{accountUsername}/subordinates/{subordinateId}/metadata") +class SubordinateMetadataController { + private val subordinateService = SubordinateService() + + @GetMapping + fun get( + @PathVariable accountUsername: String, + @PathVariable subordinateId: Int + ): Array { + return subordinateService.findSubordinateMetadata(accountUsername, subordinateId) + } + + @PostMapping + fun create( + @PathVariable accountUsername: String, + @PathVariable subordinateId: Int, + @RequestBody body: CreateMetadataDTO + ): SubordinateMetadataDTO { + return subordinateService.createMetadata( + accountUsername, + subordinateId, + body.key, + body.metadata + ) + } + + @DeleteMapping("/{id}") + fun delete( + @PathVariable accountUsername: String, + @PathVariable subordinateId: Int, + @PathVariable id: Int + ): SubordinateMetadataDTO { + return subordinateService.deleteSubordinateMetadata(accountUsername, subordinateId, id) + } +} diff --git a/modules/openapi/src/commonMain/kotlin/com/sphereon/oid/fed/openapi/openapi.yaml b/modules/openapi/src/commonMain/kotlin/com/sphereon/oid/fed/openapi/openapi.yaml index 9c431f9a..f3a1f3d5 100644 --- a/modules/openapi/src/commonMain/kotlin/com/sphereon/oid/fed/openapi/openapi.yaml +++ b/modules/openapi/src/commonMain/kotlin/com/sphereon/oid/fed/openapi/openapi.yaml @@ -1520,6 +1520,9 @@ components: type: object x-tags: - federation + required: + - kty + - kid properties: kty: type: string @@ -1532,7 +1535,7 @@ components: nullable: true kid: type: string - description: The key ID (optional). + description: The key ID. example: 12345 nullable: true x: @@ -1606,8 +1609,6 @@ components: - type: object x-tags: - federation - required: - - kty properties: d: type: string @@ -1678,6 +1679,27 @@ components: example: 2024-08-06T12:34:56Z nullable: true + SubordinateAdminJwkDto: + type: object + x-tags: + - federation + properties: + id: + type: integer + description: The unique identifier for the Subordinate key record. + example: 1 + subordinate_id: + type: integer + description: The ID of the subordinated account associated with this key. + example: 1 + key: + additionalProperties: true + created_at: + type: string + format: date-time + description: The timestamp when the key was created. + example: 2024-08-06T12:34:56Z + nullable: false JwkRevoked: type: object @@ -1792,12 +1814,6 @@ components: type: array items: type: string - metadata: - additionalProperties: true - crit: - type: array - items: - type: string trust_marks: type: array description: An array of JSON objects, each representing a Trust Mark. @@ -1840,6 +1856,42 @@ components: example: 2024-08-06T12:34:56Z nullable: true + SubordinateMetadataDTO: + type: object + x-tags: + - federation + properties: + id: + type: integer + description: The unique identifier for the Subordinate Metadata record. + example: 1 + account_id: + type: integer + description: The ID of the account associated with this Metadata. + example: 1 + subordinate_id: + type: integer + description: The ID of the subordinate associated with this Metadata. + example: 1 + key: + type: string + description: The key of the metadata. + example: openid_relying_party + metadata: + additionalProperties: true + created_at: + type: string + format: date-time + description: The timestamp when the Metadata was created. + example: 2024-08-06T12:34:56Z + nullable: false + deleted_at: + type: string + format: date-time + description: The timestamp when the Metadata was deleted. + example: 2024-08-06T12:34:56Z + nullable: true + CreateCritDTO: type: object x-tags: diff --git a/modules/openid-federation-common/src/commonMain/kotlin/com/sphereon/oid/fed/common/builder/SubordinateStatementBuilder.kt b/modules/openid-federation-common/src/commonMain/kotlin/com/sphereon/oid/fed/common/builder/SubordinateStatementBuilder.kt index cea9e93c..19b713a7 100644 --- a/modules/openid-federation-common/src/commonMain/kotlin/com/sphereon/oid/fed/common/builder/SubordinateStatementBuilder.kt +++ b/modules/openid-federation-common/src/commonMain/kotlin/com/sphereon/oid/fed/common/builder/SubordinateStatementBuilder.kt @@ -3,15 +3,18 @@ package com.sphereon.oid.fed.common.builder import com.sphereon.oid.fed.openapi.models.BaseEntityStatementJwks import com.sphereon.oid.fed.openapi.models.Jwk import com.sphereon.oid.fed.openapi.models.SubordinateStatement -import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.builtins.ListSerializer +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.buildJsonObject class SubordinateStatementBuilder { private var iss: String? = null private var sub: String? = null private var exp: Int? = null private var iat: Int? = null - private lateinit var jwks: MutableList + private var jwks: MutableList = mutableListOf(); private var metadata: MutableMap = mutableMapOf() private var metadata_policy: MutableMap = mutableMapOf() private var metadata_policy_crit: MutableMap = mutableMapOf() @@ -23,8 +26,6 @@ class SubordinateStatementBuilder { fun exp(exp: Int) = apply { this.exp = exp } fun iat(iat: Int) = apply { this.iat = iat } - fun jwks(jwk: Jwk) = apply { this.jwks.add(jwk) } - fun metadata(metadata: Pair) = apply { this.metadata[metadata.first] = metadata.second } @@ -41,13 +42,21 @@ class SubordinateStatementBuilder { this.crit.add(claim) } + fun jwks(jwk: Jwk) = apply { + this.jwks.add(jwk) + } + fun sourceEndpoint(sourceEndpoint: String) = apply { this.source_endpoint = sourceEndpoint } - @OptIn(ExperimentalSerializationApi::class) private fun createJwks(jwks: MutableList): BaseEntityStatementJwks { - return BaseEntityStatementJwks(jwks.toTypedArray()) + val jsonArray: JsonArray = + Json.encodeToJsonElement(ListSerializer(Jwk.serializer()), jwks) as JsonArray + + return buildJsonObject { + put("keys", jsonArray) + } as BaseEntityStatementJwks } fun build(): SubordinateStatement { diff --git a/modules/persistence/src/commonMain/kotlin/com/sphereon/oid/fed/persistence/Persistence.kt b/modules/persistence/src/commonMain/kotlin/com/sphereon/oid/fed/persistence/Persistence.kt index 5f60843c..aae2a79f 100644 --- a/modules/persistence/src/commonMain/kotlin/com/sphereon/oid/fed/persistence/Persistence.kt +++ b/modules/persistence/src/commonMain/kotlin/com/sphereon/oid/fed/persistence/Persistence.kt @@ -7,6 +7,7 @@ import com.sphereon.oid.fed.persistence.models.EntityConfigurationMetadataQuerie import com.sphereon.oid.fed.persistence.models.EntityConfigurationStatementQueries import com.sphereon.oid.fed.persistence.models.KeyQueries import com.sphereon.oid.fed.persistence.models.SubordinateJwkQueries +import com.sphereon.oid.fed.persistence.models.SubordinateMetadataQueries import com.sphereon.oid.fed.persistence.models.SubordinateQueries import com.sphereon.oid.fed.persistence.models.SubordinateStatementQueries @@ -20,4 +21,5 @@ expect object Persistence { val critQueries: CritQueries val subordinateStatementQueries: SubordinateStatementQueries val subordinateJwkQueries: SubordinateJwkQueries + val subordinateMetadataQueries: SubordinateMetadataQueries } diff --git a/modules/persistence/src/commonMain/sqldelight/com/sphereon/oid/fed/persistence/models/10.sqm b/modules/persistence/src/commonMain/sqldelight/com/sphereon/oid/fed/persistence/models/10.sqm new file mode 100644 index 00000000..f7ee6b70 --- /dev/null +++ b/modules/persistence/src/commonMain/sqldelight/com/sphereon/oid/fed/persistence/models/10.sqm @@ -0,0 +1,12 @@ +CREATE TABLE SubordinateMetadata ( + id SERIAL PRIMARY KEY, + account_id INT NOT NULL, + subordinate_id INT NOT NULL, + key TEXT NOT NULL, + metadata TEXT NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted_at TIMESTAMP, + CONSTRAINT FK_ParentEntityConfigurationMetadata FOREIGN KEY (account_id) REFERENCES Account (id) +); + +CREATE INDEX subordinate_metadata_account_id_index ON SubordinateMetadata (account_id); diff --git a/modules/persistence/src/commonMain/sqldelight/com/sphereon/oid/fed/persistence/models/Subordinate.sq b/modules/persistence/src/commonMain/sqldelight/com/sphereon/oid/fed/persistence/models/Subordinate.sq index 8d2585d4..b10a9a88 100644 --- a/modules/persistence/src/commonMain/sqldelight/com/sphereon/oid/fed/persistence/models/Subordinate.sq +++ b/modules/persistence/src/commonMain/sqldelight/com/sphereon/oid/fed/persistence/models/Subordinate.sq @@ -10,6 +10,9 @@ UPDATE Subordinate SET deleted_at = CURRENT_TIMESTAMP WHERE id = ? AND deleted_a findByAccountId: SELECT * FROM Subordinate WHERE account_id = ? AND deleted_at IS NULL; +findByAccountIdAndSubordinateId: +SELECT * FROM Subordinate WHERE id = ? AND account_id = ? AND deleted_at IS NULL; + findByAccountIdAndIdentifier: SELECT * FROM Subordinate WHERE account_id = ? AND identifier = ? AND deleted_at IS NULL; diff --git a/modules/persistence/src/commonMain/sqldelight/com/sphereon/oid/fed/persistence/models/SubordinateMetadata.sq b/modules/persistence/src/commonMain/sqldelight/com/sphereon/oid/fed/persistence/models/SubordinateMetadata.sq new file mode 100644 index 00000000..3795f766 --- /dev/null +++ b/modules/persistence/src/commonMain/sqldelight/com/sphereon/oid/fed/persistence/models/SubordinateMetadata.sq @@ -0,0 +1,28 @@ +create: +INSERT INTO SubordinateMetadata ( + account_id, + subordinate_id, + key, + metadata +) VALUES (?, ?, ?, ?) RETURNING *; + +delete: +UPDATE SubordinateMetadata SET deleted_at = CURRENT_TIMESTAMP WHERE id = ? AND deleted_at IS NULL RETURNING *; + +findByAccountId: +SELECT * FROM SubordinateMetadata WHERE account_id = ? AND deleted_at IS NULL; + +findByAccountIdAndSubordinateId: +SELECT * FROM SubordinateMetadata WHERE account_id = ? AND subordinate_id = ? AND deleted_at IS NULL; + +findByAccountIdAndSubordinateIdAndKey: +SELECT * FROM SubordinateMetadata WHERE account_id = ? AND subordinate_id = ? AND key = ? AND deleted_at IS NULL; + +findByAccountIdAndSubordinateIdAndId: +SELECT * FROM SubordinateMetadata WHERE account_id = ? AND subordinate_id = ? AND id = ? AND deleted_at IS NULL; + +findByAccountIdAndKey: +SELECT * FROM SubordinateMetadata WHERE account_id = ? AND key = ? AND deleted_at IS NULL; + +findById: +SELECT * FROM SubordinateMetadata WHERE id = ? AND deleted_at IS NULL; diff --git a/modules/persistence/src/jvmMain/kotlin/com.sphereon.oid.fed.persistence/Persistence.jvm.kt b/modules/persistence/src/jvmMain/kotlin/com.sphereon.oid.fed.persistence/Persistence.jvm.kt index 2098e093..f41f5aec 100644 --- a/modules/persistence/src/jvmMain/kotlin/com.sphereon.oid.fed.persistence/Persistence.jvm.kt +++ b/modules/persistence/src/jvmMain/kotlin/com.sphereon.oid.fed.persistence/Persistence.jvm.kt @@ -11,6 +11,7 @@ import com.sphereon.oid.fed.persistence.models.EntityConfigurationMetadataQuerie import com.sphereon.oid.fed.persistence.models.EntityConfigurationStatementQueries import com.sphereon.oid.fed.persistence.models.KeyQueries import com.sphereon.oid.fed.persistence.models.SubordinateJwkQueries +import com.sphereon.oid.fed.persistence.models.SubordinateMetadataQueries import com.sphereon.oid.fed.persistence.models.SubordinateQueries import com.sphereon.oid.fed.persistence.models.SubordinateStatementQueries @@ -24,6 +25,7 @@ actual object Persistence { actual val critQueries: CritQueries actual val subordinateStatementQueries: SubordinateStatementQueries actual val subordinateJwkQueries: SubordinateJwkQueries + actual val subordinateMetadataQueries: SubordinateMetadataQueries init { val driver = getDriver() @@ -39,6 +41,7 @@ actual object Persistence { critQueries = database.critQueries subordinateStatementQueries = database.subordinateStatementQueries subordinateJwkQueries = database.subordinateJwkQueries + subordinateMetadataQueries = database.subordinateMetadataQueries } private fun getDriver(): SqlDriver { diff --git a/modules/services/src/commonMain/kotlin/com/sphereon/oid/fed/services/Constants.kt b/modules/services/src/commonMain/kotlin/com/sphereon/oid/fed/services/Constants.kt index df9fde67..f907b48c 100644 --- a/modules/services/src/commonMain/kotlin/com/sphereon/oid/fed/services/Constants.kt +++ b/modules/services/src/commonMain/kotlin/com/sphereon/oid/fed/services/Constants.kt @@ -9,6 +9,7 @@ class Constants { const val SUBORDINATE_ALREADY_EXISTS = "Subordinate already exists" const val ENTITY_CONFIGURATION_METADATA_ALREADY_EXISTS = "Entity configuration metadata already exists" const val FAILED_TO_CREATE_ENTITY_CONFIGURATION_METADATA = "Failed to create entity configuration metadata" + const val FAILED_TO_CREATE_SUBORDINATE_METADATA = "Failed to create subordinate metadata" const val ENTITY_CONFIGURATION_METADATA_NOT_FOUND = "Entity configuration metadata not found" const val FAILED_TO_CREATE_AUTHORITY_HINT = "Failed to create authority hint" const val AUTHORITY_HINT_NOT_FOUND = "Authority hint not found" @@ -22,5 +23,7 @@ class Constants { const val SUBORDINATE_NOT_FOUND = "Subordinate not found" const val SUBORDINATE_JWK_NOT_FOUND = "Subordinate JWK not found" const val SUBORDINATE_STATEMENT_NOT_FOUND = "Subordinate statement not found" + const val SUBORDINATE_METADATA_NOT_FOUND = "Subordinate metadata not found" + const val SUBORDINATE_METADATA_ALREADY_EXISTS = "Subordinate metadata already exists" } } diff --git a/modules/services/src/commonMain/kotlin/com/sphereon/oid/fed/services/SubordinateService.kt b/modules/services/src/commonMain/kotlin/com/sphereon/oid/fed/services/SubordinateService.kt index d9081d15..a393913c 100644 --- a/modules/services/src/commonMain/kotlin/com/sphereon/oid/fed/services/SubordinateService.kt +++ b/modules/services/src/commonMain/kotlin/com/sphereon/oid/fed/services/SubordinateService.kt @@ -3,11 +3,15 @@ package com.sphereon.oid.fed.services import com.sphereon.oid.fed.common.builder.SubordinateStatementBuilder import com.sphereon.oid.fed.openapi.models.CreateSubordinateDTO import com.sphereon.oid.fed.openapi.models.JWTHeader +import com.sphereon.oid.fed.openapi.models.SubordinateAdminJwkDto +import com.sphereon.oid.fed.openapi.models.SubordinateMetadataDTO import com.sphereon.oid.fed.openapi.models.SubordinateStatement import com.sphereon.oid.fed.persistence.Persistence import com.sphereon.oid.fed.persistence.models.Subordinate import com.sphereon.oid.fed.persistence.models.SubordinateJwk import com.sphereon.oid.fed.services.extensions.toJwk +import com.sphereon.oid.fed.services.extensions.toSubordinateAdminJwkDTO +import com.sphereon.oid.fed.services.extensions.toSubordinateMetadataDTO import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.jsonObject @@ -54,6 +58,9 @@ class SubordinateService { ?: throw IllegalArgumentException(Constants.SUBORDINATE_NOT_FOUND) val subordinateJwks = subordinateJwkQueries.findBySubordinateId(subordinate.id).executeAsList() + val subordinateMetadataList = + Persistence.subordinateMetadataQueries.findByAccountIdAndSubordinateId(account.id, subordinate.id) + .executeAsList() val subordinateStatement = SubordinateStatementBuilder() .iss(accountService.getAccountIdentifier(account.username)) @@ -70,6 +77,12 @@ class SubordinateService { subordinateStatement.jwks(it.toJwk()) } + subordinateMetadataList.forEach { + subordinateStatement.metadata( + Pair(it.key, Json.parseToJsonElement(it.metadata).jsonObject) + ) + } + return subordinateStatement.build() } @@ -124,14 +137,15 @@ class SubordinateService { return subordinateJwkQueries.create(key = jwk.toString(), subordinate_id = subordinate.id).executeAsOne() } - fun getSubordinateJwks(accountUsername: String, id: Int): Array { + fun getSubordinateJwks(accountUsername: String, id: Int): Array { val account = accountQueries.findByUsername(accountUsername).executeAsOneOrNull() ?: throw IllegalArgumentException(Constants.ACCOUNT_NOT_FOUND) val subordinate = subordinateQueries.findById(id).executeAsOneOrNull() ?: throw IllegalArgumentException(Constants.SUBORDINATE_NOT_FOUND) - return subordinateJwkQueries.findBySubordinateId(subordinate.id).executeAsList().toTypedArray() + return subordinateJwkQueries.findBySubordinateId(subordinate.id).executeAsList() + .map { it.toSubordinateAdminJwkDTO() }.toTypedArray() } fun deleteSubordinateJwk(accountUsername: String, subordinateId: Int, id: Int): SubordinateJwk { @@ -161,4 +175,71 @@ class SubordinateService { return subordinateStatement.statement } + + fun findSubordinateMetadata( + accountUsername: String, + subordinateId: Int + ): Array { + val account = Persistence.accountQueries.findByUsername(accountUsername).executeAsOneOrNull() + ?: throw IllegalArgumentException(Constants.ACCOUNT_NOT_FOUND) + + val subordinate = Persistence.subordinateQueries.findByAccountIdAndSubordinateId(account.id, subordinateId) + .executeAsOneOrNull() ?: throw IllegalArgumentException(Constants.SUBORDINATE_NOT_FOUND) + + return Persistence.subordinateMetadataQueries.findByAccountIdAndSubordinateId(account.id, subordinate.id) + .executeAsList() + .map { it.toSubordinateMetadataDTO() }.toTypedArray() + } + + fun createMetadata( + accountUsername: String, + subordinateId: Int, + key: String, + metadata: JsonObject + ): SubordinateMetadataDTO { + val account = Persistence.accountQueries.findByUsername(accountUsername).executeAsOneOrNull() + ?: throw IllegalArgumentException(Constants.ACCOUNT_NOT_FOUND) + + val subordinate = Persistence.subordinateQueries.findByAccountIdAndSubordinateId(account.id, subordinateId) + .executeAsOneOrNull() ?: throw IllegalArgumentException(Constants.SUBORDINATE_NOT_FOUND) + + val metadataAlreadyExists = + Persistence.subordinateMetadataQueries.findByAccountIdAndSubordinateIdAndKey(account.id, subordinateId, key) + .executeAsOneOrNull() + + if (metadataAlreadyExists != null) { + throw IllegalStateException(Constants.SUBORDINATE_METADATA_ALREADY_EXISTS) + } + + val createdMetadata = + Persistence.subordinateMetadataQueries.create(account.id, subordinate.id, key, metadata.toString()) + .executeAsOneOrNull() + ?: throw IllegalStateException(Constants.FAILED_TO_CREATE_SUBORDINATE_METADATA) + + return createdMetadata.toSubordinateMetadataDTO() + } + + fun deleteSubordinateMetadata( + accountUsername: String, + subordinateId: Int, + id: Int + ): SubordinateMetadataDTO { + val account = Persistence.accountQueries.findByUsername(accountUsername).executeAsOneOrNull() + ?: throw IllegalArgumentException(Constants.ACCOUNT_NOT_FOUND) + + val subordinate = Persistence.subordinateQueries.findByAccountIdAndSubordinateId(account.id, subordinateId) + .executeAsOneOrNull() ?: throw IllegalArgumentException(Constants.SUBORDINATE_NOT_FOUND) + + val metadata = + Persistence.subordinateMetadataQueries.findByAccountIdAndSubordinateIdAndId( + account.id, + subordinate.id, + id + ).executeAsOneOrNull() ?: throw IllegalArgumentException(Constants.ENTITY_CONFIGURATION_METADATA_NOT_FOUND) + + val deletedMetadata = Persistence.subordinateMetadataQueries.delete(metadata.id).executeAsOneOrNull() + ?: throw IllegalArgumentException(Constants.SUBORDINATE_METADATA_NOT_FOUND) + + return deletedMetadata.toSubordinateMetadataDTO() + } } diff --git a/modules/services/src/commonMain/kotlin/com/sphereon/oid/fed/services/extensions/SubordinateJwkExtensions.kt b/modules/services/src/commonMain/kotlin/com/sphereon/oid/fed/services/extensions/SubordinateJwkExtensions.kt index 63a49fa9..ff166921 100644 --- a/modules/services/src/commonMain/kotlin/com/sphereon/oid/fed/services/extensions/SubordinateJwkExtensions.kt +++ b/modules/services/src/commonMain/kotlin/com/sphereon/oid/fed/services/extensions/SubordinateJwkExtensions.kt @@ -2,11 +2,22 @@ package com.sphereon.oid.fed.services.extensions import com.sphereon.oid.fed.openapi.models.Jwk import com.sphereon.oid.fed.openapi.models.JwkAdminDTO +import com.sphereon.oid.fed.openapi.models.SubordinateAdminJwkDto import com.sphereon.oid.fed.persistence.models.SubordinateJwk import kotlinx.serialization.json.Json +import kotlinx.serialization.json.jsonObject fun SubordinateJwk.toJwk(): Jwk { val key = Json.decodeFromString(this.key) return key.toJwk() } + +fun SubordinateJwk.toSubordinateAdminJwkDTO(): SubordinateAdminJwkDto { + return SubordinateAdminJwkDto( + id = this.id, + subordinateId = this.subordinate_id, + key = Json.parseToJsonElement(this.key).jsonObject, + createdAt = this.created_at.toString() + ) +} diff --git a/modules/services/src/commonMain/kotlin/com/sphereon/oid/fed/services/extensions/SubordinateMetadataExtensions.kt b/modules/services/src/commonMain/kotlin/com/sphereon/oid/fed/services/extensions/SubordinateMetadataExtensions.kt new file mode 100644 index 00000000..adc86f9c --- /dev/null +++ b/modules/services/src/commonMain/kotlin/com/sphereon/oid/fed/services/extensions/SubordinateMetadataExtensions.kt @@ -0,0 +1,17 @@ +package com.sphereon.oid.fed.services.extensions + +import com.sphereon.oid.fed.openapi.models.SubordinateMetadataDTO +import com.sphereon.oid.fed.persistence.models.SubordinateMetadata +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.jsonObject + +fun SubordinateMetadata.toSubordinateMetadataDTO(): SubordinateMetadataDTO { + return SubordinateMetadataDTO( + id = this.id, + key = this.key, + subordinateId = this.subordinate_id, + metadata = Json.parseToJsonElement(this.metadata).jsonObject, + accountId = this.account_id, + createdAt = this.created_at.toString(), + ) +}