use crate::verification::{VerificationCreation, VerificationPublication, VerificationSnapshot};
use crate::{AuthError, AuthResult, AuthSchema, CreateVerification};
use async_trait::async_trait;
#[async_trait]
pub trait VerificationStore<S: AuthSchema>: Send + Sync {
async fn create_verification_record(
&self,
_data: VerificationCreation,
_publication: VerificationPublication,
) -> AuthResult<Option<VerificationSnapshot>> {
Err(AuthError::NotImplemented(
"Verification publication phases are not supported by this store".into(),
))
}
async fn consume_verification_snapshot(
&self,
_identifier: &str,
) -> AuthResult<Option<S::Verification>> {
Err(AuthError::NotImplemented(
"Raw atomic verification consumption is not supported by this store".into(),
))
}
async fn update_verification_by_identifier(
&self,
_identifier: &str,
_data: crate::UpdateVerification,
) -> AuthResult<Option<VerificationSnapshot>> {
Err(AuthError::NotImplemented(
"Verification identifier updates are not supported by this store".into(),
))
}
async fn reserve_verification_record(
&self,
_logical_identifier: &str,
_data: CreateVerification,
) -> AuthResult<Option<S::Verification>> {
Err(AuthError::NotImplemented(
"Configured verification reservation is not supported by this store".into(),
))
}
async fn create_verification(
&self,
verification: CreateVerification,
) -> AuthResult<S::Verification>;
async fn get_verification(
&self,
identifier: &str,
value: &str,
) -> AuthResult<Option<S::Verification>>;
async fn get_verification_by_value(&self, value: &str) -> AuthResult<Option<S::Verification>>;
async fn get_verification_by_identifier(
&self,
identifier: &str,
) -> AuthResult<Option<S::Verification>>;
async fn consume_verification(
&self,
identifier: &str,
value: &str,
) -> AuthResult<Option<S::Verification>>;
async fn get_latest_verification_by_identifier(
&self,
_identifier: &str,
) -> AuthResult<Option<S::Verification>> {
Err(AuthError::internal(
"raw verification lookup is not supported by this store",
))
}
async fn consume_verification_by_identifier(
&self,
_identifier: &str,
) -> AuthResult<Option<S::Verification>> {
Err(AuthError::internal(
"atomic verification consumption is not supported by this store",
))
}
async fn delete_verifications_by_identifier(&self, _identifier: &str) -> AuthResult<()> {
Err(AuthError::internal(
"verification invalidation is not supported by this store",
))
}
async fn compare_and_swap_verification(
&self,
_id: &str,
_expected_value: &str,
_value: &str,
_expires_at: chrono::DateTime<chrono::Utc>,
) -> AuthResult<bool> {
Err(AuthError::internal(
"atomic verification updates are not supported by this store",
))
}
async fn reserve_verification(&self, _verification: CreateVerification) -> AuthResult<bool> {
Err(AuthError::internal(
"verification reservation is not supported by this store",
))
}
async fn delete_verification(&self, id: &str) -> AuthResult<()>;
async fn delete_expired_verifications(&self) -> AuthResult<usize>;
}
#[must_use]
pub fn verification_reservation_key(identifier: &str) -> (String, [u8; 32]) {
use base64::Engine;
use sha2::{Digest, Sha256};
let mut hash = Sha256::new();
hash.update(b"reserve:");
hash.update(identifier.as_bytes());
let digest: [u8; 32] = hash.finalize().into();
(
base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(digest),
digest,
)
}