summaryrefslogtreecommitdiffstats
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs99
1 files changed, 97 insertions, 2 deletions
diff --git a/src/main.rs b/src/main.rs
index e7a11a9..a96b41b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,98 @@
1fn main() { 1mod auth;
2 println!("Hello, world!"); 2mod config;
3mod db;
4mod docker;
5mod models;
6mod rcon;
7mod routes;
8
9use tracing_subscriber::EnvFilter;
10
11use crate::db::Database;
12use crate::docker::DockerManager;
13use crate::routes::AppState;
14
15#[tokio::main]
16async fn main() {
17 tracing_subscriber::fmt()
18 .with_env_filter(EnvFilter::try_from_default_env().unwrap_or_else(|_| "info".into()))
19 .init();
20
21 let config = config::Config::load().unwrap_or_else(|e| {
22 eprintln!("Configuration error: {e}");
23 eprintln!("Please create a config.toml file based on the example.");
24 std::process::exit(1);
25 });
26
27 if !config.server_directory.exists() {
28 eprintln!(
29 "Server directory does not exist: {}",
30 config.server_directory.display()
31 );
32 eprintln!("Please create it or update config.toml.");
33 std::process::exit(1);
34 }
35
36 let db_path = config.server_directory.join("mcui.db");
37 let db = Database::open(&db_path).unwrap_or_else(|e| {
38 eprintln!("Failed to open database: {e}");
39 std::process::exit(1);
40 });
41
42 bootstrap_superuser(&db, &config);
43
44 let docker = DockerManager::new(config.clone()).unwrap_or_else(|e| {
45 eprintln!("Failed to connect to Docker: {e}");
46 eprintln!("Is the Docker daemon running and accessible?");
47 std::process::exit(1);
48 });
49
50 let state = AppState {
51 config: config.clone(),
52 db: db.clone(),
53 docker,
54 };
55
56 let router = routes::build_router(state);
57
58 let addr = format!("127.0.0.1:{}", config.webui_port);
59 tracing::info!("Starting Minecraft UI on http://{addr}");
60
61 let listener = tokio::net::TcpListener::bind(&addr)
62 .await
63 .unwrap_or_else(|e| {
64 eprintln!("Failed to bind to {addr}: {e}");
65 std::process::exit(1);
66 });
67
68 axum::serve(listener, router).await.unwrap_or_else(|e| {
69 eprintln!("Server error: {e}");
70 });
71}
72
73fn bootstrap_superuser(db: &Database, config: &config::Config) {
74 let conn = db.conn();
75 let count: i32 = conn
76 .query_row("SELECT COUNT(*) FROM accounts", [], |row| row.get(0))
77 .unwrap_or(0);
78 drop(conn);
79
80 if count == 0 {
81 let hash = auth::hash_password(&config.initial_superuser_password)
82 .expect("Failed to hash initial password");
83
84 let conn = db.conn();
85 conn.execute(
86 "INSERT INTO accounts (username, password, is_superuser, password_change_required)
87 VALUES (?1, ?2, 1, 1)",
88 rusqlite::params![config.initial_superuser, hash],
89 )
90 .expect("Failed to create initial superuser");
91 drop(conn);
92
93 tracing::info!(
94 "Created initial superuser '{}' (password change required on first login)",
95 config.initial_superuser
96 );
97 }
3} 98}