Implement complete full-stack authentication system
- Restructure project with separate frontend/backend architecture - Create dedicated backend with Axum, SQLite, JWT authentication - Implement real API endpoints for register/login/verify - Update frontend to use HTTP requests instead of mock auth - Add bcrypt password hashing and secure token generation - Separate Cargo.toml files for frontend and backend builds - Fix Trunk compilation by isolating WASM-incompatible dependencies - Create demo user in database for easy testing - Both servers running: frontend (8081), backend (3000) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
57
backend/src/handlers.rs
Normal file
57
backend/src/handlers.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
use axum::{
|
||||
extract::{Query, State},
|
||||
http::{HeaderMap, StatusCode},
|
||||
response::Json,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{AppState, models::{LoginRequest, RegisterRequest, AuthResponse, ApiError}};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct VerifyQuery {
|
||||
pub token: String,
|
||||
}
|
||||
|
||||
pub async fn register(
|
||||
State(state): State<Arc<AppState>>,
|
||||
Json(request): Json<RegisterRequest>,
|
||||
) -> Result<Json<AuthResponse>, ApiError> {
|
||||
let response = state.auth_service.register(request).await?;
|
||||
Ok(Json(response))
|
||||
}
|
||||
|
||||
pub async fn login(
|
||||
State(state): State<Arc<AppState>>,
|
||||
Json(request): Json<LoginRequest>,
|
||||
) -> Result<Json<AuthResponse>, ApiError> {
|
||||
let response = state.auth_service.login(request).await?;
|
||||
Ok(Json(response))
|
||||
}
|
||||
|
||||
pub async fn verify_token(
|
||||
State(state): State<Arc<AppState>>,
|
||||
headers: HeaderMap,
|
||||
) -> Result<Json<serde_json::Value>, ApiError> {
|
||||
// Try to get token from Authorization header
|
||||
let token = if let Some(auth_header) = headers.get("authorization") {
|
||||
let auth_str = auth_header
|
||||
.to_str()
|
||||
.map_err(|_| ApiError::BadRequest("Invalid authorization header".to_string()))?;
|
||||
|
||||
if let Some(token) = auth_str.strip_prefix("Bearer ") {
|
||||
token.to_string()
|
||||
} else {
|
||||
return Err(ApiError::BadRequest("Authorization header must start with 'Bearer '".to_string()));
|
||||
}
|
||||
} else {
|
||||
return Err(ApiError::Unauthorized("Authorization header required".to_string()));
|
||||
};
|
||||
|
||||
let user_info = state.auth_service.verify_token(&token).await?;
|
||||
|
||||
Ok(Json(serde_json::json!({
|
||||
"valid": true,
|
||||
"user": user_info
|
||||
})))
|
||||
}
|
||||
Reference in New Issue
Block a user