Files
gitks/api/auth/captcha.rs
T
zhenyi 0d3b53f7a0 feat(auth): add comprehensive authentication system with 2FA support
- Add new auth module with captcha, login, logout, register, and email verification endpoints
- Implement two-factor authentication with TOTP enable, disable, verify, and backup codes regeneration
- Create RSA public key endpoint for secure password encryption
- Add user profile management with get current user and email retrieval
- Integrate OpenAPI documentation for all authentication endpoints
- Implement password reset functionality with email verification flow
- Add comprehensive API response structures with proper error handling
- Configure all auth routes under /api/v1/auth scope with proper tagging
2026-06-07 18:09:38 +08:00

39 lines
2.0 KiB
Rust

use actix_web::{HttpResponse, web};
use crate::api::response::{ApiErrorResponse, ApiResponse};
use crate::error::AppError;
use crate::service::AppService;
use crate::service::auth::captcha::{CaptchaQuery, CaptchaResponse};
use crate::session::Session;
#[utoipa::path(
get,
path = "/api/v1/auth/captcha",
tag = "Auth",
operation_id = "authGetCaptcha",
summary = "Get captcha image",
description = "Generate a one-time captcha image and store the plaintext captcha in the current session. Captchas are used for sensitive entry points such as login and sending registration email codes. Set rsa=true to return the current session RSA public key at the same time and reduce frontend initialization requests. The captcha is consumed after either successful or failed validation, so clients must fetch a new one after failure.",
params(
("w" = u32, Query, description = "Captcha image width; allowed range is 80..=400.", example = 160),
("h" = u32, Query, description = "Captcha image height; allowed range is 30..=200.", example = 64),
("dark" = bool, Query, description = "Whether to generate a dark-mode captcha.", example = false),
("rsa" = bool, Query, description = "Whether to include the RSA public key in the response.", example = true)
),
responses(
(status = 200, description = "Captcha generated successfully. The base64 field is image data that can be used directly as img.src.", body = ApiResponse<CaptchaResponse>),
(status = 400, description = "Invalid captcha size.", body = ApiErrorResponse),
(status = 500, description = "Session write failed or RSA initialization failed.", body = ApiErrorResponse)
)
)]
pub async fn handle(
service: web::Data<AppService>,
session: Session,
query: web::Query<CaptchaQuery>,
) -> Result<HttpResponse, AppError> {
let data = service
.auth
.auth_captcha(&session, query.into_inner())
.await?;
Ok(HttpResponse::Ok().json(ApiResponse::new(data)))
}