#[derive(Clone)]
pub struct Server {
address: (String, u16),
log_level: String,
db_path: String,
reset_db: bool,
admin_username: String,
admin_password: String,
}
impl Server {
pub fn new(
address: (String, u16),
log_level: String,
db_path: String,
reset_db: bool,
admin_username: String,
admin_password: String,
) -> Self {
Server {
address,
log_level,
db_path,
reset_db,
admin_username,
admin_password,
}
}
pub fn address(&self) -> (String, u16) {
self.address.clone()
}
pub fn log_level(&self) -> &str {
&self.log_level
}
pub fn db_path(&self) -> &str {
&self.db_path
}
pub fn maybe_reset_database(&self) {
if !self.reset_db {
return;
}
log::warn!(
"RESET_DB is set to true, deleting database file: {}",
self.db_path
);
if std::path::Path::new(&self.db_path).exists() {
if let Err(e) = std::fs::remove_file(&self.db_path) {
log::error!("Failed to delete database file: {e}");
} else {
log::info!("Database file deleted successfully");
}
}
}
pub fn admin_username(&self) -> &str {
&self.admin_username
}
pub fn admin_password(&self) -> &str {
&self.admin_password
}
}
impl std::fmt::Display for Server {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", ascii(self))
}
}
pub fn from_env() -> Server {
let port = std::env::var("PORT")
.unwrap_or_else(|_| "8080".to_string())
.parse()
.unwrap_or(8080);
let log_level = std::env::var("LOG_LEVEL").unwrap_or_else(|_| "info".to_string());
let db_path = std::env::var("DB_PATH").unwrap_or_else(|_| "hodis.db".to_string());
let reset_db = std::env::var("RESET_DB").unwrap_or_default() == "true";
let admin_username = std::env::var("ADMIN_USERNAME").unwrap_or_else(|_| "admin".to_string());
let admin_password = std::env::var("ADMIN_PASSWORD").unwrap_or_else(|_| "admin".to_string());
Server::new(
("0.0.0.0".to_string(), port),
log_level,
db_path,
reset_db,
admin_username,
admin_password,
)
}
fn ascii(server: &Server) -> String {
let (_, port) = server.address();
let url = format!("http://localhost:{port}");
let version = env!("CARGO_PKG_VERSION");
format!(
"
▐▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▌
▐ HOIS Preseason Challenge ▌
▐▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▌
Server running at: {url}
Version: {version}
"
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_server_new() {
let server = Server::new(
("127.0.0.1".to_string(), 8080),
"debug".to_string(),
"hodis.db".to_string(),
false,
"admin".to_string(),
"pass".to_string(),
);
assert_eq!(server.address(), ("127.0.0.1".to_string(), 8080));
assert_eq!(server.log_level(), "debug");
assert_eq!(server.db_path(), "hodis.db");
}
#[test]
fn test_server_clone() {
let server = Server::new(
("0.0.0.0".to_string(), 80),
"info".to_string(),
"hodis.db".to_string(),
false,
"admin".to_string(),
"pass".to_string(),
);
let cloned = server.clone();
assert_eq!(cloned.db_path(), server.db_path());
assert_eq!(cloned.log_level(), server.log_level());
}
#[test]
fn test_maybe_reset_database_no_flag() {
let server = Server::new(
("0.0.0.0".to_string(), 80),
"info".to_string(),
"/tmp/hodis_test_no_reset.db".to_string(),
false,
"admin".to_string(),
"pass".to_string(),
);
server.maybe_reset_database();
}
#[test]
fn test_address_returns_clone() {
let server = Server::new(
("0.0.0.0".to_string(), 3000),
"info".to_string(),
"hodis.db".to_string(),
false,
"admin".to_string(),
"pass".to_string(),
);
let addr = server.address();
assert_eq!(addr, ("0.0.0.0".to_string(), 3000));
}
#[test]
fn test_admin_credentials() {
let server = Server::new(
("0.0.0.0".to_string(), 80),
"info".to_string(),
"hodis.db".to_string(),
false,
"superadmin".to_string(),
"secret123".to_string(),
);
assert_eq!(server.admin_username(), "superadmin");
assert_eq!(server.admin_password(), "secret123");
}
}