claude_code_toolkit/providers/
registry.rs1use super::ProviderFactory;
4use crate::error::Result;
5use crate::traits::{
6 Credentials,
7 SecretManager,
8 SecretMapping,
9 SecretProvider,
10 SyncResult,
11 Target,
12};
13use async_trait::async_trait;
14use std::collections::HashMap;
15use tracing::{ error, info, warn };
16
17pub struct ProviderRegistry {
19 factory: ProviderFactory,
20 providers: HashMap<String, Box<dyn SecretProvider>>,
21}
22
23impl ProviderRegistry {
24 pub fn new() -> Self {
25 Self {
26 factory: ProviderFactory::new(),
27 providers: HashMap::new(),
28 }
29 }
30
31 pub async fn initialize_provider(
33 &mut self,
34 name: &str,
35 config: HashMap<String, String>
36 ) -> Result<()> {
37 let provider = self.factory.create(name, &config)?;
38
39 if !provider.is_configured().await? {
41 warn!("Provider {} is not properly configured", name);
42 return Err(
43 crate::error::ClaudeCodeError::Generic(format!("Provider {} is not configured", name))
44 );
45 }
46
47 info!("Initialized provider: {}", name);
48 self.providers.insert(name.to_string(), provider);
49 Ok(())
50 }
51
52 pub async fn get_all_targets(&self) -> Result<HashMap<String, Vec<Target>>> {
54 let mut all_targets = HashMap::new();
55
56 for (provider_name, provider) in &self.providers {
57 let mut provider_targets = Vec::new();
58
59 if let Ok(orgs) = provider.list_targets("organization").await {
61 for org in orgs {
62 provider_targets.push(Target {
63 provider: provider_name.clone(),
64 target_type: "organization".to_string(),
65 name: org,
66 config: HashMap::new(),
67 });
68 }
69 }
70
71 if let Ok(repos) = provider.list_targets("repository").await {
73 for repo in repos {
74 provider_targets.push(Target {
75 provider: provider_name.clone(),
76 target_type: "repository".to_string(),
77 name: repo,
78 config: HashMap::new(),
79 });
80 }
81 }
82
83 all_targets.insert(provider_name.clone(), provider_targets);
84 }
85
86 Ok(all_targets)
87 }
88}
89
90impl Default for ProviderRegistry {
91 fn default() -> Self {
92 Self::new()
93 }
94}
95
96#[async_trait]
97impl SecretManager for ProviderRegistry {
98 fn register_provider(&mut self, provider: Box<dyn SecretProvider>) {
99 let name = provider.provider_name().to_string();
100 info!("Registering provider: {}", name);
101 self.providers.insert(name, provider);
102 }
103
104 fn get_provider(&self, name: &str) -> Option<&dyn SecretProvider> {
105 self.providers.get(name).map(|p| p.as_ref())
106 }
107
108 async fn sync_credentials(
109 &self,
110 credentials: &Credentials,
111 mapping: &SecretMapping
112 ) -> Result<SyncResult> {
113 let targets = Vec::new();
115 self.sync_credentials_to_targets(credentials, mapping, &targets).await
116 }
117
118 async fn sync_credentials_to_targets(
119 &self,
120 credentials: &Credentials,
121 mapping: &SecretMapping,
122 targets: &[Target]
123 ) -> Result<SyncResult> {
124 let secrets = mapping.to_secrets(credentials);
125 let mut total_result = SyncResult {
126 succeeded: 0,
127 failed: 0,
128 errors: Vec::new(),
129 };
130
131 for (provider_name, provider) in &self.providers {
132 match provider.sync_secrets(&secrets, targets).await {
133 Ok(result) => {
134 total_result.succeeded += result.succeeded;
135 total_result.failed += result.failed;
136 total_result.errors.extend(result.errors);
137 }
138 Err(e) => {
139 error!("Provider {} sync failed: {}", provider_name, e);
140 total_result.failed += 1;
141 total_result.errors.push(format!("Provider {}: {}", provider_name, e));
142 }
143 }
144 }
145
146 info!("Sync completed: {} succeeded, {} failed", total_result.succeeded, total_result.failed);
147
148 Ok(total_result)
149 }
150
151 async fn validate_targets(&self) -> Result<HashMap<String, bool>> {
152 let mut all_results = HashMap::new();
153
154 for (provider_name, provider) in &self.providers {
155 let targets = Vec::new();
157
158 match provider.validate_access(&targets).await {
159 Ok(results) => {
160 for (target, valid) in results {
161 all_results.insert(format!("{}:{}", provider_name, target), valid);
162 }
163 }
164 Err(e) => {
165 warn!("Failed to validate targets for provider {}: {}", provider_name, e);
166 }
167 }
168 }
169
170 Ok(all_results)
171 }
172
173 fn list_providers(&self) -> Vec<&str> {
174 self.providers
175 .keys()
176 .map(|s| s.as_str())
177 .collect()
178 }
179}