🦀/100 Projects/Notes/Source

src/main.rs

View on GitHub
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Mutex;
use bcrypt::{hash, verify, DEFAULT_COST};
 
#[derive(Deserialize)]
struct SignupRequest {
    username: String,
    password: String,
}
 
#[derive(Deserialize)]
struct LoginRequest {
    username: String,
    password: String,
}
 
#[derive(Serialize, Clone)]
struct User {
    username: String,
    hashed_password: String,
}
 
struct AppState {
    users: Mutex<HashMap<String, User>>,
}
 
async fn signup(req: web::Json<SignupRequest>, data: web::Data<AppState>) -> impl Responder {
    let mut users = data.users.lock().unwrap();
 
    if users.contains_key(&req.username) {
        return HttpResponse::Conflict().body("❌ Username already exists");
    }
 
    let hashed = hash(&req.password, DEFAULT_COST).unwrap();
    let user = User {
        username: req.username.clone(),
        hashed_password: hashed,
    };
 
    users.insert(req.username.clone(), user);
    HttpResponse::Created().body("✅ User created")
}
 
async fn login(req: web::Json<LoginRequest>, data: web::Data<AppState>) -> impl Responder {
    let users = data.users.lock().unwrap();
 
    match users.get(&req.username) {
        Some(user) => {
            if verify(&req.password, &user.hashed_password).unwrap_or(false) {
                HttpResponse::Ok().body("🔐 Login successful")
            } else {
                HttpResponse::Unauthorized().body("❌ Invalid credentials")
            }
        }
        None => HttpResponse::NotFound().body("❌ User not found"),
    }
}
 
#[actix_web::main]
async fn main() -> std::io::Result<()> {
    println!("🔐 Auth API running at http://127.0.0.1:8080");
 
    let users = web::Data::new(AppState {
        users: Mutex::new(HashMap::new()),
    });
 
    HttpServer::new(move || {
        App::new()
            .app_data(users.clone())
            .route("/signup", web::post().to(signup))
            .route("/login", web::post().to(login))
    })
    .bind(("127.0.0.1", 8080))?
    .run()
    .await
}

← Back to folder