use crate::core::VerificationOutcome;
use crate::ssr::{InitialState, InitialStateRead, ProviderStartup};
pub fn initial_state(
outcome: Option<&VerificationOutcome>,
publishable_key: Option<&str>,
) -> InitialState {
InitialState::from_outcome(outcome, publishable_key)
}
pub fn initial_state_script(
outcome: Option<&VerificationOutcome>,
publishable_key: Option<&str>,
) -> String {
InitialState::from_outcome(outcome, publishable_key).script_html()
}
pub fn initial_state_from_current_context(publishable_key: Option<&str>) -> InitialState {
let outcome = super::context::current_outcome();
initial_state(outcome.as_ref(), publishable_key)
}
pub fn initial_state_script_from_current_context(publishable_key: Option<&str>) -> String {
let outcome = super::context::current_outcome();
initial_state_script(outcome.as_ref(), publishable_key)
}
#[cfg_attr(target_arch = "wasm32", allow(dead_code))]
pub(crate) fn provider_startup_from_current_context(
prop_publishable_key: Option<String>,
) -> ProviderStartup {
let outcome = super::context::current_outcome();
let seed = InitialState::from_outcome(outcome.as_ref(), prop_publishable_key.as_deref());
crate::ssr::provider_startup_from_read(InitialStateRead::Present(seed), prop_publishable_key)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::{ClerkAuth, InvalidTokenReason};
use axum::http::Request;
use dioxus_fullstack_core::FullstackContext;
#[tokio::test]
async fn provider_startup_from_current_context_uses_valid_outcome() {
let cx = fullstack_context_with_outcome(VerificationOutcome::Valid(sample_auth()));
let startup = cx
.scope(async { provider_startup_from_current_context(Some("pk_test_xxx".into())) })
.await;
let state = startup.auth.to_state();
assert!(!state.is_loaded);
assert!(state.is_signed_in());
assert_eq!(state.user_id.as_deref(), Some("user_2abc"));
assert_eq!(startup.publishable_key.as_deref(), Some("pk_test_xxx"));
assert!(startup.warning.is_none());
assert!(
startup
.initial_state_json
.as_deref()
.is_some_and(|json| json.contains("user_2abc"))
);
}
#[tokio::test]
async fn provider_startup_from_current_context_ignores_stale_raw_auth() {
let cx = fullstack_context_with_invalid_outcome_and_stale_auth();
let startup = cx
.scope(async { provider_startup_from_current_context(Some("pk_test_xxx".into())) })
.await;
let state = startup.auth.to_state();
assert!(!state.is_loaded);
assert!(!state.is_signed_in());
assert!(state.user_id.is_none());
assert_eq!(startup.publishable_key.as_deref(), Some("pk_test_xxx"));
assert!(startup.warning.is_none());
assert!(startup.initial_state_json.is_some());
}
fn fullstack_context_with_outcome(outcome: VerificationOutcome) -> FullstackContext {
let mut req = Request::builder().uri("/").body(()).unwrap();
req.extensions_mut().insert(outcome);
let (parts, _body) = req.into_parts();
FullstackContext::new(parts)
}
fn fullstack_context_with_invalid_outcome_and_stale_auth() -> FullstackContext {
let mut req = Request::builder().uri("/").body(()).unwrap();
req.extensions_mut().insert(sample_auth());
req.extensions_mut()
.insert(VerificationOutcome::Invalid(InvalidTokenReason::Other));
let (parts, _body) = req.into_parts();
FullstackContext::new(parts)
}
fn sample_auth() -> ClerkAuth {
ClerkAuth {
user_id: "user_2abc".into(),
session_id: Some("sess_2def".into()),
org_id: Some("org_2ghi".into()),
org_slug: Some("acme".into()),
org_role: Some("admin".into()),
org_permissions: vec!["org:read".into(), "org:write".into()],
exp: 9_999_999_999,
nbf: 0,
iat: 0,
}
}
}