this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

A lot

+326 -239
+51 -48
Cargo.lock
··· 18 18 checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 19 19 20 20 [[package]] 21 - name = "ahash" 22 - version = "0.8.11" 23 - source = "registry+https://github.com/rust-lang/crates.io-index" 24 - checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" 25 - dependencies = [ 26 - "cfg-if", 27 - "once_cell", 28 - "version_check", 29 - "zerocopy 0.7.35", 30 - ] 31 - 32 - [[package]] 33 21 name = "aho-corasick" 34 22 version = "1.1.3" 35 23 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 37 25 dependencies = [ 38 26 "memchr", 39 27 ] 40 - 41 - [[package]] 42 - name = "allocator-api2" 43 - version = "0.2.21" 44 - source = "registry+https://github.com/rust-lang/crates.io-index" 45 - checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" 46 28 47 29 [[package]] 48 30 name = "async-stream" ··· 403 385 checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 404 386 405 387 [[package]] 388 + name = "foldhash" 389 + version = "0.1.5" 390 + source = "registry+https://github.com/rust-lang/crates.io-index" 391 + checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" 392 + 393 + [[package]] 406 394 name = "form_urlencoded" 407 395 version = "1.2.1" 408 396 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 567 555 568 556 [[package]] 569 557 name = "hashbrown" 570 - version = "0.14.5" 571 - source = "registry+https://github.com/rust-lang/crates.io-index" 572 - checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 573 - dependencies = [ 574 - "ahash", 575 - "allocator-api2", 576 - ] 577 - 578 - [[package]] 579 - name = "hashbrown" 580 558 version = "0.15.2" 581 559 source = "registry+https://github.com/rust-lang/crates.io-index" 582 560 checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" 561 + dependencies = [ 562 + "foldhash", 563 + ] 583 564 584 565 [[package]] 585 566 name = "hashlink" 586 - version = "0.8.4" 567 + version = "0.10.0" 587 568 source = "registry+https://github.com/rust-lang/crates.io-index" 588 - checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" 569 + checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" 589 570 dependencies = [ 590 - "hashbrown 0.14.5", 571 + "hashbrown", 591 572 ] 592 573 593 574 [[package]] ··· 826 807 checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" 827 808 dependencies = [ 828 809 "equivalent", 829 - "hashbrown 0.15.2", 810 + "hashbrown", 830 811 "serde", 831 812 ] 832 813 ··· 886 867 887 868 [[package]] 888 869 name = "libsqlite3-sys" 889 - version = "0.27.0" 870 + version = "0.32.0" 890 871 source = "registry+https://github.com/rust-lang/crates.io-index" 891 - checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716" 872 + checksum = "fbb8270bb4060bd76c6e96f20c52d80620f1d82a3470885694e41e0f81ef6fe7" 892 873 dependencies = [ 893 - "cc", 894 874 "pkg-config", 895 875 "vcpkg", 896 876 ] ··· 945 925 "bcrypt", 946 926 "cynthia_con", 947 927 "dotenv", 928 + "r2d2", 929 + "r2d2_sqlite", 948 930 "rocket", 949 931 "rocket_ws", 950 932 "serde", 951 933 "serde_json", 952 934 "tokio", 953 935 "tokio-postgres", 954 - "tokio-sqlite", 955 936 "tracing", 956 937 "tracing-subscriber", 957 938 "uuid", ··· 1236 1217 checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" 1237 1218 dependencies = [ 1238 1219 "proc-macro2", 1220 + ] 1221 + 1222 + [[package]] 1223 + name = "r2d2" 1224 + version = "0.8.10" 1225 + source = "registry+https://github.com/rust-lang/crates.io-index" 1226 + checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" 1227 + dependencies = [ 1228 + "log", 1229 + "parking_lot", 1230 + "scheduled-thread-pool", 1231 + ] 1232 + 1233 + [[package]] 1234 + name = "r2d2_sqlite" 1235 + version = "0.27.0" 1236 + source = "registry+https://github.com/rust-lang/crates.io-index" 1237 + checksum = "180da684f0a188977d3968f139eb44260192ef8d9a5b7b7cbd01d881e0353179" 1238 + dependencies = [ 1239 + "r2d2", 1240 + "rusqlite", 1241 + "uuid", 1239 1242 ] 1240 1243 1241 1244 [[package]] ··· 1464 1467 1465 1468 [[package]] 1466 1469 name = "rusqlite" 1467 - version = "0.30.0" 1470 + version = "0.34.0" 1468 1471 source = "registry+https://github.com/rust-lang/crates.io-index" 1469 - checksum = "a78046161564f5e7cd9008aff3b2990b3850dc8e0349119b98e8f251e099f24d" 1472 + checksum = "37e34486da88d8e051c7c0e23c3f15fd806ea8546260aa2fec247e97242ec143" 1470 1473 dependencies = [ 1471 1474 "bitflags", 1472 1475 "fallible-iterator 0.3.0", ··· 1506 1509 version = "1.0.19" 1507 1510 source = "registry+https://github.com/rust-lang/crates.io-index" 1508 1511 checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" 1512 + 1513 + [[package]] 1514 + name = "scheduled-thread-pool" 1515 + version = "0.2.7" 1516 + source = "registry+https://github.com/rust-lang/crates.io-index" 1517 + checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" 1518 + dependencies = [ 1519 + "parking_lot", 1520 + ] 1509 1521 1510 1522 [[package]] 1511 1523 name = "scoped-tls" ··· 1872 1884 ] 1873 1885 1874 1886 [[package]] 1875 - name = "tokio-sqlite" 1876 - version = "0.1.5" 1877 - source = "registry+https://github.com/rust-lang/crates.io-index" 1878 - checksum = "2a6ff401bbb8fa20cc0f6c13332d7b52f1e82b130362ff1a2b9943fa2b26f41b" 1879 - dependencies = [ 1880 - "rusqlite", 1881 - "tokio", 1882 - ] 1883 - 1884 - [[package]] 1885 1887 name = "tokio-stream" 1886 1888 version = "0.1.17" 1887 1889 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2137 2139 checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" 2138 2140 dependencies = [ 2139 2141 "getrandom 0.3.1", 2142 + "rand 0.9.0", 2140 2143 "serde", 2141 2144 ] 2142 2145
+1 -1
README.MD
··· 17 17 | `LUMINA_DB_TYPE` | `"sqlite"` (not recommended for production) | The kind of database to use. Options are `postgres` or `sqlite`.<br /><br /><br />**OPTIONS:**<br />_With SQLite:_<br />- `LUMINA_SQLITE_FILE` `"instance.sqlite"` SQLite file to connect to. Always a relative path from the instance folder.<br /><br />_With PostGres DB:_<br />- `LUMINA_POSTGRES_PORT` `"5432"` The port to contact the database on. <br>- `LUMINA_POSTGRES_HOST` `"localhost"` The address to contact the database on.<br>- `LUMINA_POSTGRES_USERNAME` `"lumina"` The username to log in to the database with.<br>- `LUMINA_POSTGRES_PASSWORD` (none) The password to log in to the database with. If not set, Lumina will try without.<br>- `LUMINA_POSTGRES_DATABASE` `"lumina_config"` The database to use. <br> | 18 18 | `LUMINA_DB_SALT` | `"sal"` | The salting to use for some data on the database. | 19 19 | `LUMINA_SERVER_PORT` | `"8085"` | Port for Lumina to accept HTTP requests on. | 20 - | `LUMINA_SERVER_ADDR` | `"localhost"` | Address for Lumina to accept HTTP requests on. | 20 + | `LUMINA_SERVER_ADDR` | `127.0.0.1` | Address for Lumina to accept HTTP requests on. (usually `127.0.0.1` or `0.0.0.0`) | 21 21 | `LUMINA_SERVER_HTTPS` | `"false"` | Wether to use 'https' rather than 'http' in links, etc. (please do!) | 22 22 | `LUMINA_SYNCHRONISATION_IID` | `"localhost"` | A name Lumina uses when communicating with other instances, must be equal to where it's http is facing the public internet | 23 23 | `LUMINA_SYNCHRONISATION_INTERVAL` | `"30"` | Specifies the interval between syncs. Minimum is 30. |
+2 -1
server/Cargo.toml
··· 21 21 cynthia_con = "0.1.1" 22 22 dotenv = "0.15.0" 23 23 tokio-postgres = { version = "0.7.13", features = ["with-uuid-1"] } 24 - tokio-sqlite = { version = "0.1.5", features = ["bundled"] } 25 24 bcrypt = "0.17.0" 25 + r2d2 = "0.8.10" 26 + r2d2_sqlite = "0.27.0"
+1 -1
server/src/client_communication.rs
··· 95 95 format!("Handle message: {:?}", jsonmsg).color_error_red() 96 96 ); 97 97 } 98 - Err(e) => { 98 + Err(_e) => { 99 99 let _ = stream.send(ws::Message::from("unknown")).await; 100 100 } 101 101 },
+119 -93
server/src/database.rs
··· 1 1 use crate::errors::LuminaError::{self, ConfMissing}; 2 + use r2d2::Pool; 3 + use r2d2_sqlite; 4 + use r2d2_sqlite::SqliteConnectionManager; 2 5 use tokio_postgres as postgres; 3 6 use tokio_postgres::tls::NoTlsStream; 4 7 use tokio_postgres::{Client, Connection, Socket}; 5 - use tokio_sqlite as sqlite; 6 8 7 9 pub(crate) async fn setup(config: crate::ServerConfig) -> Result<DbConn, LuminaError> { 8 - // match (env::var("LUMINA_DB_TYPE").map_err(|_| ConfMissing("LUMINA_DB_TYPE".to_string()))?) 9 - // .as_str() 10 - // { 11 - // "sqlite" => { 12 - // let db_path = env::var("LUMINA_DB_PATH").unwrap_or("instance.sqlite".to_string()); 13 - // let conn = sqlite::Connection::open(db_path) 14 - // .await 15 - // .map_err(LuminaError::Sqlite)?; 16 - // Ok(DbConn::SqliteConnection(conn)) 17 - // } 18 - // "postgres" => { 19 - let pg_config = { 20 - let mut pg_config = postgres::Config::new(); 21 - pg_config.user(&{ 22 - std::env::var("LUMINA_POSTGRES_USERNAME") 23 - .map_err(|_| ConfMissing("LUMINA_POSTGRES_USERNAME".to_string()))? 24 - }); 25 - pg_config.dbname(&{ 26 - std::env::var("LUMINA_POSTGRES_DATABASE") 27 - .map_err(|_| ConfMissing("LUMINA_POSTGRES_DATABASE".to_string()))? 28 - }); 29 - pg_config.port(std::env::var("LUMINA_POSTGRES_PORT").unwrap_or_else(|_| { 10 + match (std::env::var("LUMINA_DB_TYPE") 11 + .map_err(|_| ConfMissing("LUMINA_DB_TYPE".to_string())) 12 + .unwrap_or(String::from("sqlite"))) 13 + .as_str() 14 + { 15 + "sqlite" => { 16 + let db_path = 17 + std::env::var("LUMINA_SQLITE_PATH").unwrap_or("instance.sqlite".to_string()); 18 + let manager = SqliteConnectionManager::file(db_path); 19 + let pool = Pool::new(manager).map_err(LuminaError::SqlitePool)?; 20 + { 21 + let conn = pool.get().map_err(LuminaError::SqlitePool)?; 22 + let _ = conn.execute( 23 + "CREATE TABLE IF NOT EXISTS users ( 24 + id TEXT PRIMARY KEY, 25 + email TEXT NOT NULL UNIQUE, 26 + username TEXT NOT NULL UNIQUE, 27 + password TEXT NOT NULL)", 28 + [], 29 + ); 30 + let _ = conn.execute( 31 + "CREATE TABLE IF NOT EXISTS sessions ( 32 + id TEXT PRIMARY KEY, 33 + user_id TEXT NOT NULL, 34 + session_key TEXT NOT NULL, 35 + created_at INT NOT NULL)", 36 + [], 37 + ); 38 + let _ = conn.execute("PRAGMA WAL_MODE = NORMAL", []); 39 + }; 40 + let _ = tokio::spawn(maintain(DbConn::SqliteConnectionPool(pool.clone()))); 41 + Ok(DbConn::SqliteConnectionPool(pool)) 42 + } 43 + "postgres" => { 44 + let pg_config = { 45 + let mut pg_config = postgres::Config::new(); 46 + pg_config.user(&{ 47 + std::env::var("LUMINA_POSTGRES_USERNAME") 48 + .map_err(|_| ConfMissing("LUMINA_POSTGRES_USERNAME".to_string()))? 49 + }); 50 + pg_config.dbname(&{ 51 + std::env::var("LUMINA_POSTGRES_DATABASE") 52 + .map_err(|_| ConfMissing("LUMINA_POSTGRES_DATABASE".to_string()))? 53 + }); 54 + pg_config.port(std::env::var("LUMINA_POSTGRES_PORT").unwrap_or_else(|_| { 30 55 warn!("No Postgres database port provided under environment variable '_LUMINA_POSTGRES_PORT_'. Using default value '5432'."); 31 56 "5432".to_string() 32 57 }).parse::<u16>().map_err(|_| { LuminaError::ConfInvalid("LUMINA_POSTGRES_PORT is not a valid integer number".to_string()) })?); 33 - match std::env::var("LUMINA_POSTGRES_HOST") { 34 - Ok(val) => { 35 - pg_config.host(&val); 36 - } 37 - Err(_) => { 38 - warn!( 39 - "No Postgres database host provided under environment variable 'LUMINA_POSTGRES_HOST'. Using default value 'localhost'." 40 - ); 41 - pg_config.host("localhost"); 42 - } 43 - }; 44 - match std::env::var("LUMINA_POSTGRES_PASSWORD") { 45 - Ok(val) => { 46 - pg_config.password(&val); 47 - } 48 - Err(_) => { 49 - info!( 50 - "No Postgres database password provided under environment variable 'LUMINA_POSTGRES_PASSWORD'. Trying passwordless authentication." 51 - ); 52 - } 53 - }; 54 - pg_config 55 - }; 56 - // Connect to the database 57 - let conn: (Client, Connection<Socket, NoTlsStream>) = pg_config 58 - .connect(postgres::tls::NoTls) 59 - .await 60 - .map_err(LuminaError::Postgres)?; 61 - let _ = tokio::spawn(conn.1); 62 - // Create a second connection to the database for spawning the maintain function 63 - let conn_two: (Client, Connection<Socket, NoTlsStream>) = pg_config 64 - .connect(postgres::tls::NoTls) 65 - .await 66 - .map_err(LuminaError::Postgres)?; 67 - let _ = tokio::spawn(conn_two.1); 68 - { 69 - // Set up the database tables 70 - // 71 - // Users table 72 - let _ = conn 73 - .0 74 - .execute( 75 - "CREATE TABLE IF NOT EXISTS users ( 58 + match std::env::var("LUMINA_POSTGRES_HOST") { 59 + Ok(val) => { 60 + pg_config.host(&val); 61 + } 62 + Err(_) => { 63 + warn!( 64 + "No Postgres database host provided under environment variable 'LUMINA_POSTGRES_HOST'. Using default value 'localhost'." 65 + ); 66 + pg_config.host("localhost"); 67 + } 68 + }; 69 + match std::env::var("LUMINA_POSTGRES_PASSWORD") { 70 + Ok(val) => { 71 + pg_config.password(&val); 72 + } 73 + Err(_) => { 74 + info!( 75 + "No Postgres database password provided under environment variable 'LUMINA_POSTGRES_PASSWORD'. Trying passwordless authentication." 76 + ); 77 + } 78 + }; 79 + pg_config 80 + }; 81 + // Connect to the database 82 + let conn: (Client, Connection<Socket, NoTlsStream>) = pg_config 83 + .connect(postgres::tls::NoTls) 84 + .await 85 + .map_err(LuminaError::Postgres)?; 86 + let _ = tokio::spawn(conn.1); 87 + // Create a second connection to the database for spawning the maintain function 88 + let conn_two: (Client, Connection<Socket, NoTlsStream>) = pg_config 89 + .connect(postgres::tls::NoTls) 90 + .await 91 + .map_err(LuminaError::Postgres)?; 92 + let _ = tokio::spawn(conn_two.1); 93 + { 94 + // Set up the database tables 95 + // 96 + // Users table 97 + let _ = conn 98 + .0 99 + .execute( 100 + "CREATE TABLE IF NOT EXISTS users ( 76 101 id UUID DEFAULT gen_random_uuid (), 77 102 email VARCHAR NOT NULL UNIQUE, 78 103 username VARCHAR NOT NULL UNIQUE, 79 104 password VARCHAR NOT NULL 80 105 )", 81 - &[], 82 - ) 83 - .await 84 - .map_err(LuminaError::Postgres)?; 85 - // Sessions table 86 - let _ = conn 87 - .0 88 - .execute( 89 - "CREATE TABLE IF NOT EXISTS sessions ( 106 + &[], 107 + ) 108 + .await 109 + .map_err(LuminaError::Postgres)?; 110 + // Sessions table 111 + let _ = conn 112 + .0 113 + .execute( 114 + "CREATE TABLE IF NOT EXISTS sessions ( 90 115 id UUID DEFAULT gen_random_uuid (), 91 116 user_id UUID NOT NULL, 92 117 session_key VARCHAR NOT NULL, 93 118 created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP 94 119 )", 95 - &[], 96 - ) 97 - .await 98 - .map_err(LuminaError::Postgres)?; 99 - }; 100 - let _ = tokio::spawn(maintain(DbConn::PgsqlConnection(conn_two.0))); 101 - Ok(DbConn::PgsqlConnection(conn.0)) 102 - // } 103 - // _ => { 104 - // Err(LuminaError::ConfInvalid( 105 - // // "LUMINA_DB_TYPE does not contain a valid value, only 'sqlite' or 'postgres' are allowed.".to_string() 106 - // "LUMINA_DB_TYPE does not contain a valid value, only 'postgres' is allowed." 107 - // .to_string(), 108 - // )) 109 - // } 110 - // } 120 + &[], 121 + ) 122 + .await 123 + .map_err(LuminaError::Postgres)?; 124 + }; 125 + let _ = tokio::spawn(maintain(DbConn::PgsqlConnection(conn_two.0))); 126 + Ok(DbConn::PgsqlConnection(conn.0)) 127 + } 128 + 129 + _ => { 130 + Err(LuminaError::ConfInvalid( 131 + // "LUMINA_DB_TYPE does not contain a valid value, only 'sqlite' or 'postgres' are allowed.".to_string() 132 + "LUMINA_DB_TYPE does not contain a valid value, only 'postgres' is allowed." 133 + .to_string(), 134 + )) 135 + } 136 + } 111 137 } 112 138 113 139 // This will be an enum containing either a pgsql connection or a sqlite connection 114 140 #[derive()] 115 141 pub enum DbConn { 116 142 PgsqlConnection(postgres::Client), 117 - SqliteConnection(()), 143 + SqliteConnectionPool(Pool<SqliteConnectionManager>), 118 144 } 119 145 120 146 // This function will be used to maintain the database, such as deleting old sessions ··· 133 159 .await; 134 160 } 135 161 } 136 - DbConn::SqliteConnection(_) => { 162 + DbConn::SqliteConnectionPool(_) => { 137 163 todo!() 138 164 } 139 165 }
+4 -1
server/src/errors.rs
··· 1 1 use crate::postgres; 2 2 use crate::sqlite; 3 + use r2d2_sqlite::rusqlite; 3 4 pub(crate) enum LuminaError { 4 5 ConfMissing(String), 5 6 ConfInvalid(String), 6 - Sqlite(sqlite::Error), 7 + Sqlite(rusqlite::Error), 8 + SqlitePool(r2d2::Error), 7 9 Postgres(postgres::Error), 8 10 Unknown, 9 11 RocketFaillure(rocket::Error), ··· 15 17 RegisterUsernameInvalid, 16 18 PasswordNotValid, 17 19 LoginInvalid, 20 + UUidError(uuid::Error), 18 21 }
+70 -45
server/src/main.rs
··· 7 7 8 8 #[macro_use] 9 9 extern crate rocket; 10 - use std::sync::Arc; 10 + use std::{ 11 + net::{IpAddr, Ipv4Addr, Ipv6Addr}, 12 + sync::Arc, 13 + }; 11 14 use tokio::sync::Mutex; 12 15 mod user; 16 + use r2d2_sqlite::rusqlite as sqlite; 13 17 use tokio_postgres as postgres; 14 - use tokio_sqlite as sqlite; 15 18 struct AppState(Arc<(ServerConfig, Mutex<DbConn>)>); 16 19 17 20 use database::DbConn; 18 - use rocket::request::FromRequest; 19 21 20 22 #[derive(Debug, Clone)] 21 23 struct ServerConfig { 22 24 port: u16, 23 - host: String, 25 + host: IpAddr, 24 26 } 25 27 26 28 extern crate dotenv; ··· 29 31 use cynthia_con::CynthiaColors; 30 32 use dotenv::dotenv; 31 33 34 + fn config_get() -> Result<ServerConfig, LuminaError> { 35 + let addr = { 36 + let s = std::env::var("LUMINA_SERVER_ADDR").unwrap_or(String::from("127.0.0.1")); 37 + s.parse::<IpAddr>() 38 + .map_err(|_| LuminaError::ConfInvalid("LUMINA_SERVER_ADDR".to_string()))? 39 + }; 40 + let port = { 41 + let s = std::env::var("LUMINA_SERVER_PORT").unwrap_or(String::from("8080")); 42 + s.parse::<u16>() 43 + .map_err(|_| LuminaError::ConfInvalid("LUMINA_SERVER_PORT".to_string()))? 44 + }; 45 + Ok(ServerConfig { port, host: addr }) 46 + } 47 + 32 48 #[rocket::main] 33 49 async fn main() { 34 50 dotenv().ok(); 35 51 36 - let config = ServerConfig { 37 - port: 8000, 38 - host: "localhost".to_string(), 39 - }; 40 - let db = match database::setup(config.clone()).await { 41 - Ok(db) => db, 52 + match config_get() { 53 + Ok(config) => { 54 + let db = match database::setup(config.clone()).await { 55 + Ok(db) => db, 56 + Err(LuminaError::ConfMissing(a)) => panic!( 57 + "Missing environment variable {}, which is required to continue. Please make sure it is set, or change other variables to make it redundant, if possible.", 58 + a.color_bright_orange() 59 + ), 60 + Err(LuminaError::ConfInvalid(a)) => { 61 + panic!("Invalid environment variable: {}", a.color_bright_orange()) 62 + } 63 + Err(LuminaError::Sqlite(a)) => panic!("Error opening sqlite database: {}", a), 64 + Err(LuminaError::Postgres(a)) => { 65 + panic!("Error connecting to postgres database: {}", a) 66 + } 67 + Err(_) => panic!("Unknown error: could not setup database connection."), 68 + }; 69 + let appstate = AppState(Arc::from((config.clone(), Mutex::from(db)))); 70 + let mut def = rocket::Config::default(); 71 + def.port = config.port; 72 + def.address = config.host; 73 + let result = rocket::build() 74 + .configure(def) 75 + .mount( 76 + "/", 77 + routes![ 78 + staticroutes::index, 79 + staticroutes::lumina_js, 80 + staticroutes::lumina_css, 81 + client_communication::wsconnection, 82 + staticroutes::logo_svg, 83 + staticroutes::logo_png, 84 + staticroutes::favicon, 85 + ], 86 + ) 87 + .manage(appstate) 88 + .launch() 89 + .await 90 + .map_err(LuminaError::RocketFaillure); 91 + match result { 92 + Ok(_) => {} 93 + Err(LuminaError::RocketFaillure(e)) => { 94 + println!("Error starting server: {:?}", e); 95 + } 96 + Err(_) => { 97 + println!("Unknown error starting server."); 98 + } 99 + } 100 + } 42 101 Err(LuminaError::ConfMissing(a)) => panic!( 43 102 "Missing environment variable {}, which is required to continue. Please make sure it is set, or change other variables to make it redundant, if possible.", 44 103 a.color_bright_orange() ··· 46 105 Err(LuminaError::ConfInvalid(a)) => { 47 106 panic!("Invalid environment variable: {}", a.color_bright_orange()) 48 107 } 49 - Err(LuminaError::Sqlite(a)) => panic!("Error opening sqlite database: {}", a), 50 - Err(LuminaError::Postgres(a)) => panic!("Error connecting to postgres database: {}", a), 51 - Err(_) => panic!("Unknown error: could not setup database connection."), 108 + Err(_) => panic!("Unknown error: could not setup server configuration."), 52 109 }; 53 - let appstate = AppState(Arc::from((config, Mutex::from(db)))); 54 - let should_start_server = true; 55 - if should_start_server { 56 - let result = rocket::build() 57 - .mount( 58 - "/", 59 - routes![ 60 - staticroutes::index, 61 - staticroutes::lumina_js, 62 - staticroutes::lumina_css, 63 - client_communication::wsconnection, 64 - staticroutes::logo_svg, 65 - staticroutes::logo_png, 66 - staticroutes::favicon, 67 - ], 68 - ) 69 - .manage(appstate) 70 - .launch() 71 - .await 72 - .map_err(LuminaError::RocketFaillure); 73 - match result { 74 - Ok(_) => {} 75 - Err(LuminaError::RocketFaillure(e)) => { 76 - println!("Error starting server: {:?}", e); 77 - } 78 - Err(_) => { 79 - println!("Unknown error starting server."); 80 - } 81 - } 82 - } else { 83 - // do something else 84 - } 85 110 }
+78 -49
server/src/user.rs
··· 1 - use crate::sqlite::Connection; 2 1 use crate::{LuminaError, database::DbConn}; 3 2 use std::str::FromStr; 4 - use tokio_sqlite::Value; 5 3 use uuid::Uuid; 6 4 7 5 #[derive(Debug, Clone)] ··· 17 15 password: String, 18 16 db: &DbConn, 19 17 ) -> Result<User, LuminaError> { 18 + if { 19 + let mut check_results = vec![]; 20 + { 21 + check_results.push(username.len() > 4); 22 + check_results.push(username.len() < 20); 23 + check_results.push(username.chars().all(char::is_alphanumeric)); 24 + check_results.push(username.chars().all(char::is_lowercase)); 25 + } 26 + check_results.contains(&false) 27 + } { 28 + return Err(LuminaError::RegisterUsernameInvalid); 29 + } 30 + // Check if the email is valid 31 + if { 32 + let mut check_results = vec![]; 33 + { 34 + check_results.push(email.contains('@')); 35 + check_results.push(email.contains('.')); 36 + let mut splemail = email.split("@"); 37 + check_results.push(match splemail.nth(0) { 38 + Some(v) => v.len() > 4, 39 + None => false, 40 + }); 41 + check_results.push(match splemail.nth(1) { 42 + Some(v) => { 43 + v.len() > 4 44 + && v.contains('.') 45 + && v.split('.').last().unwrap().len() > 1 46 + && v.split('.').last().unwrap().len() < 5 47 + && v == splemail.last().unwrap() 48 + } 49 + None => false, 50 + }); 51 + 52 + check_results.push(email.len() > 8); 53 + } 54 + check_results.contains(&false) 55 + } { 56 + return Err(LuminaError::EmailNotValid); 57 + } 58 + // hash the password 59 + let password = 60 + bcrypt::hash(password, bcrypt::DEFAULT_COST).map_err(LuminaError::BcryptError)?; 20 61 match db { 21 62 DbConn::PgsqlConnection(client) => { 22 63 // Some username and email validation should be done here ··· 36 77 if !username_exists.is_empty() { 37 78 return Err(LuminaError::RegisterUsernameInUse); 38 79 } 39 - if { 40 - let mut check_results = vec![]; 41 - { 42 - check_results.push(username.len() > 4); 43 - check_results.push(username.len() < 20); 44 - check_results.push(username.chars().all(char::is_alphanumeric)); 45 - check_results.push(username.chars().all(char::is_lowercase)); 46 - } 47 - check_results.contains(&false) 48 - } { 49 - return Err(LuminaError::RegisterUsernameInvalid); 50 - } 51 - // Check if the email is valid 52 - if { 53 - let mut check_results = vec![]; 54 - { 55 - check_results.push(email.contains('@')); 56 - check_results.push(email.contains('.')); 57 - let mut splemail = email.split("@"); 58 - check_results.push(match splemail.nth(0) { 59 - Some(v) => v.len() > 4, 60 - None => false, 61 - }); 62 - check_results.push(match splemail.nth(1) { 63 - Some(v) => { 64 - v.len() > 4 65 - && v.contains('.') 66 - && v.split('.').last().unwrap().len() > 1 67 - && v.split('.').last().unwrap().len() < 5 68 - && v == splemail.last().unwrap() 69 - } 70 - None => false, 71 - }); 72 80 73 - check_results.push(email.len() > 8); 74 - } 75 - check_results.contains(&false) 76 - } { 77 - return Err(LuminaError::EmailNotValid); 78 - } 79 - // hash the password 80 - let password = bcrypt::hash(password, bcrypt::DEFAULT_COST) 81 - .map_err(LuminaError::BcryptError)?; 82 81 let id = client 83 82 .query_one("INSERT INTO users (email, username, password) VALUES ($1, $2, $3) RETURNING id", &[&email, &username, &password]) 84 83 .await ··· 89 88 username, 90 89 }) 91 90 } 92 - DbConn::SqliteConnection(_) => { 93 - todo!() 91 + DbConn::SqliteConnectionPool(pool) => { 92 + let conn = pool.get().map_err(LuminaError::SqlitePool)?; 93 + let username_exists = conn 94 + .prepare("SELECT * FROM users WHERE username = ?1") 95 + .map_err(LuminaError::Sqlite)? 96 + .exists(&[&username]) 97 + .map_err(LuminaError::Sqlite)?; 98 + if username_exists { 99 + return Err(LuminaError::RegisterUsernameInUse); 100 + } 101 + let email_exists = conn 102 + .prepare("SELECT * FROM users WHERE email = ?1") 103 + .map_err(LuminaError::Sqlite)? 104 + .exists(&[&email]) 105 + .map_err(LuminaError::Sqlite)?; 106 + if email_exists { 107 + return Err(LuminaError::RegisterEmailInUse); 108 + } 109 + let id = conn 110 + .prepare("INSERT INTO users (email, username, password) VALUES (?1, ?2, ?3) RETURNING id") 111 + .map_err(LuminaError::Sqlite)? 112 + .query_row(&[&email, &username, &password], |row| { 113 + let a: String = row.get(0)?; 114 + // Unwrap: Not entirely safe. If the database is corrupted, this will panic. 115 + Ok(Uuid::from_str(a.as_str()).unwrap()) 116 + }).map_err(LuminaError::Sqlite) 117 + ?; 118 + Ok(User { 119 + id, 120 + email, 121 + username, 122 + }) 94 123 } 95 124 } 96 125 } ··· 118 147 username: user.get(2), 119 148 }) 120 149 } 121 - DbConn::SqliteConnection(_) => { 150 + DbConn::SqliteConnectionPool(_) => { 122 151 todo!() 123 152 } 124 153 } ··· 140 169 .map_err(LuminaError::Postgres)?; 141 170 Ok((session_key, user)) 142 171 } 143 - DbConn::SqliteConnection(_) => { 172 + DbConn::SqliteConnectionPool(_) => { 144 173 todo!() 145 174 } 146 175 } ··· 161 190 username: user.get(2), 162 191 }) 163 192 } 164 - DbConn::SqliteConnection(_) => { 193 + DbConn::SqliteConnectionPool(_) => { 165 194 todo!() 166 195 } 167 196 }