44 lines
1.3 KiB
Rust
44 lines
1.3 KiB
Rust
use axum::extract::State;
|
|
use axum::http::StatusCode;
|
|
use axum::Json;
|
|
use serde_json::{json, Value};
|
|
use std::sync::Arc;
|
|
|
|
use crate::auth::{hash, random};
|
|
use crate::error::AppError;
|
|
use crate::roles::ROLE_SUPERADMIN;
|
|
use crate::state::AppState;
|
|
|
|
pub async fn bootstrap(State(state): State<Arc<AppState>>) -> Result<Json<Value>, AppError> {
|
|
// 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?;
|
|
|
|
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();
|
|
|
|
sqlx::query!(
|
|
r#"INSERT INTO users ( name, display_name, password, roles ) VALUES ( $1, $2, $3, $4 ) RETURNING id"#,
|
|
username,
|
|
"Administrator",
|
|
hash(&password)?,
|
|
&[ROLE_SUPERADMIN],
|
|
)
|
|
.fetch_one(&state.database)
|
|
.await?;
|
|
|
|
Ok(Json(json!({"username": username, "password": password})))
|
|
}
|