feat(config): 在加密导出/导入中包含个人访问令牌

This commit is contained in:
2026-03-23 17:59:23 +08:00
parent 0c7d2ad518
commit 8dd9e85b77
7 changed files with 787 additions and 48 deletions

View File

@@ -177,31 +177,82 @@ impl ConfigManager {
// Token management
/// Add a token to a profile
/// Add a token to a profile (stores token in keyring)
pub fn add_token_to_profile(&mut self, profile_name: &str, service: String, token: TokenConfig) -> Result<()> {
if !self.config.profiles.contains_key(profile_name) {
bail!("Profile '{}' does not exist", profile_name);
}
if let Some(profile) = self.config.profiles.get_mut(profile_name) {
profile.add_token(service, token);
self.modified = true;
Ok(())
}
Ok(())
}
/// Store a PAT token in keyring for a profile
pub fn store_pat_for_profile(&self, profile_name: &str, service: &str, token_value: &str) -> Result<()> {
let profile = self.get_profile(profile_name)
.ok_or_else(|| anyhow::anyhow!("Profile '{}' not found", profile_name))?;
let user_email = &profile.user_email;
self.keyring.store_pat(profile_name, user_email, service, token_value)
}
/// Get a PAT token from keyring for a profile
pub fn get_pat_for_profile(&self, profile_name: &str, service: &str) -> Result<Option<String>> {
let profile = self.get_profile(profile_name)
.ok_or_else(|| anyhow::anyhow!("Profile '{}' not found", profile_name))?;
let user_email = &profile.user_email;
self.keyring.get_pat(profile_name, user_email, service)
}
/// Check if a PAT token exists for a profile
pub fn has_pat_for_profile(&self, profile_name: &str, service: &str) -> bool {
if let Some(profile) = self.get_profile(profile_name) {
let user_email = &profile.user_email;
self.keyring.has_pat(profile_name, user_email, service)
} else {
bail!("Profile '{}' does not exist", profile_name);
false
}
}
// /// Get a token from a profile
// pub fn get_token_from_profile(&self, profile_name: &str, service: &str) -> Option<&TokenConfig> {
// self.config.profiles.get(profile_name)?.get_token(service)
// }
/// Remove a token from a profile
/// Remove a token from a profile (deletes from keyring)
pub fn remove_token_from_profile(&mut self, profile_name: &str, service: &str) -> Result<()> {
if !self.config.profiles.contains_key(profile_name) {
bail!("Profile '{}' does not exist", profile_name);
}
let user_email = self.config.profiles.get(profile_name).unwrap().user_email.clone();
let services: Vec<String> = self.config.profiles.get(profile_name).unwrap().tokens.keys().cloned().collect();
if !services.contains(&service.to_string()) {
bail!("Token for service '{}' not found in profile '{}'", service, profile_name);
}
self.keyring.delete_pat(profile_name, &user_email, service)?;
if let Some(profile) = self.config.profiles.get_mut(profile_name) {
profile.remove_token(service);
self.modified = true;
Ok(())
} else {
bail!("Profile '{}' does not exist", profile_name);
}
Ok(())
}
/// Delete all PAT tokens for a profile (used when removing a profile)
pub fn delete_all_pats_for_profile(&self, profile_name: &str) -> Result<()> {
if let Some(profile) = self.get_profile(profile_name) {
let user_email = &profile.user_email;
let services: Vec<String> = profile.tokens.keys().cloned().collect();
self.keyring.delete_all_pats_for_profile(profile_name, user_email, &services)?;
}
Ok(())
}
// /// List all tokens in a profile
@@ -257,6 +308,37 @@ impl ConfigManager {
profile.compare_with_git_config(repo)
}
/// Find a profile that matches the given user config (name, email, signing_key)
pub fn find_matching_profile(&self, user_name: &str, user_email: &str, signing_key: Option<&str>) -> Option<&GitProfile> {
for profile in self.config.profiles.values() {
let name_match = profile.user_name == user_name;
let email_match = profile.user_email == user_email;
let key_match = match (signing_key, profile.signing_key()) {
(Some(git_key), Some(profile_key)) => git_key == profile_key,
(None, None) => true,
(Some(_), None) => false,
(None, Some(_)) => false,
};
if name_match && email_match && key_match {
return Some(profile);
}
}
None
}
/// Find profiles that partially match (same name or same email)
pub fn find_partial_matches(&self, user_name: &str, user_email: &str) -> Vec<&GitProfile> {
self.config.profiles.values()
.filter(|p| p.user_name == user_name || p.user_email == user_email)
.collect()
}
/// Get repo profile mapping
pub fn get_repo_profile_name(&self, repo_path: &str) -> Option<&String> {
self.config.repo_profiles.get(repo_path)
}
// LLM configuration
/// Get LLM provider