use ockam_core::compat::sync::Arc;
use ockam_core::Result;
use ockam_vault::{SigningKeyType, SigningSecretKeyHandle};
use crate::models::TimestampInSeconds;
use crate::utils::now;
use crate::IdentityOptions;
use crate::{Identifier, IdentitiesCreation};
pub const DEFAULT_IDENTITY_TTL: TimestampInSeconds = TimestampInSeconds(10 * 365 * 24 * 60 * 60);
enum Key {
Generate(SigningKeyType),
Existing(SigningSecretKeyHandle),
}
enum Ttl {
CreatedNowWithTtl(TimestampInSeconds),
FullTimestamps {
attestations_valid_from: TimestampInSeconds,
attestations_valid_until: TimestampInSeconds,
},
}
pub struct IdentityBuilder {
identities_creation: Arc<IdentitiesCreation>,
revoke_all_purpose_keys: bool,
key: Key,
ttl: Ttl,
}
impl IdentityBuilder {
pub fn new(identities_creation: Arc<IdentitiesCreation>) -> Self {
Self {
identities_creation,
revoke_all_purpose_keys: false,
key: Key::Generate(SigningKeyType::EdDSACurve25519),
ttl: Ttl::CreatedNowWithTtl(DEFAULT_IDENTITY_TTL),
}
}
pub fn with_existing_key(mut self, signing_secret_key_handle: SigningSecretKeyHandle) -> Self {
self.key = Key::Existing(signing_secret_key_handle);
self
}
pub fn with_random_key(mut self, key_type: SigningKeyType) -> Self {
self.key = Key::Generate(key_type);
self
}
pub fn with_timestamps(
mut self,
attestations_valid_from: TimestampInSeconds,
attestations_valid_until: TimestampInSeconds,
) -> Self {
self.ttl = Ttl::FullTimestamps {
attestations_valid_from,
attestations_valid_until,
};
self
}
pub fn with_ttl(mut self, ttl_seconds: impl Into<TimestampInSeconds>) -> Self {
self.ttl = Ttl::CreatedNowWithTtl(ttl_seconds.into());
self
}
pub fn with_purpose_keys_revocation(mut self) -> Self {
self.revoke_all_purpose_keys = true;
self
}
pub async fn build_options(self) -> Result<IdentityOptions> {
let key = match self.key {
Key::Generate(stype) => {
self.identities_creation
.identity_vault
.generate_signing_secret_key(stype)
.await?
}
Key::Existing(signing_secret_key_handle) => signing_secret_key_handle,
};
let (attestations_valid_from, attestations_valid_until) = match self.ttl {
Ttl::CreatedNowWithTtl(ttl) => {
let attestations_valid_from = now()?;
let attestations_valid_until = attestations_valid_from + ttl;
(attestations_valid_from, attestations_valid_until)
}
Ttl::FullTimestamps {
attestations_valid_from,
attestations_valid_until,
} => (attestations_valid_from, attestations_valid_until),
};
let options = IdentityOptions::new(
key,
self.revoke_all_purpose_keys,
attestations_valid_from,
attestations_valid_until,
);
Ok(options)
}
pub async fn build(self) -> Result<Identifier> {
let identities_creation = self.identities_creation.clone();
let options = self.build_options().await?;
identities_creation
.create_identity_with_options(options)
.await
}
}