1#![cfg(feature = "client")]
14
15use std::any::Any;
16
17use anyhow::{Result, anyhow};
18use async_trait::async_trait;
19use weft_client_shim::{CliContext, WeftExtensions};
20
21use crate::{
22 cli::{AgentTemplateArg, AuthCommands, AuthTrustCommands, commands::cmd_auth},
23 hosted_runtime::{
24 auth_requests::{AuthCommand, AuthTrustCommand},
25 device_flow::AgentTemplate,
26 },
27};
28
29pub struct EnabledWeftExtensions;
30
31#[async_trait]
32impl WeftExtensions for EnabledWeftExtensions {
33 async fn auth(
34 &self,
35 ctx: &(dyn CliContext + 'static),
36 command: &(dyn Any + Send + Sync),
37 ) -> Result<()> {
38 let command = downcast::<AuthCommands>(command, "AuthCommands")?;
39 cmd_auth(ctx, auth_command(command.clone())).await
40 }
41
42 async fn whoami(&self, ctx: &(dyn CliContext + 'static), server: Option<String>) -> Result<()> {
43 crate::hosted_runtime::whoami::cmd_whoami(ctx, server).await
44 }
45}
46
47fn auth_command(command: AuthCommands) -> AuthCommand {
48 match command {
49 AuthCommands::Login {
50 server,
51 open_browser,
52 credential,
53 } => AuthCommand::Login {
54 server,
55 open_browser,
56 credential,
57 },
58 AuthCommands::Logout { server } => AuthCommand::Logout { server },
59 AuthCommands::Status { server } => AuthCommand::Status { server },
60 AuthCommands::Trust { command } => AuthCommand::Trust {
61 command: match command {
62 AuthTrustCommands::Show(args) => AuthTrustCommand::Show {
63 server: args.server,
64 },
65 AuthTrustCommands::Replace(args) => AuthTrustCommand::Replace {
66 server: args.server,
67 expected_current_public_key: args.expect_current_public_key,
68 key_id: args.key_id,
69 public_key: args.public_key,
70 },
71 },
72 },
73 AuthCommands::DeriveAgent {
74 server,
75 agent_id,
76 ttl_secs,
77 scopes,
78 allowed_operations,
79 template,
80 out,
81 } => AuthCommand::DeriveAgent {
82 server,
83 agent_id,
84 ttl_secs,
85 scopes,
86 allowed_operations,
87 template: template.map(agent_template),
88 out,
89 },
90 AuthCommands::CreateServiceToken {
91 name,
92 namespace,
93 server,
94 out,
95 } => AuthCommand::CreateServiceToken {
96 name,
97 namespace,
98 server,
99 out,
100 },
101 }
102}
103
104fn agent_template(template: AgentTemplateArg) -> AgentTemplate {
105 match template {
106 AgentTemplateArg::Reviewer => AgentTemplate::Reviewer,
107 AgentTemplateArg::Contributor => AgentTemplate::Contributor,
108 AgentTemplateArg::CiLanding => AgentTemplate::CiLanding,
109 }
110}
111
112fn downcast<'a, T: 'static>(
113 value: &'a (dyn Any + Send + Sync),
114 name: &'static str,
115) -> Result<&'a T> {
116 value
117 .downcast_ref::<T>()
118 .ok_or_else(|| anyhow!("WeftExtensions trait dispatch: failed to downcast to {name}"))
119}