use crate::core::{ClerkAuth, ClerkError, VerificationOutcome};
use axum::http::StatusCode;
use dioxus_fullstack_core::{FullstackContext, HttpError, ServerFnError};
pub fn current_outcome() -> Option<VerificationOutcome> {
FullstackContext::current().and_then(|ctx| ctx.extension::<VerificationOutcome>())
}
fn required_context_outcome() -> Result<Option<VerificationOutcome>, ClerkError> {
let ctx = FullstackContext::current().ok_or(ClerkError::NoServerContext)?;
let outcome = ctx.extension::<VerificationOutcome>();
if outcome.is_none() {
super::extractor::log_missing_layer();
}
Ok(outcome)
}
pub fn current_auth_opt() -> Result<Option<ClerkAuth>, ClerkError> {
match required_context_outcome()? {
Some(VerificationOutcome::Unavailable) => Err(jwks_unavailable()),
Some(VerificationOutcome::Valid(auth)) => Ok(Some(auth)),
_ => Ok(None),
}
}
pub fn current_auth() -> Result<ClerkAuth, ClerkError> {
match required_context_outcome()? {
Some(VerificationOutcome::Valid(auth)) => Ok(auth),
Some(VerificationOutcome::Invalid(reason)) => Err(reason.into()),
Some(VerificationOutcome::Unavailable) => Err(jwks_unavailable()),
_ => Err(ClerkError::Unauthenticated),
}
}
fn jwks_unavailable() -> ClerkError {
ClerkError::JwksUnavailable(
"verification infrastructure was unavailable for this request".into(),
)
}
impl From<ClerkError> for ServerFnError {
fn from(value: ClerkError) -> Self {
let status = clerk_error_status(&value);
HttpError::new(status, value.to_string()).into()
}
}
fn clerk_error_status(error: &ClerkError) -> StatusCode {
match error {
ClerkError::Unauthenticated | ClerkError::TokenExpired => StatusCode::UNAUTHORIZED,
ClerkError::JwksUnavailable(_) => StatusCode::SERVICE_UNAVAILABLE,
_ => StatusCode::INTERNAL_SERVER_ERROR,
}
}