userp 0.0.4

Userp is a user account system inspired by Next Auth, with OAuth, password and email support, a ready-made Axum router with Askama templates, and more on the way!
Documentation
use super::{EmailChallenge, SendEmailChallengeError};
use crate::{
    core::CoreUserp,
    traits::{UserpCookies, UserpStore},
};
use chrono::Utc;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum EmailVerifyCallbackError<StoreError: std::error::Error> {
    #[error("Challenge expired")]
    ChallengeExpired,
    #[error("Challenge not found")]
    ChallengeNotFound,
    #[error(transparent)]
    Store(#[from] StoreError),
}

impl<S: UserpStore, C: UserpCookies> CoreUserp<S, C> {
    pub async fn email_verify_callback(
        &self,
        code: String,
    ) -> Result<(String, Option<String>), EmailVerifyCallbackError<S::Error>> {
        let Some(challenge) = self.store.email_consume_challenge(code).await? else {
            return Err(EmailVerifyCallbackError::ChallengeNotFound);
        };

        if challenge.get_expires() < Utc::now() {
            return Err(EmailVerifyCallbackError::ChallengeExpired);
        }

        self.store
            .email_set_verified(challenge.get_address())
            .await?;

        Ok((
            challenge.get_address().to_owned(),
            challenge.get_next().clone(),
        ))
    }

    pub async fn email_verify_init(
        &self,
        email: String,
        next: Option<String>,
    ) -> Result<(), SendEmailChallengeError<S::Error>> {
        self.send_email_challenge(
            self.routes.actions.user_email_verify.clone(),
            email,
            "Click here to verify email".into(),
            next,
        )
        .await?;

        Ok(())
    }
}