mabel/src/routes/admin.rs

52 lines
1.3 KiB
Rust

use axum::http::StatusCode;
use axum::response::IntoResponse;
use axum::routing::post;
use axum::Json;
use axum::{extract::State, Router};
use serde_json::json;
use std::sync::Arc;
use crate::{
auth::{hash::random, user::User},
error::AppError,
roles::ROLE_SUPERADMIN,
state::AppState,
};
async fn bootstrap(State(state): State<Arc<AppState>>) -> impl IntoResponse {
// Only allow this request if the user table is completely empty!
let empty = sqlx::query!(
"SELECT CASE WHEN EXISTS(SELECT 1 FROM users) THEN false ELSE true END AS empty;"
)
.map(|row| row.empty.unwrap_or(true))
.fetch_one(&state.database)
.await
.map_err(AppError::from)?;
if !empty {
return Err(AppError::ClientError {
status: StatusCode::BAD_REQUEST,
code: "already-setup".into(),
message: "The instance was already bootstrapped".into(),
});
}
let username = "admin";
let password = random();
User::create(
&state.database,
&username,
&password,
&[ROLE_SUPERADMIN].to_vec(),
)
.await
.map_err(AppError::from)?;
Ok(Json(json!({"username": username, "password": password})))
}
pub fn router() -> Router<Arc<AppState>> {
Router::new().route("/bootstrap", post(bootstrap))
}