Jump to…
snowinitial commitqoxwzsukwmkx1mo
Matt W1//! One-time site-admin bootstrap (decided; mirrors the Ory console's pattern).
Matt W2
Matt W3use axum::extract::State;
Matt W4use axum::response::{IntoResponse, Response};
Matt W5use axum::Form;
Matt W6use df_auth::provisioning;
Matt W7use serde::Deserialize;
Matt W8
Matt W9use crate::error::{AppError, AppResult};
Matt W10use crate::state::{AppState, CsrfToken, CurrentUser, Nonce};
Matt W11use crate::views::{self, Chrome};
Matt W12
Matt W13pub async fn show(
Matt W14 CurrentUser(user): CurrentUser,
Matt W15 CsrfToken(csrf): CsrfToken,
Matt W16 Nonce(nonce): Nonce,
Matt W17) -> AppResult<Response> {
Matt W18 // Claiming admin attaches it to an account, so one is required first.
Matt W19 let Some(user) = user else {
Matt W20 return Err(AppError::Unauthorized);
Matt W21 };
Matt W22
Matt W23 Ok(views::page(
Matt W24 Chrome { title: "Setup", user: Some(&user), csrf: &csrf, nonce: &nonce },
Matt W25 views::pages::setup(&csrf, None),
Matt W26 )
Matt W27 .into_response())
Matt W28}
Matt W29
Matt W30#[derive(Deserialize)]
Matt W31pub struct SetupForm {
Matt W32 pub token: String,
Matt W33}
Matt W34
Matt W35pub async fn claim(
Matt W36 State(state): State<AppState>,
Matt W37 CurrentUser(user): CurrentUser,
Matt W38 CsrfToken(csrf): CsrfToken,
Matt W39 Nonce(nonce): Nonce,
Matt W40 Form(form): Form<SetupForm>,
Matt W41) -> AppResult<Response> {
Matt W42 let Some(user) = user else {
Matt W43 return Err(AppError::Unauthorized);
Matt W44 };
Matt W45
Matt W46 let ok = provisioning::claim_admin(&state.db, user.id, form.token.trim()).await?;
Matt W47
Matt W48 if !ok {
Matt W49 tracing::warn!(user = %user.id, "setup token rejected");
Matt W50 return Ok(views::page(
Matt W51 Chrome { title: "Setup", user: Some(&user), csrf: &csrf, nonce: &nonce },
Matt W52 views::pages::setup(&csrf, Some("That token is not valid, or has already been used.")),
Matt W53 )
Matt W54 .into_response());
Matt W55 }
Matt W56
Matt W57 tracing::info!(user = %user.id, "site admin claimed");
Matt W58 Ok(views::page(
Matt W59 Chrome { title: "Setup complete", user: Some(&user), csrf: &csrf, nonce: &nonce },
Matt W60 views::pages::setup_done(),
Matt W61 )
Matt W62 .into_response())
Matt W63}

63 lines · Rust