1use trellis_client::{TrellisClient, UserConnectOptions};
2use trellis_sdk_auth::{
3 AuthClient as AuthApiClient, ListApprovalsRequest, RenewBindingTokenResponse,
4 RevokeApprovalRequest,
5};
6use crate::{
7 save_admin_session, AdminSessionState, ApprovalEntryRecord, AuthenticatedUser,
8 BoundSession, ServiceListEntry, TrellisAuthError,
9};
10
11pub async fn connect_admin_client_async(
13 state: &AdminSessionState,
14) -> Result<TrellisClient, TrellisAuthError> {
15 Ok(TrellisClient::connect_user(UserConnectOptions {
16 servers: &state.nats_servers,
17 sentinel_jwt: &state.sentinel_jwt,
18 sentinel_seed: &state.sentinel_seed,
19 session_key_seed_base64url: &state.session_seed,
20 binding_token: &state.binding_token,
21 timeout_ms: 5_000,
22 })
23 .await?)
24}
25
26pub fn persist_renewed_admin_session(
28 state: &mut AdminSessionState,
29 renewed: RenewBindingTokenResponse,
30) -> Result<(), TrellisAuthError> {
31 let renewed = BoundSession {
32 binding_token: renewed.binding_token,
33 inbox_prefix: renewed.inbox_prefix,
34 expires: renewed.expires,
35 sentinel: renewed.sentinel,
36 };
37
38 state.binding_token = renewed.binding_token;
39 state.expires = renewed.expires;
40 state.sentinel_jwt = renewed.sentinel.jwt;
41 state.sentinel_seed = renewed.sentinel.seed;
42 save_admin_session(state)
43}
44
45pub struct AuthClient<'a> {
47 inner: AuthApiClient<'a>,
48}
49
50impl<'a> AuthClient<'a> {
51 pub fn new(inner: &'a TrellisClient) -> Self {
53 Self {
54 inner: AuthApiClient::new(inner),
55 }
56 }
57
58 pub async fn me(&self) -> Result<AuthenticatedUser, TrellisAuthError> {
60 Ok(self.inner.auth_me().await?.user)
61 }
62
63 pub async fn list_approvals(
65 &self,
66 user: Option<&str>,
67 digest: Option<&str>,
68 ) -> Result<Vec<ApprovalEntryRecord>, TrellisAuthError> {
69 let request = ListApprovalsRequest {
70 user: user.map(ToOwned::to_owned),
71 digest: digest.map(ToOwned::to_owned),
72 };
73 Ok(self.inner.auth_list_approvals(&request).await?.approvals)
74 }
75
76 pub async fn revoke_approval(
78 &self,
79 digest: &str,
80 user: Option<&str>,
81 ) -> Result<bool, TrellisAuthError> {
82 let request = RevokeApprovalRequest {
83 contract_digest: digest.to_string(),
84 user: user.map(ToOwned::to_owned),
85 };
86 Ok(self.inner.auth_revoke_approval(&request).await?.success)
87 }
88
89 pub async fn list_services(&self) -> Result<Vec<ServiceListEntry>, TrellisAuthError> {
91 Ok(self.inner.auth_list_services().await?.services)
92 }
93
94 pub async fn logout(&self) -> Result<bool, TrellisAuthError> {
96 Ok(self.inner.auth_logout().await?.success)
97 }
98
99 pub async fn renew_binding_token(
101 &self,
102 state: &mut AdminSessionState,
103 ) -> Result<(), TrellisAuthError> {
104 persist_renewed_admin_session(state, self.inner.auth_renew_binding_token().await?)
105 }
106}