Function bodies 391 total
put_secret_value function · rust · L72-L79 (8 LOC)src/providers/gcp_sm.rs
async fn put_secret_value(&self, _secret_id: &str, _secret_value: &str) -> Result<()> {
Err(FnoxError::ProviderApiError {
provider: "GCP Secret Manager".to_string(),
details: "put_secret not yet implemented".to_string(),
hint: "Contributions welcome to implement payload data setting".to_string(),
url: URL.to_string(),
})
}get_secret function · rust · L87-L140 (54 LOC)src/providers/gcp_sm.rs
async fn get_secret(&self, value: &str) -> Result<String> {
let client = self.create_client().await?;
let secret_name = self.build_secret_name(value);
let response = client
.access_secret_version()
.set_name(secret_name)
.send()
.await
.map_err(|e| {
let err_str = e.to_string();
if err_str.contains("NOT_FOUND") || err_str.contains("not found") {
FnoxError::ProviderSecretNotFound {
provider: "GCP Secret Manager".to_string(),
secret: value.to_string(),
hint: "Check that the secret exists in the GCP project".to_string(),
url: URL.to_string(),
}
} else if err_str.contains("PERMISSION_DENIED") || err_str.contains("permission") {
FnoxError::ProviderAuthFailed {
provider: "GCP Sectest_connection function · rust · L141-L174 (34 LOC)src/providers/gcp_sm.rs
async fn test_connection(&self) -> Result<()> {
let client = self.create_client().await?;
// Try to list secrets to verify access
client
.list_secrets()
.set_parent(format!("projects/{}", self.project))
.send()
.await
.map_err(|e| {
let err_str = e.to_string();
if err_str.contains("PERMISSION_DENIED") || err_str.contains("permission") {
FnoxError::ProviderAuthFailed {
provider: "GCP Secret Manager".to_string(),
details: err_str,
hint: "Check IAM permissions for secretmanager.secrets.list".to_string(),
url: URL.to_string(),
}
} else {
FnoxError::ProviderApiError {
provider: "GCP Secret Manager".to_string(),
details: format!(
put_secret function · rust · L175-L181 (7 LOC)src/providers/gcp_sm.rs
async fn put_secret(&self, key: &str, value: &str) -> Result<String> {
let secret_id = self.get_secret_id(key);
self.put_secret_value(&secret_id, value).await?;
// Return the key name (without prefix) to store in config
Ok(key.to_string())
}new function · rust · L15-L25 (11 LOC)src/providers/infisical.rs
pub fn new(
project_id: Option<String>,
environment: Option<String>,
path: Option<String>,
) -> Self {
Self {
project_id,
environment,
path,
}
}execute_infisical_command function · rust · L140-L203 (64 LOC)src/providers/infisical.rs
fn execute_infisical_command(&self, args: &[&str]) -> Result<String> {
tracing::debug!("Executing infisical command with args: {:?}", args);
let token = self.get_auth_token()?;
let mut cmd = Command::new("infisical");
cmd.args(args);
// Add authentication token
cmd.arg("--token");
cmd.arg(&token);
// Add custom domain if specified, stripping /api suffix if present
// The CLI's --domain flag expects base URL (some commands append /api automatically)
if let Some(api_url) = infisical_api_url() {
let base_url = api_url.trim_end_matches("/api").trim_end_matches('/');
cmd.arg("--domain");
cmd.arg(base_url);
}
// Add silent flag to reduce noise
cmd.arg("--silent");
cmd.stdin(std::process::Stdio::null());
let output = cmd.output().map_err(|e| {
if e.kind() == std::io::ErrorKind::NotFound {
FnoxError::Pget_secret function · rust · L207-L289 (83 LOC)src/providers/infisical.rs
async fn get_secret(&self, value: &str) -> Result<String> {
tracing::debug!("Getting secret '{}' from Infisical", value);
// Build the command: infisical secrets get <name> --output json
// Using JSON format allows us to distinguish between "not found" and "empty value"
let mut args = vec!["secrets", "get", value, "--output", "json"];
// Add project ID if specified
let project_arg;
if let Some(ref project_id) = self.project_id {
project_arg = format!("--projectId={}", project_id);
args.push(&project_arg);
}
// Add environment if specified (otherwise CLI uses its default: "dev")
let env_arg;
if let Some(ref environment) = self.environment {
env_arg = format!("--env={}", environment);
args.push(&env_arg);
}
// Add path if specified (otherwise CLI uses its default: "/")
let path_arg;
if let Some(ref path) = self.patWant this analysis on your repo? https://repobility.com/scan/
test_connection function · rust · L414-L424 (11 LOC)src/providers/infisical.rs
async fn test_connection(&self) -> Result<()> {
tracing::debug!("Testing connection to Infisical");
// Try to authenticate and get a token
let _token = self.get_auth_token()?;
tracing::debug!("Infisical connection test successful");
Ok(())
}env_dependencies function · rust · L426-L438 (13 LOC)src/providers/infisical.rs
pub fn env_dependencies() -> &'static [&'static str] {
&[
"INFISICAL_TOKEN",
"FNOX_INFISICAL_TOKEN",
"INFISICAL_CLIENT_ID",
"FNOX_INFISICAL_CLIENT_ID",
"INFISICAL_CLIENT_SECRET",
"FNOX_INFISICAL_CLIENT_SECRET",
"INFISICAL_API_URL",
"FNOX_INFISICAL_API_URL",
]
}infisical_token function · rust · L439-L444 (6 LOC)src/providers/infisical.rs
fn infisical_token() -> Option<String> {
env::var("FNOX_INFISICAL_TOKEN")
.or_else(|_| env::var("INFISICAL_TOKEN"))
.ok()
}infisical_client_id function · rust · L445-L450 (6 LOC)src/providers/infisical.rs
fn infisical_client_id() -> Option<String> {
env::var("FNOX_INFISICAL_CLIENT_ID")
.or_else(|_| env::var("INFISICAL_CLIENT_ID"))
.ok()
}infisical_client_secret function · rust · L451-L456 (6 LOC)src/providers/infisical.rs
fn infisical_client_secret() -> Option<String> {
env::var("FNOX_INFISICAL_CLIENT_SECRET")
.or_else(|_| env::var("INFISICAL_CLIENT_SECRET"))
.ok()
}infisical_api_url function · rust · L457-L462 (6 LOC)src/providers/infisical.rs
fn infisical_api_url() -> Option<String> {
env::var("FNOX_INFISICAL_API_URL")
.or_else(|_| env::var("INFISICAL_API_URL"))
.ok()
}new function · rust · L19-L25 (7 LOC)src/providers/keepass.rs
pub fn new(database: String, keyfile: Option<String>, password: Option<String>) -> Self {
Self {
database_path: PathBuf::from(shellexpand::tilde(&database).to_string()),
keyfile_path: keyfile.map(|k| PathBuf::from(shellexpand::tilde(&k).to_string())),
password,
}
}get_password function · rust · L28-L117 (90 LOC)src/providers/keepass.rs
fn get_password(&self) -> Result<String> {
// Priority: env var > config
if let Some(password) = keepass_password() {
return Ok(password);
}
if let Some(password) = &self.password {
return Ok(password.clone());
}
Err(FnoxError::ProviderAuthFailed {
provider: "KeePass".to_string(),
details: "Database password not set".to_string(),
hint: "Set FNOX_KEEPASS_PASSWORD or KEEPASS_PASSWORD environment variable, or configure password in provider config".to_string(),
url: "https://fnox.jdx.dev/providers/keepass".to_string(),
})
}
/// Build the database key from password and optional keyfile
fn build_key(&self) -> Result<DatabaseKey> {
let password = self.get_password()?;
let mut key = DatabaseKey::new();
// Add password
key = key.with_password(&password);
// Add keyfile if configured
if let Some(keyfilRepobility · open methodology · https://repobility.com/research/
build_key function · rust · L47-L74 (28 LOC)src/providers/keepass.rs
fn build_key(&self) -> Result<DatabaseKey> {
let password = self.get_password()?;
let mut key = DatabaseKey::new();
// Add password
key = key.with_password(&password);
// Add keyfile if configured
if let Some(keyfile_path) = &self.keyfile_path {
let mut keyfile =
File::open(keyfile_path).map_err(|e| FnoxError::ProviderApiError {
provider: "KeePass".to_string(),
details: format!("Failed to open keyfile '{}': {}", keyfile_path.display(), e),
hint: "Check that the keyfile exists and is readable".to_string(),
url: "https://fnox.jdx.dev/providers/keepass".to_string(),
})?;
key = key
.with_keyfile(&mut keyfile)
.map_err(|e| FnoxError::ProviderApiError {
provider: "KeePass".to_string(),
details: format!("Failed to read keyfile: {}", e)open_database function · rust · L77-L97 (21 LOC)src/providers/keepass.rs
fn open_database(&self) -> Result<Database> {
let file = File::open(&self.database_path).map_err(|e| FnoxError::ProviderApiError {
provider: "KeePass".to_string(),
details: format!(
"Failed to open database '{}': {}",
self.database_path.display(),
e
),
hint: "Check that the database file exists and is readable".to_string(),
url: "https://fnox.jdx.dev/providers/keepass".to_string(),
})?;
let mut reader = BufReader::new(file);
let key = self.build_key()?;
Database::open(&mut reader, key).map_err(|e| FnoxError::ProviderAuthFailed {
provider: "KeePass".to_string(),
details: format!("Failed to decrypt database: {}", e),
hint: "Check that the password and/or keyfile are correct".to_string(),
url: "https://fnox.jdx.dev/providers/keepass".to_string(),
})
}parse_reference function · rust · L198-L225 (28 LOC)src/providers/keepass.rs
fn parse_reference(value: &str) -> (Vec<&str>, &str) {
let parts: Vec<&str> = value.split('/').collect();
// Known field names (case-insensitive check, but return proper casing)
let known_fields = ["password", "username", "url", "notes", "title"];
if parts.len() == 1 {
// Just entry name, default to password
(parts, "Password")
} else {
// Check if the last part is a known field
let last = parts.last().unwrap().to_lowercase();
if known_fields.contains(&last.as_str()) {
let field = match last.as_str() {
"password" => "Password",
"username" => "UserName",
"url" => "URL",
"notes" => "Notes",
"title" => "Title",
_ => "Password",
};
(parts[..parts.len() - 1].to_vec(), field)
} else {
// Last pafind_entry function · rust · L230-L249 (20 LOC)src/providers/keepass.rs
fn find_entry<'a>(group: &'a Group, path: &[&str]) -> Option<&'a Entry> {
if path.is_empty() {
return None;
}
if path.len() == 1 {
// Search for entry by title in this group and all subgroups
let entry_name = path[0];
Self::find_entry_by_title(group, entry_name)
} else {
// Navigate to subgroup first
let group_name = path[0];
for subgroup in &group.groups {
if subgroup.name == group_name {
return Self::find_entry(subgroup, &path[1..]);
}
}
None
}
}find_entry_by_title function · rust · L252-L264 (13 LOC)src/providers/keepass.rs
fn find_entry_by_title<'a>(group: &'a Group, title: &str) -> Option<&'a Entry> {
for entry in &group.entries {
if entry.get_title() == Some(title) {
return Some(entry);
}
}
for subgroup in &group.groups {
if let Some(entry) = Self::find_entry_by_title(subgroup, title) {
return Some(entry);
}
}
None
}find_entry_by_title_mut function · rust · L267-L289 (23 LOC)src/providers/keepass.rs
fn find_entry_by_title_mut<'a>(group: &'a mut Group, title: &str) -> Option<&'a mut Entry> {
// First check if entry is in this group's direct entries
let found_entry_idx = group
.entries
.iter()
.position(|e| e.get_title() == Some(title));
if let Some(idx) = found_entry_idx {
return Some(&mut group.entries[idx]);
}
// Check subgroups
let found_in_subgroup_idx = group
.groups
.iter()
.position(|sg| Self::find_entry_by_title(sg, title).is_some());
if let Some(idx) = found_in_subgroup_idx {
return Self::find_entry_by_title_mut(&mut group.groups[idx], title);
}
None
}find_or_create_entry function · rust · L293-L362 (70 LOC)src/providers/keepass.rs
fn find_or_create_entry(
group: &mut Group,
path: &[&str],
value: &str,
field: &str,
) -> Result<String> {
if path.is_empty() {
return Err(FnoxError::ProviderInvalidResponse {
provider: "KeePass".to_string(),
details: "Empty path for entry".to_string(),
hint: "Provide an entry name or path".to_string(),
url: "https://fnox.jdx.dev/providers/keepass".to_string(),
});
}
// Reject writing to Title field as it's used for entry lookups
if field == "Title" {
return Err(FnoxError::ProviderInvalidResponse {
provider: "KeePass".to_string(),
details: "Cannot write to 'Title' field".to_string(),
hint: "The 'Title' field is used for entry identification. Use a different field name.".to_string(),
url: "https://fnox.jdx.dev/providers/keepass".to_string(),
put_secret function · rust · L406-L443 (38 LOC)src/providers/keepass.rs
async fn put_secret(&self, key: &str, value: &str) -> Result<String> {
// Parse the key to determine entry path and field
let (entry_path, field) = Self::parse_reference(key);
tracing::debug!(
"Storing KeePass secret '{}' field '{}' in '{}'",
entry_path.join("/"),
field,
self.database_path.display()
);
// Check if database exists; if not, create a new one
let mut db = if self.database_path.exists() {
self.open_database()?
} else {
// Create new KDBX4 database
tracing::info!(
"Creating new KeePass database at '{}'",
self.database_path.display()
);
Database::new(keepass::config::DatabaseConfig::default())
};
// Find or create the entry
let entry_name = Self::find_or_create_entry(&mut db.root, &entry_path, value, field)?;
// Save the database
self.Same scanner, your repo: https://repobility.com — Repobility
test_parse_reference_with_field function · rust · L505-L521 (17 LOC)src/providers/keepass.rs
fn test_parse_reference_with_field() {
let (path, field) = KeePassProvider::parse_reference("my-entry/username");
assert_eq!(path, vec!["my-entry"]);
assert_eq!(field, "UserName");
let (path, field) = KeePassProvider::parse_reference("my-entry/password");
assert_eq!(path, vec!["my-entry"]);
assert_eq!(field, "Password");
let (path, field) = KeePassProvider::parse_reference("my-entry/url");
assert_eq!(path, vec!["my-entry"]);
assert_eq!(field, "URL");
let (path, field) = KeePassProvider::parse_reference("my-entry/notes");
assert_eq!(path, vec!["my-entry"]);
assert_eq!(field, "Notes");
}test_parse_reference_with_group function · rust · L524-L532 (9 LOC)src/providers/keepass.rs
fn test_parse_reference_with_group() {
let (path, field) = KeePassProvider::parse_reference("group/my-entry");
assert_eq!(path, vec!["group", "my-entry"]);
assert_eq!(field, "Password");
let (path, field) = KeePassProvider::parse_reference("group/subgroup/my-entry");
assert_eq!(path, vec!["group", "subgroup", "my-entry"]);
assert_eq!(field, "Password");
}test_parse_reference_with_group_and_field function · rust · L535-L543 (9 LOC)src/providers/keepass.rs
fn test_parse_reference_with_group_and_field() {
let (path, field) = KeePassProvider::parse_reference("group/my-entry/username");
assert_eq!(path, vec!["group", "my-entry"]);
assert_eq!(field, "UserName");
let (path, field) = KeePassProvider::parse_reference("group/subgroup/my-entry/password");
assert_eq!(path, vec!["group", "subgroup", "my-entry"]);
assert_eq!(field, "Password");
}build_key_name function · rust · L20-L25 (6 LOC)src/providers/keychain.rs
fn build_key_name(&self, key: &str) -> String {
match &self.prefix {
Some(prefix) => format!("{}{}", prefix, key),
None => key.to_string(),
}
}create_entry function · rust · L28-L71 (44 LOC)src/providers/keychain.rs
fn create_entry(&self, key: &str) -> Result<Entry> {
let full_key = self.build_key_name(key);
Entry::new(&self.service, &full_key).map_err(|e| FnoxError::ProviderApiError {
provider: "Keychain".to_string(),
details: format!(
"Failed to create entry for service '{}', key '{}': {}",
self.service, full_key, e
),
hint: "Check that the keychain is accessible".to_string(),
url: "https://fnox.jdx.dev/providers/keychain".to_string(),
})
}
/// Store a secret in the OS keychain
pub async fn put_secret(&self, key: &str, value: &str) -> Result<()> {
let entry = self.create_entry(key)?;
let full_key = self.build_key_name(key);
tracing::debug!(
"Storing secret '{}' in OS keychain (service: '{}', key: '{}')",
full_key,
self.service,
full_key
);
entry
.set_password(valueput_secret function · rust · L42-L108 (67 LOC)src/providers/keychain.rs
pub async fn put_secret(&self, key: &str, value: &str) -> Result<()> {
let entry = self.create_entry(key)?;
let full_key = self.build_key_name(key);
tracing::debug!(
"Storing secret '{}' in OS keychain (service: '{}', key: '{}')",
full_key,
self.service,
full_key
);
entry
.set_password(value)
.map_err(|e| FnoxError::ProviderApiError {
provider: "Keychain".to_string(),
details: format!(
"Failed to store secret '{}' (service: '{}'): {}",
full_key, self.service, e
),
hint: "Check that the keychain is accessible and writable".to_string(),
url: "https://fnox.jdx.dev/providers/keychain".to_string(),
})?;
tracing::debug!(
"Successfully stored secret '{}' in OS keychain (service: '{}')",
full_key,
self.stest_connection function · rust · L131-L167 (37 LOC)src/providers/keychain.rs
async fn test_connection(&self) -> Result<()> {
// Try to create an entry with a test key to verify keychain access
let test_key = "__fnox_test__";
let entry = self.create_entry(test_key)?;
// Try to set a test value to verify we have keychain access
entry
.set_password("test")
.map_err(|e| FnoxError::ProviderAuthFailed {
provider: "Keychain".to_string(),
details: format!(
"Failed to access keychain (service: '{}'): {}",
self.service, e
),
hint: "Check that you have permission to access the OS keychain".to_string(),
url: "https://fnox.jdx.dev/providers/keychain".to_string(),
})?;
// Try to read it back to verify it worked
entry
.get_password()
.map_err(|e| FnoxError::ProviderAuthFailed {
provider: "Keychain".to_string(),
put_secret function · rust · L168-L173 (6 LOC)src/providers/keychain.rs
async fn put_secret(&self, key: &str, value: &str) -> Result<String> {
self.put_secret(key, value).await?;
// Return the key name to store in config
Ok(key.to_string())
}Powered by Repobility — scan your code at https://repobility.com
test_keychain_set_and_get function · rust · L182-L197 (16 LOC)src/providers/keychain.rs
async fn test_keychain_set_and_get() {
let provider = KeychainProvider::new("fnox-unit-test".to_string(), None);
// Set a secret
let result = provider.put_secret("test_key", "test_value").await;
assert!(result.is_ok(), "Failed to set secret: {:?}", result.err());
// Get it back
let result = provider.get_secret("test_key").await;
assert!(result.is_ok(), "Failed to get secret: {:?}", result.err());
assert_eq!(result.unwrap(), "test_value");
// Clean up
let entry = provider.create_entry("test_key").unwrap();
let _ = entry.delete_credential();
}display_name function · rust · L55-L63 (9 LOC)src/providers/mod.rs
pub fn display_name(&self) -> &'static str {
match self {
Self::Local => "Local (easy to start)",
Self::PasswordManager => "Password Manager",
Self::CloudKms => "Cloud KMS",
Self::CloudSecretsManager => "Cloud Secrets Manager",
Self::OsKeychain => "OS Keychain",
}
}description function · rust · L66-L78 (13 LOC)src/providers/mod.rs
pub fn description(&self) -> &'static str {
match self {
Self::Local => "Plain text or local encryption - no external dependencies",
Self::PasswordManager => {
"1Password, Bitwarden, Infisical - use your existing password manager"
}
Self::CloudKms => "AWS KMS, Azure Key Vault, GCP KMS - encrypt with cloud keys",
Self::CloudSecretsManager => {
"AWS, Azure, GCP, HashiCorp Vault - store secrets remotely"
}
Self::OsKeychain => "Use your operating system's secure keychain",
}
}all function · rust · L81-L89 (9 LOC)src/providers/mod.rs
pub fn all() -> &'static [WizardCategory] {
&[
Self::Local,
Self::PasswordManager,
Self::CloudKms,
Self::CloudSecretsManager,
Self::OsKeychain,
]
}encrypt function · rust · L182-L187 (6 LOC)src/providers/mod.rs
async fn encrypt(&self, _value: &str) -> Result<String> {
// Default implementation for non-encryption providers
Err(crate::error::FnoxError::Provider(
"This provider does not support encryption".to_string(),
))
}put_secret function · rust · L197-L214 (18 LOC)src/providers/mod.rs
async fn put_secret(&self, _key: &str, value: &str) -> Result<String> {
let capabilities = self.capabilities();
if capabilities.contains(&ProviderCapability::Encryption) {
// Encryption provider - encrypt and return ciphertext
self.encrypt(value).await
} else if capabilities.contains(&ProviderCapability::RemoteStorage) {
// Remote storage provider - should override this method
Err(crate::error::FnoxError::Provider(
"Remote storage provider must implement put_secret".to_string(),
))
} else {
// Read-only provider
Err(crate::error::FnoxError::Provider(
"This provider does not support storing secrets".to_string(),
))
}
}wizard_info_by_category function · rust · L258-L263 (6 LOC)src/providers/mod.rs
pub fn wizard_info_by_category(category: WizardCategory) -> Vec<&'static WizardInfo> {
ALL_WIZARD_INFO
.iter()
.filter(|info| info.category == category)
.collect()
}get_provider_resolved function · rust · L273-L281 (9 LOC)src/providers/mod.rs
pub async fn get_provider_resolved(
config: &crate::config::Config,
profile: &str,
provider_name: &str,
provider_config: &ProviderConfig,
) -> Result<Box<dyn Provider>> {
let resolved = resolve_provider_config(config, profile, provider_name, provider_config).await?;
get_provider_from_resolved(&resolved)
}Want this analysis on your repo? https://repobility.com/scan/
new function · rust · L22-L28 (7 LOC)src/providers/onepassword.rs
pub fn new(vault: Option<String>, account: Option<String>, token: Option<String>) -> Self {
Self {
vault,
account,
token,
}
}get_token function · rust · L31-L36 (6 LOC)src/providers/onepassword.rs
fn get_token(&self) -> Option<String> {
self.token
.as_ref()
.cloned()
.or_else(op_service_account_token)
}value_to_reference function · rust · L39-L105 (67 LOC)src/providers/onepassword.rs
fn value_to_reference(&self, value: &str) -> Result<String> {
// Check if value is already a full op:// reference
if value.starts_with("op://") {
return Ok(value.to_string());
}
if self.vault.is_none() {
return Err(FnoxError::ProviderInvalidResponse {
provider: "1Password".to_string(),
details: format!("Unknown secret vault for: '{}'", value),
hint: "Specify a vault in the provider config or use a full 'op://' reference"
.to_string(),
url: "https://fnox.jdx.dev/providers/1password".to_string(),
});
}
// Parse value as "item/field" or just "item"
// Default field is "password" if not specified
let parts: Vec<&str> = value.split('/').collect();
match parts.len() {
1 => Ok(format!(
"op://{}/{}/password",
self.vault.as_ref().unwrap(),
pexecute_op_command function · rust · L80-L239 (160 LOC)src/providers/onepassword.rs
fn execute_op_command(&self, args: &[&str]) -> Result<String> {
tracing::debug!("Executing op command with args: {:?}", args);
let mut cmd = Command::new("op");
if let Some(token) = self.get_token() {
tracing::debug!(
"Setting OP_SERVICE_ACCOUNT_TOKEN (token length: {})",
token.len()
);
cmd.env("OP_SERVICE_ACCOUNT_TOKEN", token);
}
cmd.args(args);
// Add account flag if specified
if let Some(account) = &self.account {
cmd.arg("--account").arg(account);
}
let output = cmd.output().map_err(|e| {
if e.kind() == std::io::ErrorKind::NotFound {
FnoxError::ProviderCliNotFound {
provider: "1Password".to_string(),
cli: "op".to_string(),
install_hint: "brew install 1password-cli".to_string(),
url: "https://fnox.jdx.dev/providers/1pasget_secret function · rust · L263-L271 (9 LOC)src/providers/onepassword.rs
async fn get_secret(&self, value: &str) -> Result<String> {
tracing::debug!("Getting secret '{}' from 1Password", value);
let reference = self.value_to_reference(value)?;
tracing::debug!("Reading 1Password secret: {}", reference);
// Use 'op read' to fetch the secret
self.execute_op_command(&["read", &reference])
}test_connection function · rust · L390-L400 (11 LOC)src/providers/onepassword.rs
async fn test_connection(&self) -> Result<()> {
tracing::debug!("Testing connection to 1Password");
// Try to get the current user as a basic connectivity test
let output = self.execute_op_command(&["whoami"])?;
tracing::debug!("1Password whoami output: {}", output);
Ok(())
}op_service_account_token function · rust · L406-L411 (6 LOC)src/providers/onepassword.rs
fn op_service_account_token() -> Option<String> {
env::var("FNOX_OP_SERVICE_ACCOUNT_TOKEN")
.or_else(|_| env::var("OP_SERVICE_ACCOUNT_TOKEN"))
.ok()
}new function · rust · L44-L65 (22 LOC)src/providers/passwordstate.rs
pub fn new(
base_url: String,
api_key: Option<String>,
password_list_id: String,
verify_ssl: Option<String>,
) -> Self {
let api_key = api_key.or_else(passwordstate_api_key).unwrap_or_default();
let verify_ssl = verify_ssl
.map(|v| v.to_lowercase() != "false")
.unwrap_or(true);
// Normalize base_url (remove trailing slash)
let base_url = base_url.trim_end_matches('/').to_string();
Self {
base_url,
api_key,
password_list_id,
verify_ssl,
}
}Repobility · open methodology · https://repobility.com/research/
create_client function · rust · L68-L105 (38 LOC)src/providers/passwordstate.rs
fn create_client(&self) -> Result<reqwest::Client> {
reqwest::Client::builder()
.danger_accept_invalid_certs(!self.verify_ssl)
.build()
.map_err(|e| FnoxError::ProviderApiError {
provider: "Passwordstate".to_string(),
details: format!("Failed to create HTTP client: {}", e),
hint: "Check your network configuration".to_string(),
url: "https://fnox.jdx.dev/providers/overview".to_string(),
})
}
/// Parse value reference into (identifier, field, is_id)
///
/// Supported formats:
/// - `123` (numeric) - Password ID, returns password field
/// - `123/field` - Password ID with specific field
/// - `title` (non-numeric) - Search by title, returns password field
/// - `title/field` - Search by title, get specific field
fn parse_reference(&self, value: &str) -> Result<(String, String, bool)> {
let parts: Vec<&str> = value.split('/get_by_id function · rust · L109-L138 (30 LOC)src/providers/passwordstate.rs
async fn get_by_id(&self, password_id: &str) -> Result<PasswordEntry> {
let client = self.create_client()?;
let url = format!("{}/api/passwords/{}", self.base_url, password_id);
tracing::debug!("Fetching password by ID from: {}", url);
let response = client
.get(&url)
.header("APIKey", &self.api_key)
.send()
.await
.map_err(|e| FnoxError::ProviderApiError {
provider: "Passwordstate".to_string(),
details: format!("HTTP request failed: {}", e),
hint: "Check network connectivity to the Passwordstate server".to_string(),
url: "https://fnox.jdx.dev/providers/overview".to_string(),
})?;
if !response.status().is_success() {
let status = response.status();
let body = response.text().await.unwrap_or_default();
if status.as_u16() == 401 || status.as_u16() == 403 {
extract_field function · rust · L172-L266 (95 LOC)src/providers/passwordstate.rs
fn extract_field(entry: &PasswordEntry, field: &str) -> Result<String> {
let value = match field {
"password" => entry.password.clone(),
"username" | "user" => entry.user_name.clone(),
"title" => entry.title.clone(),
"url" => entry.url.clone(),
"description" => entry.description.clone(),
"notes" => entry.notes.clone(),
_ => None,
};
value.ok_or_else(|| FnoxError::ProviderInvalidResponse {
provider: "Passwordstate".to_string(),
details: format!("Field '{}' not found or empty in password entry", field),
hint: "Available fields: password, username, title, url, description, notes"
.to_string(),
url: "https://fnox.jdx.dev/providers/overview".to_string(),
})
}
/// Search for a password by title within the configured list
async fn search_by_title(&self, title: &str) -> Result<PasswordEntry> {