bda1ef251a
calling this v0.4.0
199 lines
6.7 KiB
Rust
199 lines
6.7 KiB
Rust
use backend::rocket_builder;
|
|
use backend::repo::mock::{MockUserRepo, MockTokenRepo};
|
|
use backend::repo::message_repo::MessageRepository;
|
|
use backend::svc::chat_svc::ChatService;
|
|
use backend::repo::user_repo::UserRepository;
|
|
use backend::repo::{Repo, AccessTokenRepoTrait};
|
|
use rocket::local::asynchronous::Client;
|
|
use rocket::http::{Status, ContentType};
|
|
use serde_json::json;
|
|
use std::sync::{Arc, Mutex};
|
|
use sqlx::PgPool;
|
|
use chrono::Utc;
|
|
use backend::svc::llm_service::LlmService;
|
|
|
|
async fn test_rocket() -> rocket::Rocket<rocket::Build> {
|
|
let users = Arc::new(MockUserRepo { users: Mutex::new(vec![]) });
|
|
let tokens = Arc::new(MockTokenRepo { tokens: Mutex::new(vec![]) });
|
|
|
|
let pool = PgPool::connect_lazy("postgres://localhost/unused").unwrap();
|
|
let messages = MessageRepository::new(pool.clone());
|
|
let user_repo = Arc::new(UserRepository::new(pool));
|
|
let llm_service = LlmService::new();
|
|
let chat_service = ChatService::new(32, messages, user_repo, llm_service);
|
|
|
|
rocket_builder(users, tokens, chat_service)
|
|
}
|
|
|
|
#[rocket::async_test]
|
|
async fn test_unauthorized_access() {
|
|
let client = Client::tracked(test_rocket().await).await.expect("valid rocket instance");
|
|
|
|
// Attempt to access a protected endpoint without authentication
|
|
let response = client.patch("/api/settings/display_name").dispatch().await;
|
|
assert_eq!(response.status(), Status::Unauthorized);
|
|
|
|
let response = client.post("/api/settings/password").dispatch().await;
|
|
assert_eq!(response.status(), Status::Unauthorized);
|
|
|
|
let response = client.delete("/api/settings").dispatch().await;
|
|
assert_eq!(response.status(), Status::Unauthorized);
|
|
}
|
|
|
|
#[rocket::async_test]
|
|
async fn test_signup_invalid_token() {
|
|
let client = Client::tracked(test_rocket().await).await.expect("valid rocket instance");
|
|
|
|
let signup_data = json!({
|
|
"email": "test@example.com",
|
|
"username": "testuser",
|
|
"password": "password123",
|
|
"access_token": "invalid-token"
|
|
});
|
|
|
|
let response = client.post("/api/signup")
|
|
.header(ContentType::JSON)
|
|
.body(signup_data.to_string())
|
|
.dispatch()
|
|
.await;
|
|
|
|
assert_eq!(response.status(), Status::Unauthorized);
|
|
}
|
|
|
|
#[rocket::async_test]
|
|
async fn test_login_invalid_credentials() {
|
|
let client = Client::tracked(test_rocket().await).await.expect("valid rocket instance");
|
|
|
|
let login_data = json!({
|
|
"username": "nonexistent",
|
|
"password": "wrongpassword"
|
|
});
|
|
|
|
let response = client.post("/api/login")
|
|
.header(ContentType::JSON)
|
|
.body(login_data.to_string())
|
|
.dispatch()
|
|
.await;
|
|
|
|
assert_eq!(response.status(), Status::Unauthorized);
|
|
}
|
|
|
|
#[rocket::async_test]
|
|
async fn test_full_auth_flow() {
|
|
let users = Arc::new(MockUserRepo { users: Mutex::new(vec![]) });
|
|
let tokens = Arc::new(MockTokenRepo { tokens: Mutex::new(vec![]) });
|
|
let pool = PgPool::connect_lazy("postgres://localhost/unused").unwrap();
|
|
let messages = MessageRepository::new(pool.clone());
|
|
let user_repo = Arc::new(UserRepository::new(pool));
|
|
let llm_service = LlmService::new();
|
|
let chat_service = ChatService::new(32, messages, user_repo, llm_service);
|
|
|
|
let token_code = "valid-token";
|
|
tokens.create_new(1, "test", token_code, 1, Utc::now(), Utc::now()).await.unwrap();
|
|
|
|
let client = Client::tracked(rocket_builder(users, tokens, chat_service)).await.expect("valid rocket instance");
|
|
|
|
// 1. Signup
|
|
let signup_data = json!({
|
|
"email": "test@example.com",
|
|
"username": "testuser",
|
|
"password": "password123",
|
|
"access_token": token_code
|
|
});
|
|
|
|
let response = client.post("/api/signup")
|
|
.header(ContentType::JSON)
|
|
.body(signup_data.to_string())
|
|
.dispatch()
|
|
.await;
|
|
|
|
assert_eq!(response.status(), Status::Ok);
|
|
let body = response.into_string().await.unwrap();
|
|
assert!(body.contains("token"));
|
|
|
|
// 2. Login
|
|
let login_data = json!({
|
|
"username": "testuser",
|
|
"password": "password123"
|
|
});
|
|
|
|
let response = client.post("/api/login")
|
|
.header(ContentType::JSON)
|
|
.body(login_data.to_string())
|
|
.dispatch()
|
|
.await;
|
|
|
|
assert_eq!(response.status(), Status::Ok);
|
|
let body = response.into_string().await.unwrap();
|
|
assert!(body.contains("token"));
|
|
}
|
|
|
|
#[rocket::async_test]
|
|
async fn test_delete_account_security() {
|
|
let users = Arc::new(MockUserRepo { users: Mutex::new(vec![]) });
|
|
let tokens = Arc::new(MockTokenRepo { tokens: Mutex::new(vec![]) });
|
|
let pool = PgPool::connect_lazy("postgres://localhost/unused").unwrap();
|
|
let messages = MessageRepository::new(pool.clone());
|
|
let user_repo = Arc::new(UserRepository::new(pool));
|
|
let llm_service = LlmService::new();
|
|
let chat_service = ChatService::new(32, messages, user_repo, llm_service);
|
|
|
|
let client = Client::tracked(rocket_builder(users.clone(), tokens.clone(), chat_service)).await.expect("valid rocket instance");
|
|
|
|
let token_code = "valid-token";
|
|
tokens.create_new(1, "test", token_code, 1, Utc::now(), Utc::now()).await.unwrap();
|
|
|
|
client.post("/api/signup")
|
|
.header(ContentType::JSON)
|
|
.body(json!({
|
|
"email": "test@example.com",
|
|
"username": "testuser",
|
|
"password": "password123",
|
|
"access_token": token_code
|
|
}).to_string())
|
|
.dispatch()
|
|
.await;
|
|
|
|
// Login to get JWT
|
|
let login_res = client.post("/api/login")
|
|
.header(ContentType::JSON)
|
|
.body(json!({
|
|
"username": "testuser",
|
|
"password": "password123"
|
|
}).to_string())
|
|
.dispatch()
|
|
.await;
|
|
|
|
let auth_resp: serde_json::Value = serde_json::from_str(&login_res.into_string().await.unwrap()).unwrap();
|
|
let jwt = auth_resp["token"].as_str().unwrap();
|
|
|
|
// 1. Delete with WRONG password
|
|
let response = client.delete("/api/settings")
|
|
.header(ContentType::JSON)
|
|
.header(rocket::http::Header::new("Authorization", format!("Bearer {}", jwt)))
|
|
.body(json!({
|
|
"password": "wrongpassword",
|
|
"totp_code": null
|
|
}).to_string())
|
|
.dispatch()
|
|
.await;
|
|
|
|
assert_eq!(response.status(), Status::Unauthorized);
|
|
|
|
// 2. Delete with CORRECT password
|
|
let response = client.delete("/api/settings")
|
|
.header(ContentType::JSON)
|
|
.header(rocket::http::Header::new("Authorization", format!("Bearer {}", jwt)))
|
|
.body(json!({
|
|
"password": "password123",
|
|
"totp_code": null
|
|
}).to_string())
|
|
.dispatch()
|
|
.await;
|
|
|
|
assert_eq!(response.status(), Status::Ok);
|
|
|
|
// Verify user is gone
|
|
assert!(users.users.lock().unwrap().is_empty());
|
|
}
|