10 files changed
+1286
-149
No files matched your search
@@ -7,6 +7,19 @@ import com.m57.hermescontrol.data.model.ConnectorCatalogEntry
|
||||
import com.m57.hermescontrol.data.model.ConnectorError
|
||||
import com.m57.hermescontrol.data.model.ConnectorPolicy
|
||||
import com.m57.hermescontrol.data.model.ConnectorTool
|
||||
import com.m57.hermescontrol.data.ws.contract.ConnectorOwner
|
||||
import com.m57.hermescontrol.data.ws.contract.ConnectorsAccountsParams
|
||||
import com.m57.hermescontrol.data.ws.contract.ConnectorsAccountsRemoveParams
|
||||
import com.m57.hermescontrol.data.ws.contract.ConnectorsCatalogParams
|
||||
import com.m57.hermescontrol.data.ws.contract.ConnectorsConnectParams
|
||||
import com.m57.hermescontrol.data.ws.contract.ConnectorsListParams
|
||||
import com.m57.hermescontrol.data.ws.contract.ConnectorsOperationStatusParams
|
||||
import com.m57.hermescontrol.data.ws.contract.ConnectorsPolicyGetParams
|
||||
import com.m57.hermescontrol.data.ws.contract.ConnectorsPolicySetParams
|
||||
import com.m57.hermescontrol.data.ws.contract.ConnectorsToolsParams
|
||||
import com.m57.hermescontrol.data.ws.contract.HermesRpcCaller
|
||||
import com.m57.hermescontrol.data.ws.contract.RpcMethods
|
||||
import com.m57.hermescontrol.data.ws.contract.TypedRpcCaller
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
@@ -74,6 +87,7 @@ class HermesAccountConnectorRepository(
|
||||
if (!deferred.isCompleted) deferred.cancel()
|
||||
}
|
||||
},
|
||||
private val caller: TypedRpcCaller = HermesRpcCaller,
|
||||
) : AccountConnectorRepository {
|
||||
private suspend fun request(
|
||||
method: String,
|
||||
@@ -116,10 +130,11 @@ class HermesAccountConnectorRepository(
|
||||
override suspend fun listConnectors(): com.m57.hermescontrol.data.model.ConnectorListResult =
|
||||
try {
|
||||
ConnectorParser.parseListResult(
|
||||
rpc(
|
||||
WsMethods.CONNECTORS_LIST,
|
||||
accountParams(
|
||||
mapOf("owner" to mapOf("type" to "account")),
|
||||
caller.call(
|
||||
RpcMethods.CONNECTORS_LIST,
|
||||
ConnectorsListParams(
|
||||
owner = ConnectorOwner.account(),
|
||||
profile = AuthManager.activeProfileId.value,
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -146,14 +161,13 @@ class HermesAccountConnectorRepository(
|
||||
) = guarded {
|
||||
require(slugs.isNotEmpty() && slugs.all(ConnectorRepository::isValidSlug))
|
||||
parseOperation(
|
||||
request(
|
||||
WsMethods.CONNECTORS_CONNECT,
|
||||
accountParams(
|
||||
mapOf(
|
||||
"owner" to mapOf("type" to "account"),
|
||||
"connectors" to slugs,
|
||||
"reconnect" to reconnect,
|
||||
),
|
||||
caller.call(
|
||||
RpcMethods.CONNECTORS_CONNECT,
|
||||
ConnectorsConnectParams(
|
||||
owner = ConnectorOwner.account(),
|
||||
connectors = slugs,
|
||||
reconnect = reconnect,
|
||||
profile = AuthManager.activeProfileId.value,
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -166,7 +180,16 @@ class HermesAccountConnectorRepository(
|
||||
|
||||
override suspend fun operationStatus(opId: String) =
|
||||
guarded {
|
||||
parseOperation(operationRequest(WsMethods.CONNECTORS_OPERATION_STATUS, mapOf("op_id" to opId)))
|
||||
parseOperation(
|
||||
caller.call(
|
||||
RpcMethods.CONNECTORS_OPERATION_STATUS,
|
||||
ConnectorsOperationStatusParams(
|
||||
owner = ConnectorOwner.account(),
|
||||
opId = opId,
|
||||
profile = AuthManager.activeProfileId.value,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@@ -180,7 +203,14 @@ class HermesAccountConnectorRepository(
|
||||
|
||||
override suspend fun catalog() =
|
||||
guarded {
|
||||
obj(request(WsMethods.CONNECTORS_CATALOG, accountParams()))["connectors"]!!.jsonArray.map {
|
||||
val response =
|
||||
caller.call(
|
||||
RpcMethods.CONNECTORS_CATALOG,
|
||||
ConnectorsCatalogParams(
|
||||
profile = AuthManager.activeProfileId.value,
|
||||
),
|
||||
)
|
||||
obj(response)["connectors"]!!.jsonArray.map {
|
||||
val row = it.jsonObject
|
||||
ConnectorCatalogEntry(row.str("slug"), row.str("name"), row.str("description"), row.str("category"))
|
||||
}
|
||||
@@ -188,7 +218,14 @@ class HermesAccountConnectorRepository(
|
||||
|
||||
override suspend fun accounts() =
|
||||
guarded {
|
||||
obj(request(WsMethods.CONNECTORS_ACCOUNTS, accountParams()))["accounts"]!!.jsonArray.map { e ->
|
||||
val response =
|
||||
caller.call(
|
||||
RpcMethods.CONNECTORS_ACCOUNTS,
|
||||
ConnectorsAccountsParams(
|
||||
profile = AuthManager.activeProfileId.value,
|
||||
),
|
||||
)
|
||||
obj(response)["accounts"]!!.jsonArray.map { e ->
|
||||
val r = e.jsonObject
|
||||
ConnectorAccount(
|
||||
r.str("connection_id"),
|
||||
@@ -209,10 +246,11 @@ class HermesAccountConnectorRepository(
|
||||
require(connectionId.isNotBlank())
|
||||
val response =
|
||||
obj(
|
||||
request(
|
||||
WsMethods.CONNECTORS_ACCOUNTS_REMOVE,
|
||||
accountParams(
|
||||
mapOf("connection_id" to connectionId),
|
||||
caller.call(
|
||||
RpcMethods.CONNECTORS_ACCOUNTS_REMOVE,
|
||||
ConnectorsAccountsRemoveParams(
|
||||
connectionId = connectionId,
|
||||
profile = AuthManager.activeProfileId.value,
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -225,12 +263,16 @@ class HermesAccountConnectorRepository(
|
||||
refresh: Boolean,
|
||||
) = guarded {
|
||||
require(ConnectorRepository.isValidSlug(slug))
|
||||
val params =
|
||||
buildMap<String, Any> {
|
||||
put("slug", slug)
|
||||
if (refresh) put("refresh", true)
|
||||
}
|
||||
obj(request(WsMethods.CONNECTORS_TOOLS, accountParams(params)))["tools"]!!.jsonArray.map { e ->
|
||||
val response =
|
||||
caller.call(
|
||||
RpcMethods.CONNECTORS_TOOLS,
|
||||
ConnectorsToolsParams(
|
||||
slug = slug,
|
||||
refresh = if (refresh) true else null,
|
||||
profile = AuthManager.activeProfileId.value,
|
||||
),
|
||||
)
|
||||
obj(response)["tools"]!!.jsonArray.map { e ->
|
||||
val r = e.jsonObject
|
||||
ConnectorTool(
|
||||
r.str("slug"),
|
||||
@@ -245,7 +287,15 @@ class HermesAccountConnectorRepository(
|
||||
|
||||
override suspend fun policy() =
|
||||
guarded {
|
||||
val root = obj(request(WsMethods.CONNECTORS_POLICY_GET, accountParams()))
|
||||
val root =
|
||||
obj(
|
||||
caller.call(
|
||||
RpcMethods.CONNECTORS_POLICY_GET,
|
||||
ConnectorsPolicyGetParams(
|
||||
profile = AuthManager.activeProfileId.value,
|
||||
),
|
||||
),
|
||||
)
|
||||
val layers = root.array("layers").map { it.jsonObject }
|
||||
val member = layers.firstOrNull { it.str("kind") == "member" }
|
||||
parsePolicy(root["effective"]!!.jsonObject).copy(
|
||||
@@ -293,13 +343,12 @@ class HermesAccountConnectorRepository(
|
||||
check(scope == AuthManager.currentDataScope()) { "Account scope changed" }
|
||||
val result =
|
||||
obj(
|
||||
request(
|
||||
WsMethods.CONNECTORS_POLICY_SET,
|
||||
accountParams(
|
||||
mapOf(
|
||||
"change" to change,
|
||||
"expected_revision" to expectedRevision,
|
||||
),
|
||||
caller.call(
|
||||
RpcMethods.CONNECTORS_POLICY_SET,
|
||||
ConnectorsPolicySetParams(
|
||||
change = ConnectorParser.toJsonElement(change) as JsonObject,
|
||||
expectedRevision = expectedRevision,
|
||||
profile = AuthManager.activeProfileId.value,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -3,6 +3,12 @@ package com.m57.hermescontrol.data.ws
|
||||
import com.m57.hermescontrol.data.model.ConnectorConnectResult
|
||||
import com.m57.hermescontrol.data.model.ConnectorError
|
||||
import com.m57.hermescontrol.data.model.ConnectorListResult
|
||||
import com.m57.hermescontrol.data.ws.contract.ConnectorOwner
|
||||
import com.m57.hermescontrol.data.ws.contract.ConnectorsConnectParams
|
||||
import com.m57.hermescontrol.data.ws.contract.ConnectorsListParams
|
||||
import com.m57.hermescontrol.data.ws.contract.HermesRpcCaller
|
||||
import com.m57.hermescontrol.data.ws.contract.RpcMethods
|
||||
import com.m57.hermescontrol.data.ws.contract.TypedRpcCaller
|
||||
import kotlinx.coroutines.CancellationException
|
||||
|
||||
/**
|
||||
@@ -42,19 +48,7 @@ interface ConnectorRepository {
|
||||
* Default implementation of [ConnectorRepository] backed by [HermesWsClient].
|
||||
*/
|
||||
class HermesConnectorRepository(
|
||||
private val rpcRequest: suspend (method: String, params: Map<String, Any>) -> Any? = { method, params ->
|
||||
val deferred = HermesWsClient.request(method, params)
|
||||
try {
|
||||
deferred.await()
|
||||
} catch (e: CancellationException) {
|
||||
deferred.cancel(e)
|
||||
throw e
|
||||
} finally {
|
||||
if (!deferred.isCompleted) {
|
||||
deferred.cancel()
|
||||
}
|
||||
}
|
||||
},
|
||||
private val caller: TypedRpcCaller = HermesRpcCaller,
|
||||
) : ConnectorRepository {
|
||||
override suspend fun listConnectors(sessionId: String): ConnectorListResult {
|
||||
if (sessionId.isBlank()) {
|
||||
@@ -64,8 +58,8 @@ class HermesConnectorRepository(
|
||||
}
|
||||
|
||||
return try {
|
||||
val params = mapOf("owner" to ConnectorRepository.sessionOwner(sessionId))
|
||||
val result = rpcRequest(WsMethods.CONNECTORS_LIST, params)
|
||||
val params = ConnectorsListParams(owner = ConnectorOwner.session(sessionId))
|
||||
val result = caller.call(RpcMethods.CONNECTORS_LIST, params)
|
||||
ConnectorParser.parseListResult(result)
|
||||
} catch (e: CancellationException) {
|
||||
throw e
|
||||
@@ -107,12 +101,12 @@ class HermesConnectorRepository(
|
||||
|
||||
return try {
|
||||
val params =
|
||||
mapOf(
|
||||
"owner" to ConnectorRepository.sessionOwner(sessionId),
|
||||
"connectors" to connectors,
|
||||
"reconnect" to reconnect,
|
||||
ConnectorsConnectParams(
|
||||
owner = ConnectorOwner.session(sessionId),
|
||||
connectors = connectors,
|
||||
reconnect = reconnect,
|
||||
)
|
||||
val result = rpcRequest(WsMethods.CONNECTORS_CONNECT, params)
|
||||
val result = caller.call(RpcMethods.CONNECTORS_CONNECT, params)
|
||||
ConnectorParser.parseConnectResult(result)
|
||||
} catch (e: CancellationException) {
|
||||
throw e
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.m57.hermescontrol.data.ws.contract
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
|
||||
@Serializable
|
||||
data class ConnectorOwner(
|
||||
@SerialName("type") val type: String,
|
||||
@SerialName("session_id") val sessionId: String? = null,
|
||||
) {
|
||||
companion object {
|
||||
fun account() = ConnectorOwner("account")
|
||||
|
||||
fun session(sessionId: String) = ConnectorOwner("session", sessionId)
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class ConnectorsListParams(
|
||||
@SerialName("owner") val owner: ConnectorOwner,
|
||||
@SerialName("profile") val profile: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ConnectorsConnectParams(
|
||||
@SerialName("owner") val owner: ConnectorOwner,
|
||||
@SerialName("connectors") val connectors: List<String>,
|
||||
@SerialName("reconnect") val reconnect: Boolean? = null,
|
||||
@SerialName("profile") val profile: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ConnectorsOperationStatusParams(
|
||||
@SerialName("owner") val owner: ConnectorOwner,
|
||||
@SerialName("op_id") val opId: String,
|
||||
@SerialName("profile") val profile: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ConnectorsCatalogParams(
|
||||
@SerialName("profile") val profile: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ConnectorsAccountsParams(
|
||||
@SerialName("connector") val connector: String? = null,
|
||||
@SerialName("profile") val profile: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ConnectorsAccountsRemoveParams(
|
||||
@SerialName("connection_id") val connectionId: String,
|
||||
@SerialName("profile") val profile: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ConnectorsPolicyGetParams(
|
||||
@SerialName("profile") val profile: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ConnectorsPolicySetParams(
|
||||
@SerialName("change") val change: JsonObject,
|
||||
@SerialName("expected_revision") val expectedRevision: String,
|
||||
@SerialName("profile") val profile: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ConnectorsToolsParams(
|
||||
@SerialName("slug") val slug: String,
|
||||
@SerialName("refresh") val refresh: Boolean? = null,
|
||||
@SerialName("profile") val profile: String? = null,
|
||||
)
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.m57.hermescontrol.data.ws.contract
|
||||
|
||||
import com.m57.hermescontrol.data.ws.HermesWsClient
|
||||
import com.m57.hermescontrol.data.ws.WsMethods
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
@@ -18,6 +19,20 @@ interface TypedRpcSender {
|
||||
): String
|
||||
}
|
||||
|
||||
interface TypedRpcCaller {
|
||||
suspend fun <P, R> call(
|
||||
method: RpcMethod<P, R>,
|
||||
params: P,
|
||||
): R
|
||||
}
|
||||
|
||||
object HermesRpcCaller : TypedRpcCaller {
|
||||
override suspend fun <P, R> call(
|
||||
method: RpcMethod<P, R>,
|
||||
params: P,
|
||||
): R = HermesWsClient.call(method, params)
|
||||
}
|
||||
|
||||
object RpcMethods {
|
||||
val SESSION_EVENTS_SINCE: RpcMethod<SessionEventsSinceParams, SessionEventsSinceResult> =
|
||||
RpcMethod(
|
||||
@@ -228,6 +243,78 @@ object RpcMethods {
|
||||
JsonElement.serializer(),
|
||||
)
|
||||
|
||||
// Passthrough JsonElement results: callers keep their existing legacy parsers.
|
||||
val CONNECTORS_LIST: RpcMethod<ConnectorsListParams, JsonElement> =
|
||||
RpcMethod(
|
||||
WsMethods.CONNECTORS_LIST,
|
||||
ConnectorsListParams.serializer(),
|
||||
JsonElement.serializer(),
|
||||
)
|
||||
|
||||
// Passthrough JsonElement results: callers keep their existing legacy parsers.
|
||||
val CONNECTORS_CONNECT: RpcMethod<ConnectorsConnectParams, JsonElement> =
|
||||
RpcMethod(
|
||||
WsMethods.CONNECTORS_CONNECT,
|
||||
ConnectorsConnectParams.serializer(),
|
||||
JsonElement.serializer(),
|
||||
)
|
||||
|
||||
// Passthrough JsonElement results: callers keep their existing legacy parsers.
|
||||
val CONNECTORS_OPERATION_STATUS: RpcMethod<ConnectorsOperationStatusParams, JsonElement> =
|
||||
RpcMethod(
|
||||
WsMethods.CONNECTORS_OPERATION_STATUS,
|
||||
ConnectorsOperationStatusParams.serializer(),
|
||||
JsonElement.serializer(),
|
||||
)
|
||||
|
||||
// Passthrough JsonElement results: callers keep their existing legacy parsers.
|
||||
val CONNECTORS_CATALOG: RpcMethod<ConnectorsCatalogParams, JsonElement> =
|
||||
RpcMethod(
|
||||
WsMethods.CONNECTORS_CATALOG,
|
||||
ConnectorsCatalogParams.serializer(),
|
||||
JsonElement.serializer(),
|
||||
)
|
||||
|
||||
// Passthrough JsonElement results: callers keep their existing legacy parsers.
|
||||
val CONNECTORS_ACCOUNTS: RpcMethod<ConnectorsAccountsParams, JsonElement> =
|
||||
RpcMethod(
|
||||
WsMethods.CONNECTORS_ACCOUNTS,
|
||||
ConnectorsAccountsParams.serializer(),
|
||||
JsonElement.serializer(),
|
||||
)
|
||||
|
||||
// Passthrough JsonElement results: callers keep their existing legacy parsers.
|
||||
val CONNECTORS_ACCOUNTS_REMOVE: RpcMethod<ConnectorsAccountsRemoveParams, JsonElement> =
|
||||
RpcMethod(
|
||||
WsMethods.CONNECTORS_ACCOUNTS_REMOVE,
|
||||
ConnectorsAccountsRemoveParams.serializer(),
|
||||
JsonElement.serializer(),
|
||||
)
|
||||
|
||||
// Passthrough JsonElement results: callers keep their existing legacy parsers.
|
||||
val CONNECTORS_POLICY_GET: RpcMethod<ConnectorsPolicyGetParams, JsonElement> =
|
||||
RpcMethod(
|
||||
WsMethods.CONNECTORS_POLICY_GET,
|
||||
ConnectorsPolicyGetParams.serializer(),
|
||||
JsonElement.serializer(),
|
||||
)
|
||||
|
||||
// Passthrough JsonElement results: callers keep their existing legacy parsers.
|
||||
val CONNECTORS_POLICY_SET: RpcMethod<ConnectorsPolicySetParams, JsonElement> =
|
||||
RpcMethod(
|
||||
WsMethods.CONNECTORS_POLICY_SET,
|
||||
ConnectorsPolicySetParams.serializer(),
|
||||
JsonElement.serializer(),
|
||||
)
|
||||
|
||||
// Passthrough JsonElement results: callers keep their existing legacy parsers.
|
||||
val CONNECTORS_TOOLS: RpcMethod<ConnectorsToolsParams, JsonElement> =
|
||||
RpcMethod(
|
||||
WsMethods.CONNECTORS_TOOLS,
|
||||
ConnectorsToolsParams.serializer(),
|
||||
JsonElement.serializer(),
|
||||
)
|
||||
|
||||
/** Every typed method. GatewayContractTest iterates this; future migrations append here. */
|
||||
val all: List<RpcMethod<*, *>> =
|
||||
listOf(
|
||||
@@ -260,5 +347,14 @@ object RpcMethods {
|
||||
VAULT_SOURCE_SET,
|
||||
VAULT_UNLOCK,
|
||||
VAULT_LOCK,
|
||||
CONNECTORS_LIST,
|
||||
CONNECTORS_CONNECT,
|
||||
CONNECTORS_OPERATION_STATUS,
|
||||
CONNECTORS_CATALOG,
|
||||
CONNECTORS_ACCOUNTS,
|
||||
CONNECTORS_ACCOUNTS_REMOVE,
|
||||
CONNECTORS_POLICY_GET,
|
||||
CONNECTORS_POLICY_SET,
|
||||
CONNECTORS_TOOLS,
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user