add admin setup token i love admin setup token
This commit is contained in:
parent
660da70666
commit
ac13e77dc4
15 changed files with 136 additions and 21 deletions
|
@ -189,6 +189,27 @@ pub async fn register(
|
|||
state: web::Data<AppState>,
|
||||
payload: web::Json<RegisterRequest>,
|
||||
) -> Result<impl Responder, AppError> {
|
||||
// Check if any users exist
|
||||
let user_count = sqlx::query!("SELECT COUNT(*) as count FROM users")
|
||||
.fetch_one(&state.db)
|
||||
.await?
|
||||
.count
|
||||
.unwrap_or(0);
|
||||
|
||||
// If users exist, registration is closed - no exceptions
|
||||
if user_count > 0 {
|
||||
return Err(AppError::Auth("Registration is closed".to_string()));
|
||||
}
|
||||
|
||||
// Verify admin token for first user
|
||||
match (&state.admin_token, &payload.admin_token) {
|
||||
(Some(stored_token), Some(provided_token)) if stored_token == provided_token => {
|
||||
// Token matches, proceed with registration
|
||||
}
|
||||
_ => return Err(AppError::Auth("Invalid admin setup token".to_string())),
|
||||
}
|
||||
|
||||
// Check if email already exists
|
||||
let exists = sqlx::query!("SELECT id FROM users WHERE email = $1", payload.email)
|
||||
.fetch_optional(&state.db)
|
||||
.await?;
|
||||
|
|
41
src/lib.rs
41
src/lib.rs
|
@ -1,4 +1,8 @@
|
|||
use rand::Rng;
|
||||
use sqlx::PgPool;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use tracing::info;
|
||||
|
||||
pub mod auth;
|
||||
pub mod error;
|
||||
|
@ -8,4 +12,41 @@ pub mod models;
|
|||
#[derive(Clone)]
|
||||
pub struct AppState {
|
||||
pub db: PgPool,
|
||||
pub admin_token: Option<String>,
|
||||
}
|
||||
|
||||
pub async fn check_and_generate_admin_token(pool: &sqlx::PgPool) -> anyhow::Result<Option<String>> {
|
||||
// Check if any users exist
|
||||
let user_count = sqlx::query!("SELECT COUNT(*) as count FROM users")
|
||||
.fetch_one(pool)
|
||||
.await?
|
||||
.count
|
||||
.unwrap_or(0);
|
||||
|
||||
if user_count == 0 {
|
||||
// Generate a random token using simple characters
|
||||
let token: String = (0..32)
|
||||
.map(|_| {
|
||||
let idx = rand::thread_rng().gen_range(0..62);
|
||||
match idx {
|
||||
0..=9 => (b'0' + idx as u8) as char,
|
||||
10..=35 => (b'a' + (idx - 10) as u8) as char,
|
||||
_ => (b'A' + (idx - 36) as u8) as char,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Save token to file
|
||||
let mut file = File::create("admin-setup-token.txt")?;
|
||||
writeln!(file, "{}", token)?;
|
||||
|
||||
info!("No users found - generated admin setup token");
|
||||
info!("Token has been saved to admin-setup-token.txt");
|
||||
info!("Use this token to create the admin user");
|
||||
info!("Admin setup token: {}", token);
|
||||
|
||||
Ok(Some(token))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ use actix_cors::Cors;
|
|||
use actix_files as fs;
|
||||
use actix_web::{web, App, HttpServer};
|
||||
use anyhow::Result;
|
||||
use simplelink::check_and_generate_admin_token;
|
||||
use simplelink::{handlers, AppState};
|
||||
use sqlx::postgres::PgPoolOptions;
|
||||
use tracing::info;
|
||||
|
@ -27,7 +28,12 @@ async fn main() -> Result<()> {
|
|||
// Run database migrations
|
||||
sqlx::migrate!("./migrations").run(&pool).await?;
|
||||
|
||||
let state = AppState { db: pool };
|
||||
let admin_token = check_and_generate_admin_token(&pool).await?;
|
||||
|
||||
let state = AppState {
|
||||
db: pool,
|
||||
admin_token,
|
||||
};
|
||||
|
||||
let host = std::env::var("SERVER_HOST").unwrap_or_else(|_| "127.0.0.1".to_string());
|
||||
let port = std::env::var("SERVER_PORT").unwrap_or_else(|_| "8080".to_string());
|
||||
|
|
|
@ -49,6 +49,7 @@ pub struct LoginRequest {
|
|||
pub struct RegisterRequest {
|
||||
pub email: String,
|
||||
pub password: String,
|
||||
pub admin_token: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue