pub mod mapper;
use crate::{
cdk::types::Principal,
dto::auth::{AttestationKey, AttestationKeySet},
storage::stable::auth::{
AuthState, DelegatedSessionBootstrapBindingRecord, DelegatedSessionRecord,
DelegatedTokenUseConsumeResult, DelegatedTokenUseRecord,
},
};
use mapper::AttestationPublicKeyRecordMapper;
pub use crate::storage::stable::auth::DelegatedSessionUpsertResult;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct DelegatedSession {
pub wallet_pid: Principal,
pub delegated_pid: Principal,
pub issued_at: u64,
pub expires_at: u64,
pub bootstrap_token_fingerprint: Option<[u8; 32]>,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct DelegatedSessionBootstrapBinding {
pub wallet_pid: Principal,
pub delegated_pid: Principal,
pub token_fingerprint: [u8; 32],
pub bound_at: u64,
pub expires_at: u64,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct DelegatedTokenUse {
pub issuer_shard_pid: Principal,
pub subject: Principal,
pub cert_hash: [u8; 32],
pub nonce: [u8; 16],
pub used_at: u64,
pub expires_at: u64,
}
pub struct AuthStateOps;
impl AuthStateOps {
#[must_use]
pub fn delegated_session(wallet_pid: Principal, now_secs: u64) -> Option<DelegatedSession> {
AuthState::get_active_delegated_session(wallet_pid, now_secs)
.map(delegated_session_record_to_view)
}
#[must_use]
pub fn delegated_session_subject(wallet_pid: Principal, now_secs: u64) -> Option<Principal> {
Self::delegated_session(wallet_pid, now_secs).map(|session| session.delegated_pid)
}
#[cfg(test)]
pub fn upsert_delegated_session(
session: DelegatedSession,
now_secs: u64,
) -> DelegatedSessionUpsertResult {
AuthState::upsert_delegated_session(delegated_session_view_to_record(session), now_secs)
}
pub fn upsert_delegated_session_with_bootstrap_binding(
session: DelegatedSession,
binding: DelegatedSessionBootstrapBinding,
now_secs: u64,
) -> DelegatedSessionUpsertResult {
AuthState::upsert_delegated_session_with_bootstrap_binding(
delegated_session_view_to_record(session),
delegated_session_bootstrap_binding_view_to_record(binding),
now_secs,
)
}
pub fn clear_delegated_session(wallet_pid: Principal) {
AuthState::clear_delegated_session(wallet_pid);
}
#[must_use]
pub fn prune_expired_delegated_sessions(now_secs: u64) -> usize {
AuthState::prune_expired_delegated_sessions(now_secs)
}
#[must_use]
pub fn delegated_session_bootstrap_binding(
token_fingerprint: [u8; 32],
now_secs: u64,
) -> Option<DelegatedSessionBootstrapBinding> {
AuthState::get_active_delegated_session_bootstrap_binding(token_fingerprint, now_secs)
.map(delegated_session_bootstrap_binding_record_to_view)
}
#[must_use]
pub fn prune_expired_delegated_session_bootstrap_bindings(now_secs: u64) -> usize {
AuthState::prune_expired_delegated_session_bootstrap_bindings(now_secs)
}
#[must_use]
pub fn consume_delegated_token_use(
token_use: DelegatedTokenUse,
now_secs: u64,
) -> DelegatedTokenUseConsumeResult {
AuthState::consume_delegated_token_use(
delegated_token_use_view_to_record(token_use),
now_secs,
)
}
#[must_use]
pub fn attestation_public_key(key_id: u32, key_name: &str) -> Option<AttestationKey> {
AuthState::get_attestation_public_key(key_id, key_name)
.map(AttestationPublicKeyRecordMapper::record_to_dto)
}
#[must_use]
pub fn attestation_public_key_sec1(key_id: u32, key_name: &str) -> Option<Vec<u8>> {
Self::attestation_public_key(key_id, key_name).map(|entry| entry.public_key)
}
#[must_use]
pub fn attestation_keys(key_name: &str) -> Vec<AttestationKey> {
AuthState::get_attestation_public_keys(key_name)
.into_iter()
.map(AttestationPublicKeyRecordMapper::record_to_dto)
.collect()
}
pub fn set_attestation_key_set(key_set: AttestationKeySet) {
let keys = key_set
.keys
.into_iter()
.map(AttestationPublicKeyRecordMapper::dto_to_record)
.collect();
AuthState::set_attestation_public_keys(keys);
}
pub fn upsert_attestation_key(key: AttestationKey) {
AuthState::upsert_attestation_public_key(AttestationPublicKeyRecordMapper::dto_to_record(
key,
));
}
}
const fn delegated_session_record_to_view(record: DelegatedSessionRecord) -> DelegatedSession {
DelegatedSession {
wallet_pid: record.wallet_pid,
delegated_pid: record.delegated_pid,
issued_at: record.issued_at,
expires_at: record.expires_at,
bootstrap_token_fingerprint: record.bootstrap_token_fingerprint,
}
}
const fn delegated_session_view_to_record(view: DelegatedSession) -> DelegatedSessionRecord {
DelegatedSessionRecord {
wallet_pid: view.wallet_pid,
delegated_pid: view.delegated_pid,
issued_at: view.issued_at,
expires_at: view.expires_at,
bootstrap_token_fingerprint: view.bootstrap_token_fingerprint,
}
}
const fn delegated_session_bootstrap_binding_record_to_view(
record: DelegatedSessionBootstrapBindingRecord,
) -> DelegatedSessionBootstrapBinding {
DelegatedSessionBootstrapBinding {
wallet_pid: record.wallet_pid,
delegated_pid: record.delegated_pid,
token_fingerprint: record.token_fingerprint,
bound_at: record.bound_at,
expires_at: record.expires_at,
}
}
const fn delegated_session_bootstrap_binding_view_to_record(
view: DelegatedSessionBootstrapBinding,
) -> DelegatedSessionBootstrapBindingRecord {
DelegatedSessionBootstrapBindingRecord {
wallet_pid: view.wallet_pid,
delegated_pid: view.delegated_pid,
token_fingerprint: view.token_fingerprint,
bound_at: view.bound_at,
expires_at: view.expires_at,
}
}
const fn delegated_token_use_view_to_record(view: DelegatedTokenUse) -> DelegatedTokenUseRecord {
DelegatedTokenUseRecord {
issuer_shard_pid: view.issuer_shard_pid,
subject: view.subject,
cert_hash: view.cert_hash,
nonce: view.nonce,
used_at: view.used_at,
expires_at: view.expires_at,
}
}