feat(backend): replace auth stub with real session, create users and sessions tables
This commit is contained in:
@@ -93,36 +93,71 @@ mod tests {
|
||||
TestServer,
|
||||
multipart::{MultipartForm, Part},
|
||||
};
|
||||
use rand::RngExt;
|
||||
use serde_json::json;
|
||||
use sqlx::PgPool;
|
||||
use tower_cookies::CookieManagerLayer;
|
||||
|
||||
use crate::{
|
||||
model::FileRepository,
|
||||
model::{FileRepository, UserRepository},
|
||||
web::{
|
||||
mw_auth::{mw_ctx_resolver, mw_require_auth},
|
||||
routes_file::routes_file,
|
||||
},
|
||||
};
|
||||
|
||||
// Cookie format: user-[user-id].[expiration].[signature]
|
||||
const AUTH_COOKIE: &str = "auth-token=user-1.0123456789.a1b2c3d4e5f6";
|
||||
const BAD_AUTH_COOKIE: &str = "auth-token=user-1.0123456789";
|
||||
const BAD_AUTH_COOKIE: &str = "auth-token=user-0123456789";
|
||||
|
||||
async fn file_repository() -> FileRepository {
|
||||
dotenvy::dotenv().ok();
|
||||
let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
||||
let pool = PgPool::connect(&database_url).await.unwrap();
|
||||
let file_repository = FileRepository::new(pool).unwrap();
|
||||
file_repository
|
||||
}
|
||||
|
||||
async fn user_repository() -> UserRepository {
|
||||
dotenvy::dotenv().ok();
|
||||
let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
||||
let pool = PgPool::connect(&database_url).await.unwrap();
|
||||
let user_repository = UserRepository::new(pool).unwrap();
|
||||
user_repository
|
||||
}
|
||||
|
||||
async fn test_server() -> TestServer {
|
||||
let file_repository = FileRepository::new().await.unwrap();
|
||||
let user_repository = user_repository().await;
|
||||
let file_repository = file_repository().await;
|
||||
let routes_file =
|
||||
routes_file(file_repository.clone()).route_layer(middleware::from_fn(mw_require_auth));
|
||||
let app = Router::new()
|
||||
.nest("/api", routes_file)
|
||||
.layer(middleware::from_fn_with_state(
|
||||
file_repository,
|
||||
user_repository,
|
||||
mw_ctx_resolver,
|
||||
))
|
||||
.layer(CookieManagerLayer::new());
|
||||
|
||||
TestServer::new(app)
|
||||
}
|
||||
|
||||
async fn create_test_session(user_repository: &UserRepository) -> String {
|
||||
let user = user_repository
|
||||
.create_user("testuser".to_string(), "hash".to_string())
|
||||
.await
|
||||
.unwrap();
|
||||
let token: String = rand::rng()
|
||||
.sample_iter(&rand::distr::Alphanumeric)
|
||||
.take(64)
|
||||
.map(char::from)
|
||||
.collect();
|
||||
let expires_at = chrono::Utc::now() + chrono::Duration::days(1);
|
||||
user_repository
|
||||
.create_session(user.id, token.clone(), expires_at)
|
||||
.await
|
||||
.unwrap();
|
||||
token
|
||||
}
|
||||
|
||||
async fn truncate(pool: &PgPool) {
|
||||
sqlx::query!("TRUNCATE TABLE file_records")
|
||||
.execute(pool)
|
||||
@@ -149,7 +184,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
#[serial_test::serial]
|
||||
async fn test_requires_auth_post() {
|
||||
let file_repository = FileRepository::new().await.unwrap();
|
||||
let file_repository = file_repository().await;
|
||||
truncate(&file_repository.pool).await;
|
||||
|
||||
let server = test_server().await;
|
||||
@@ -167,13 +202,15 @@ mod tests {
|
||||
#[tokio::test]
|
||||
#[serial_test::serial]
|
||||
async fn test_list_files_empty() {
|
||||
let file_repository = FileRepository::new().await.unwrap();
|
||||
let user_repository = user_repository().await;
|
||||
let token = create_test_session(&user_repository).await;
|
||||
let file_repository = file_repository().await;
|
||||
truncate(&file_repository.pool).await;
|
||||
|
||||
let server = test_server().await;
|
||||
server
|
||||
.get("/api/files")
|
||||
.add_header(axum::http::header::COOKIE, AUTH_COOKIE)
|
||||
.add_header(axum::http::header::COOKIE, format!("auth-token={token}"))
|
||||
.await
|
||||
.assert_status_ok()
|
||||
.assert_json(&json!([]));
|
||||
@@ -182,13 +219,15 @@ mod tests {
|
||||
#[tokio::test]
|
||||
#[serial_test::serial]
|
||||
async fn test_upload_and_list_files() {
|
||||
let file_repository = FileRepository::new().await.unwrap();
|
||||
let user_repository = user_repository().await;
|
||||
let token = create_test_session(&user_repository).await;
|
||||
let file_repository = file_repository().await;
|
||||
truncate(&file_repository.pool).await;
|
||||
|
||||
let server = test_server().await;
|
||||
let res = server
|
||||
.post("/api/files")
|
||||
.add_header(axum::http::header::COOKIE, AUTH_COOKIE)
|
||||
.add_header(axum::http::header::COOKIE, format!("auth-token={token}"))
|
||||
.multipart(MultipartForm::new().add_part(
|
||||
"file",
|
||||
Part::bytes(b"fake_bytes".to_vec()).file_name("a.jpg"),
|
||||
@@ -201,7 +240,7 @@ mod tests {
|
||||
|
||||
let list = server
|
||||
.get("/api/files")
|
||||
.add_header(axum::http::header::COOKIE, AUTH_COOKIE)
|
||||
.add_header(axum::http::header::COOKIE, format!("auth-token={token}"))
|
||||
.await
|
||||
.json::<serde_json::Value>();
|
||||
|
||||
@@ -212,13 +251,15 @@ mod tests {
|
||||
#[tokio::test]
|
||||
#[serial_test::serial]
|
||||
async fn test_download_file() {
|
||||
let file_repository = FileRepository::new().await.unwrap();
|
||||
let user_repository = user_repository().await;
|
||||
let token = create_test_session(&user_repository).await;
|
||||
let file_repository = file_repository().await;
|
||||
truncate(&file_repository.pool).await;
|
||||
|
||||
let server = test_server().await;
|
||||
let post_res = server
|
||||
.post("/api/files")
|
||||
.add_header(axum::http::header::COOKIE, AUTH_COOKIE)
|
||||
.add_header(axum::http::header::COOKIE, format!("auth-token={token}"))
|
||||
.multipart(MultipartForm::new().add_part(
|
||||
"file",
|
||||
Part::bytes(b"fake_bytes".to_vec()).file_name("a.jpg"),
|
||||
@@ -227,7 +268,7 @@ mod tests {
|
||||
let id = post_res.json::<serde_json::Value>()["id"].as_i64().unwrap();
|
||||
let res = server
|
||||
.get(&format!("/api/files/{id}/download"))
|
||||
.add_header(axum::http::header::COOKIE, AUTH_COOKIE)
|
||||
.add_header(axum::http::header::COOKIE, format!("auth-token={token}"))
|
||||
.await;
|
||||
|
||||
res.assert_status_ok();
|
||||
@@ -238,10 +279,12 @@ mod tests {
|
||||
#[tokio::test]
|
||||
#[serial_test::serial]
|
||||
async fn test_download_file_not_found() {
|
||||
let user_repository = user_repository().await;
|
||||
let token = create_test_session(&user_repository).await;
|
||||
let server = test_server().await;
|
||||
server
|
||||
.get("/api/files/99/download")
|
||||
.add_header(axum::http::header::COOKIE, AUTH_COOKIE)
|
||||
.add_header(axum::http::header::COOKIE, format!("auth-token={token}"))
|
||||
.await
|
||||
.assert_status_not_found();
|
||||
}
|
||||
@@ -249,13 +292,15 @@ mod tests {
|
||||
#[tokio::test]
|
||||
#[serial_test::serial]
|
||||
async fn test_delete_file() {
|
||||
let file_repository = FileRepository::new().await.unwrap();
|
||||
let user_repository = user_repository().await;
|
||||
let token = create_test_session(&user_repository).await;
|
||||
let file_repository = file_repository().await;
|
||||
truncate(&file_repository.pool).await;
|
||||
|
||||
let server = test_server().await;
|
||||
let post_res = server
|
||||
.post("/api/files")
|
||||
.add_header(axum::http::header::COOKIE, AUTH_COOKIE)
|
||||
.add_header(axum::http::header::COOKIE, format!("auth-token={token}"))
|
||||
.multipart(MultipartForm::new().add_part(
|
||||
"file",
|
||||
Part::bytes(b"fake_bytes".to_vec()).file_name("a.jpg"),
|
||||
@@ -265,13 +310,13 @@ mod tests {
|
||||
|
||||
server
|
||||
.delete(&format!("/api/files/{id}"))
|
||||
.add_header(axum::http::header::COOKIE, AUTH_COOKIE)
|
||||
.add_header(axum::http::header::COOKIE, format!("auth-token={token}"))
|
||||
.await
|
||||
.assert_status_ok();
|
||||
|
||||
server
|
||||
.get(&format!("/api/files/{id}"))
|
||||
.add_header(axum::http::header::COOKIE, AUTH_COOKIE)
|
||||
.add_header(axum::http::header::COOKIE, format!("auth-token={token}"))
|
||||
.await
|
||||
.assert_status_not_found();
|
||||
|
||||
@@ -281,10 +326,12 @@ mod tests {
|
||||
#[tokio::test]
|
||||
#[serial_test::serial]
|
||||
async fn test_delete_file_not_found() {
|
||||
let user_repository = user_repository().await;
|
||||
let token = create_test_session(&user_repository).await;
|
||||
let server = test_server().await;
|
||||
server
|
||||
.delete("/api/files/99")
|
||||
.add_header(axum::http::header::COOKIE, AUTH_COOKIE)
|
||||
.add_header(axum::http::header::COOKIE, format!("auth-token={token}"))
|
||||
.await
|
||||
.assert_status_not_found();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user