85 lines
3 KiB
Rust
85 lines
3 KiB
Rust
use std::{net::{Ipv4Addr, SocketAddrV4, TcpListener}, sync::Arc, time::{SystemTime, UNIX_EPOCH}};
|
|
|
|
use sea_orm::{ActiveModelTrait, ActiveValue::{NotSet, Set}, ColumnTrait, ConnectionTrait, Database, DatabaseConnection, EntityTrait, QueryFilter};
|
|
|
|
use alexandria::{create_tables, entities::{owner, prelude::*, user}, routes::auth::{generate_token_from_claims, Claims, DEFAULT_TOKEN_EXPIRY_TIME}, run_server, utils::auth::hash_password};
|
|
|
|
pub struct SetupData {
|
|
/// A valid JWT for testing features that need authentication
|
|
pub jwt: String,
|
|
pub api_path: String
|
|
}
|
|
|
|
/// Common setup function for tests that require a database and server setup
|
|
pub async fn setup() -> SetupData {
|
|
let _ = pretty_env_logger::try_init();
|
|
|
|
let db: Arc<DatabaseConnection> = Arc::new(
|
|
match Database::connect(format!("sqlite::memory:?mode=rwc")).await {
|
|
Ok(c) => c,
|
|
Err(e) => {
|
|
panic!("Error while opening fatabase: {}", e.to_string())
|
|
}
|
|
});
|
|
|
|
create_tables(db.as_ref()).await.expect("Create tables should not fail");
|
|
|
|
let port = free_local_ipv4_port().expect("Could not get a free port");
|
|
let db_c = db.clone();
|
|
tokio::spawn(async move {
|
|
run_server(db_c, port, false).await;
|
|
});
|
|
|
|
create_user(db.as_ref(), "test_username", "test_password").await;
|
|
|
|
|
|
let unix_timestamp = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time should go forward").as_secs();
|
|
|
|
let claims = Claims {
|
|
sub: "test_username".to_string(),
|
|
exp: unix_timestamp + DEFAULT_TOKEN_EXPIRY_TIME,
|
|
user_id: 1
|
|
};
|
|
|
|
SetupData {
|
|
jwt: generate_token_from_claims(claims),
|
|
api_path: format!("http://0.0.0.0:{port}/api")
|
|
}
|
|
}
|
|
|
|
|
|
fn free_local_ipv4_port() -> Option<u16> {
|
|
let socket = SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0);
|
|
TcpListener::bind(socket)
|
|
.and_then(|listener| listener.local_addr())
|
|
.map(|addr| addr.port())
|
|
.ok()
|
|
}
|
|
|
|
async fn create_user<C>(db_conn: &C, username_t: impl ToString, password_t: impl ToString)
|
|
where C: ConnectionTrait {
|
|
let username = username_t.to_string();
|
|
if User::find().filter(user::Column::Username.eq(username.clone())).one(db_conn).await.is_ok_and(|r| r.is_some()) {
|
|
panic!("Username {username} already in use");
|
|
} else {
|
|
let password = password_t.to_string();
|
|
let mut new_user = user::ActiveModel {
|
|
id: NotSet,
|
|
username: Set(username.clone()),
|
|
hashed_password: Set(hash_password(password)),
|
|
owner_id: Set(None)
|
|
};
|
|
let res = new_user.clone().insert(db_conn).await.unwrap();
|
|
|
|
let new_owner = owner::ActiveModel {
|
|
id: NotSet,
|
|
user_id: Set(res.id),
|
|
first_name: Set(format!("{username} first name")),
|
|
last_name: Set(format!("{username} last name")),
|
|
contact: Set(format!("{username}@mail.com"))
|
|
};
|
|
let owner_res = new_owner.insert(db_conn).await.unwrap();
|
|
new_user.owner_id = Set(Some(owner_res.id));
|
|
let _ = new_user.update(db_conn);
|
|
}
|
|
}
|