use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Credential {
name: String,
username: String,
password: String,
url: Option<String>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct CredentialBuilder {
name: Option<String>,
username: Option<String>,
password: Option<String>,
url: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CredentialBuilderError {
MissingName,
MissingUsername,
MissingPassword,
}
impl Credential {
pub fn new(name: String, username: String, password: String, url: Option<String>) -> Self {
Credential {
name,
username,
password,
url,
}
}
pub fn builder() -> CredentialBuilder {
CredentialBuilder::default()
}
pub fn name(&self) -> &str {
&self.name
}
pub fn set_name(&mut self, name: String) -> &mut Self {
self.name = name;
self
}
pub fn username(&self) -> &str {
&self.username
}
pub fn set_username(&mut self, username: String) -> &mut Self {
self.username = username;
self
}
pub fn password(&self) -> &str {
&self.password
}
pub fn set_password(&mut self, password: String) -> &mut Self {
self.password = password;
self
}
pub fn url(&self) -> Option<&str> {
self.url.as_deref()
}
pub fn set_url(&mut self, url: Option<String>) -> &mut Self {
self.url = url;
self
}
}
impl CredentialBuilder {
pub fn name(mut self, name: String) -> Self {
self.name = Some(name);
self
}
pub fn username(mut self, username: String) -> Self {
self.username = Some(username);
self
}
pub fn password(mut self, password: String) -> Self {
self.password = Some(password);
self
}
pub fn url(mut self, url: String) -> Self {
self.url = Some(url);
self
}
pub fn build(self) -> Result<Credential, CredentialBuilderError> {
let name = self.name.ok_or(CredentialBuilderError::MissingName)?;
let username = self
.username
.ok_or(CredentialBuilderError::MissingUsername)?;
let password = self
.password
.ok_or(CredentialBuilderError::MissingPassword)?;
Ok(Credential {
name,
username,
password,
url: self.url,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new() {
let credential = Credential::new(
"My Credential".to_string(),
"username".to_string(),
"password".to_string(),
Some("https://example.com".to_string()),
);
assert_eq!(credential.name(), "My Credential");
assert_eq!(credential.username(), "username");
assert_eq!(credential.password(), "password");
assert_eq!(credential.url(), Some("https://example.com"));
}
#[test]
fn builder_with_optional_url() {
let credential = Credential::builder()
.name("My Credential".to_string())
.username("username".to_string())
.password("password".to_string())
.url("https://example.com".to_string())
.build()
.unwrap();
assert_eq!(credential.name(), "My Credential");
assert_eq!(credential.username(), "username");
assert_eq!(credential.password(), "password");
assert_eq!(credential.url(), Some("https://example.com"));
}
#[test]
fn builder_without_optional_url() {
let credential = Credential::builder()
.name("My Credential".to_string())
.username("username".to_string())
.password("password".to_string())
.build()
.unwrap();
assert_eq!(credential.url(), None);
}
#[test]
fn builder_missing_required_field() {
let result = Credential::builder()
.name("My Credential".to_string())
.password("password".to_string())
.build();
assert_eq!(result, Err(CredentialBuilderError::MissingUsername));
}
}