Backend initial admin setup
This commit is contained in:
@@ -304,6 +304,84 @@ pub async fn update_user(
|
|||||||
Ok(Json(response))
|
Ok(Json(response))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn check_admin_exists(
|
||||||
|
State(data): State<Arc<AppState>>,
|
||||||
|
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
|
||||||
|
let admin_count = sqlx::query_scalar::<_, i64>(r#"SELECT COUNT(*) FROM users WHERE is_admin = true"#)
|
||||||
|
.fetch_one(&data.db)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
(
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(json!({"status": "error", "message": format!("{:?}", e)})),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let has_admin = admin_count > 0;
|
||||||
|
Ok(Json(json!({"has_admin": has_admin})))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn setup_initial_admin(
|
||||||
|
State(data): State<Arc<AppState>>,
|
||||||
|
Json(request): Json<UserCreateScheme>,
|
||||||
|
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
|
||||||
|
// Check if any admin already exists
|
||||||
|
let admin_count = sqlx::query_scalar::<_, i64>(r#"SELECT COUNT(*) FROM users WHERE is_admin = true"#)
|
||||||
|
.fetch_one(&data.db)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
(
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(json!({"status": "error", "message": format!("{:?}", e)})),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if admin_count > 0 {
|
||||||
|
return Err((
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(json!({"status": "error", "message": "Admin user already exists"})),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if request.username.is_empty() || request.pwd.is_empty() {
|
||||||
|
return Err((
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(json!({"status": "error", "message": "Missing credential"})),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let argon = Argon2::default();
|
||||||
|
let salt = SaltString::generate(&mut OsRng);
|
||||||
|
let hashed_pwd = match argon.hash_password(request.pwd.clone().as_bytes(), &salt) {
|
||||||
|
Ok(h) => h.to_string(),
|
||||||
|
Err(e) => panic!("Error hashing {:}", e),
|
||||||
|
};
|
||||||
|
|
||||||
|
let user = sqlx::query("INSERT INTO users (username, pwd, first_name, last_name, is_admin) VALUES ($1, $2, $3, $4, $5)")
|
||||||
|
.bind(request.username)
|
||||||
|
.bind(&hashed_pwd)
|
||||||
|
.bind(request.first_name)
|
||||||
|
.bind(request.last_name)
|
||||||
|
.bind(true)
|
||||||
|
.execute(&data.db)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
(
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(json!({"status": "error", "message": format!("{}", e)})),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if user.rows_affected() < 1 {
|
||||||
|
return Err((
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(json!({"status": "error", "message": "Error creating admin user"})),
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
Ok(Json(json!({"status": "success", "result": "Admin user created"})))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn filter_user(user: &User) -> FilteredUser {
|
pub fn filter_user(user: &User) -> FilteredUser {
|
||||||
FilteredUser {
|
FilteredUser {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ use crate::{
|
|||||||
cookie::validation::{validate_admin, validate_token},
|
cookie::validation::{validate_admin, validate_token},
|
||||||
handlers::{
|
handlers::{
|
||||||
auth::{
|
auth::{
|
||||||
create_user, delete_user, get_current_user, get_user_by_id, get_users, login, logout,
|
check_admin_exists, create_user, delete_user, get_current_user, get_user_by_id, get_users, login, logout,
|
||||||
update_user,
|
setup_initial_admin, update_user,
|
||||||
},
|
},
|
||||||
ticket::{create_ticket, delete_ticket, edit_ticket, get_ticket_by_id, get_tickets},
|
ticket::{create_ticket, delete_ticket, edit_ticket, get_ticket_by_id, get_tickets},
|
||||||
},
|
},
|
||||||
@@ -50,5 +50,7 @@ pub fn create_router(state: Arc<AppState>) -> Router {
|
|||||||
Router::new()
|
Router::new()
|
||||||
.merge(protected_routes)
|
.merge(protected_routes)
|
||||||
.route("/api/login", post(login))
|
.route("/api/login", post(login))
|
||||||
|
.route("/api/check-admin", get(check_admin_exists))
|
||||||
|
.route("/api/setup-admin", post(setup_initial_admin))
|
||||||
.with_state(state)
|
.with_state(state)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user