52 lines
1.3 KiB
Rust
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))
|
|
}
|