mirror of
https://github.com/RaisFast/raisfast.git
synced 2026-09-24 16:02:44 +00:00
260 lines
7.9 KiB
Rust
260 lines
7.9 KiB
Rust
use super::*;
|
|
|
|
#[tokio::test]
|
|
async fn register_success() {
|
|
let (mut app, _) = test_app().await;
|
|
let (status, body): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json(
|
|
"/api/v1/auth/register",
|
|
json!({"email": "reg@test.com", "username": "reguser", "password": "Password123"}),
|
|
),
|
|
)
|
|
.await;
|
|
assert!(status.is_success(), "{status} {body:?}");
|
|
assert_eq!(body["code"], 0);
|
|
assert_eq!(body["data"]["username"], "reguser");
|
|
assert_eq!(body["data"]["role"], "reader");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn register_duplicate_email() {
|
|
let (mut app, _) = test_app().await;
|
|
let req_body = json!({"email": "dup@test.com", "username": "dup1", "password": "Password123"});
|
|
let (s, _): (StatusCode, Value) =
|
|
send(&mut app, post_json("/api/v1/auth/register", req_body)).await;
|
|
assert!(s.is_success());
|
|
|
|
let (status, body): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json(
|
|
"/api/v1/auth/register",
|
|
json!({"email": "dup@test.com", "username": "dup2", "password": "Password123"}),
|
|
),
|
|
)
|
|
.await;
|
|
assert_eq!(status, StatusCode::CONFLICT);
|
|
assert_eq!(body["code"], 40900);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn register_validation_errors() {
|
|
let (mut app, _) = test_app().await;
|
|
let cases = vec![
|
|
json!({"email": "bad", "username": "user", "password": "Password123"}),
|
|
json!({"email": "ok@test.com", "username": "a", "password": "Password123"}),
|
|
json!({"email": "ok@test.com", "username": "user", "password": "short"}),
|
|
json!({"email": "", "username": "", "password": ""}),
|
|
];
|
|
for case in cases {
|
|
let (status, body): (StatusCode, Value) =
|
|
send(&mut app, post_json("/api/v1/auth/register", case)).await;
|
|
assert_eq!(status, StatusCode::BAD_REQUEST, "expected 400: {body:?}");
|
|
assert_eq!(body["code"], 40000);
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn login_success() {
|
|
let (mut app, _) = test_app().await;
|
|
let (access, refresh) =
|
|
register_and_login(&mut app, "login@test.com", "loginuser", "Password123").await;
|
|
assert!(!access.is_empty());
|
|
assert!(!refresh.is_empty());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn login_wrong_password() {
|
|
let (mut app, _) = test_app().await;
|
|
let _ = register_and_login(&mut app, "lwp@test.com", "lwpuser", "Password123").await;
|
|
let (status, body): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json(
|
|
"/api/v1/auth/login",
|
|
json!({"email": "lwp@test.com", "password": "Wrong123"}),
|
|
),
|
|
)
|
|
.await;
|
|
assert_eq!(status, StatusCode::UNAUTHORIZED);
|
|
assert_eq!(body["code"], 40100);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn login_nonexistent_user() {
|
|
let (mut app, _) = test_app().await;
|
|
let (status, _): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json(
|
|
"/api/v1/auth/login",
|
|
json!({"email": "none@test.com", "password": "Password123"}),
|
|
),
|
|
)
|
|
.await;
|
|
assert_eq!(status, StatusCode::UNAUTHORIZED);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn refresh_token_success() {
|
|
let (mut app, _) = test_app().await;
|
|
let (_, refresh) =
|
|
register_and_login(&mut app, "refresh@test.com", "refreshuser", "Password123").await;
|
|
let (status, body): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json("/api/v1/auth/refresh", json!({"refresh_token": refresh})),
|
|
)
|
|
.await;
|
|
assert!(status.is_success(), "{status} {body:?}");
|
|
assert_eq!(body["code"], 0);
|
|
assert!(body["data"]["access_token"].is_string());
|
|
assert!(body["data"]["refresh_token"].is_string());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn refresh_token_invalid() {
|
|
let (mut app, _) = test_app().await;
|
|
let (status, _): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json(
|
|
"/api/v1/auth/refresh",
|
|
json!({"refresh_token": "bad-token"}),
|
|
),
|
|
)
|
|
.await;
|
|
assert_eq!(status, StatusCode::UNAUTHORIZED);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn refresh_token_rotation() {
|
|
let (mut app, _) = test_app().await;
|
|
let (_, r1) = register_and_login(&mut app, "rot@test.com", "rotuser", "Password123").await;
|
|
|
|
let (_, body): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json("/api/v1/auth/refresh", json!({"refresh_token": r1})),
|
|
)
|
|
.await;
|
|
let r2 = body["data"]["refresh_token"].as_str().unwrap().to_string();
|
|
|
|
let (s, _): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json("/api/v1/auth/refresh", json!({"refresh_token": r1})),
|
|
)
|
|
.await;
|
|
assert_eq!(s, StatusCode::UNAUTHORIZED, "旧 token 应已失效");
|
|
|
|
let (s, _): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json("/api/v1/auth/refresh", json!({"refresh_token": r2})),
|
|
)
|
|
.await;
|
|
assert!(s.is_success(), "新 token 应可用");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn logout_success() {
|
|
let (mut app, _) = test_app().await;
|
|
let (access, _) = register_and_login(&mut app, "lo@test.com", "louser", "Password123").await;
|
|
let (status, body): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json_auth("/api/v1/auth/logout", json!({}), &access),
|
|
)
|
|
.await;
|
|
assert!(status.is_success(), "{status} {body:?}");
|
|
assert_eq!(body["code"], 0);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn logout_without_token() {
|
|
let (mut app, _) = test_app().await;
|
|
let (status, _): (StatusCode, Value) =
|
|
send(&mut app, post_json("/api/v1/auth/logout", json!({}))).await;
|
|
assert_eq!(status, StatusCode::UNAUTHORIZED);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn register_then_login_and_access_me() {
|
|
let (mut app, _) = test_app().await;
|
|
let (access, _) = register_and_login(
|
|
&mut app,
|
|
"lifecycle@test.com",
|
|
"lifecycleuser",
|
|
"Password123",
|
|
)
|
|
.await;
|
|
|
|
let (status, body) = send(&mut app, get_auth("/api/v1/users/me", &access)).await;
|
|
assert!(status.is_success(), "{status} {body:?}");
|
|
assert_eq!(body["data"]["username"], "lifecycleuser");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn register_duplicate_username() {
|
|
let (mut app, _) = test_app().await;
|
|
let req_body =
|
|
json!({"email": "dupu1@test.com", "username": "dupuser", "password": "Password123"});
|
|
let (s, _): (StatusCode, Value) =
|
|
send(&mut app, post_json("/api/v1/auth/register", req_body)).await;
|
|
assert!(s.is_success());
|
|
|
|
let (status, body): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json(
|
|
"/api/v1/auth/register",
|
|
json!({"email": "dupu2@test.com", "username": "dupuser", "password": "Password123"}),
|
|
),
|
|
)
|
|
.await;
|
|
assert_eq!(status, StatusCode::CONFLICT);
|
|
assert_eq!(body["code"], 40900);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn refresh_token_after_password_change() {
|
|
let (mut app, _) = test_app().await;
|
|
let (access, refresh) =
|
|
register_and_login(&mut app, "rpc@test.com", "rpcuser", "OldPass123").await;
|
|
|
|
let (status, _): (StatusCode, Value) = send(
|
|
&mut app,
|
|
put_json_auth(
|
|
"/api/v1/users/me/password",
|
|
json!({"old_password": "OldPass123", "new_password": "NewPass456"}),
|
|
&access,
|
|
),
|
|
)
|
|
.await;
|
|
assert!(status.is_success());
|
|
|
|
let (status, _): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json("/api/v1/auth/refresh", json!({"refresh_token": refresh})),
|
|
)
|
|
.await;
|
|
assert_eq!(
|
|
status,
|
|
StatusCode::UNAUTHORIZED,
|
|
"old refresh token should be invalidated after password change"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn logout_invalidates_access() {
|
|
let (mut app, _) = test_app().await;
|
|
let (access, _) =
|
|
register_and_login(&mut app, "loinv@test.com", "loinvuser", "Password123").await;
|
|
|
|
let (status, _): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json_auth("/api/v1/auth/logout", json!({}), &access),
|
|
)
|
|
.await;
|
|
assert!(status.is_success());
|
|
|
|
let (status, _): (StatusCode, Value) =
|
|
send(&mut app, get_auth("/api/v1/users/me", &access)).await;
|
|
assert!(
|
|
status.is_success(),
|
|
"JWT is stateless — still valid after logout"
|
|
);
|
|
}
|