feat(useragent): add SDK clients table screen

This commit is contained in:
hdbg
2026-03-22 13:07:14 +01:00
parent 4ebe7b6fc4
commit d9b3694cab
26 changed files with 1977 additions and 1402 deletions

View File

@@ -25,6 +25,19 @@ pub enum Error {
Internal { message: Cow<'static, str> },
}
impl From<crate::db::PoolError> for Error {
fn from(err: crate::db::PoolError) -> Self {
error!(?err, "Database pool error");
Self::internal("Database pool error")
}
}
impl From<diesel::result::Error> for Error {
fn from(err: diesel::result::Error) -> Self {
error!(?err, "Database error");
Self::internal("Database error")
}
}
impl Error {
pub fn internal(message: impl Into<Cow<'static, str>>) -> Self {
Self::Internal {
@@ -49,7 +62,7 @@ mod connection;
pub(crate) use connection::{
BootstrapError, HandleBootstrapEncryptedKey, HandleEvmWalletCreate, HandleEvmWalletList,
HandleGrantCreate, HandleGrantDelete, HandleGrantList, HandleNewClientApprove,
HandleQueryVaultState,
HandleQueryVaultState, HandleSdkClientList,
};
pub use connection::{HandleUnsealEncryptedKey, HandleUnsealRequest, UnsealError};

View File

@@ -2,15 +2,18 @@ use std::sync::Mutex;
use alloy::primitives::Address;
use chacha20poly1305::{AeadInPlace, XChaCha20Poly1305, XNonce, aead::KeyInit};
use diesel::{QueryDsl as _, SelectableHelper};
use diesel_async::RunQueryDsl;
use kameo::error::SendError;
use kameo::messages;
use kameo::prelude::Context;
use kameo::{message, messages};
use tracing::{error, info};
use x25519_dalek::{EphemeralSecret, PublicKey};
use crate::actors::flow_coordinator::client_connect_approval::ClientApprovalAnswer;
use crate::actors::keyholder::KeyHolderState;
use crate::actors::user_agent::session::Error;
use crate::db::models::{ProgramClient, ProgramClientMetadata};
use crate::evm::policies::{Grant, SpecificGrant};
use crate::safe_cell::SafeCell;
use crate::{
@@ -383,4 +386,20 @@ impl UserAgentSession {
Ok(())
}
}
#[message]
pub(crate) async fn handle_sdk_client_list(
&mut self,
) -> Result<Vec<(ProgramClient, ProgramClientMetadata)>, Error> {
use crate::db::schema::{program_client, client_metadata};
let mut conn = self.props.db.get().await?;
let clients = program_client::table
.inner_join(client_metadata::table)
.select((ProgramClient::as_select(), ProgramClientMetadata::as_select()))
.load::<(ProgramClient, ProgramClientMetadata)>(&mut conn)
.await?;
Ok(clients)
}
}

View File

@@ -21,10 +21,14 @@ use arbiter_proto::{
user_agent::{
BootstrapEncryptedKey as ProtoBootstrapEncryptedKey,
BootstrapResult as ProtoBootstrapResult,
SdkClientEntry as ProtoSdkClientEntry, SdkClientError as ProtoSdkClientError,
SdkClientConnectionCancel as ProtoSdkClientConnectionCancel,
SdkClientConnectionRequest as ProtoSdkClientConnectionRequest,
SdkClientList as ProtoSdkClientList,
SdkClientListResponse as ProtoSdkClientListResponse,
UnsealEncryptedKey as ProtoUnsealEncryptedKey, UnsealResult as ProtoUnsealResult,
UnsealStart, UserAgentRequest, UserAgentResponse, VaultState as ProtoVaultState,
sdk_client_list_response::Result as ProtoSdkClientListResult,
user_agent_request::Payload as UserAgentRequestPayload,
user_agent_response::Payload as UserAgentResponsePayload,
},
@@ -49,7 +53,8 @@ use crate::{
session::{
BootstrapError, Error, HandleBootstrapEncryptedKey, HandleEvmWalletCreate,
HandleEvmWalletList, HandleGrantCreate, HandleGrantDelete, HandleGrantList,
HandleNewClientApprove, HandleQueryVaultState, HandleUnsealEncryptedKey,
HandleNewClientApprove, HandleQueryVaultState, HandleSdkClientList,
HandleUnsealEncryptedKey,
HandleUnsealRequest, UnsealError,
},
},
@@ -303,7 +308,11 @@ async fn dispatch_conn_message(
return Ok(());
}
UserAgentRequestPayload::SdkClientRevoke(_sdk_client_revoke_request) => todo!(),
UserAgentRequestPayload::SdkClientList(_) => todo!(),
UserAgentRequestPayload::SdkClientList(_) => {
UserAgentResponsePayload::SdkClientListResponse(
SdkClient::list_response(actor.ask(HandleSdkClientList {}).await),
)
},
UserAgentRequestPayload::AuthChallengeRequest(..)
| UserAgentRequestPayload::AuthChallengeSolution(..) => {
warn!(?payload, "Unsupported post-auth user agent request");
@@ -355,6 +364,43 @@ async fn send_out_of_band(
.map_err(|_| ())
}
struct SdkClient;
impl SdkClient {
fn list_response<M>(
result: Result<
Vec<(crate::db::models::ProgramClient, crate::db::models::ProgramClientMetadata)>,
SendError<M, Error>,
>,
) -> ProtoSdkClientListResponse {
let result = match result {
Ok(clients) => ProtoSdkClientListResult::Clients(ProtoSdkClientList {
clients: clients
.into_iter()
.map(|(client, metadata)| ProtoSdkClientEntry {
id: client.id,
pubkey: client.public_key,
info: Some(ProtoClientMetadata {
name: metadata.name,
description: metadata.description,
version: metadata.version,
}),
created_at: client.created_at.0.timestamp() as i32,
})
.collect(),
}),
Err(err) => {
warn!(error = ?err, "Failed to list SDK clients");
ProtoSdkClientListResult::Error(ProtoSdkClientError::Internal.into())
}
};
ProtoSdkClientListResponse {
result: Some(result),
}
}
}
fn parse_grant_request(
shared: Option<ProtoSharedSettings>,
specific: Option<ProtoSpecificGrant>,