···1919 * You should have received a copy of the GNU Affero General Public License
2020 * along with this program. If not, see <https://www.gnu.org/licenses/>.
2121 */
2222-2222+use crate::EnvVar::*;
2323use crate::errors::LuminaError::{self};
2424use crate::helpers::events::EventLogger;
2525use crate::timeline;
···8484 // Parse the port as u16, if it fails, return an error
8585 pg_config.port(port.parse::<u16>().map_err(|_| {
8686 LuminaError::ConfInvalid(
8787- "LUMINA_POSTGRES_PORT is not a valid integer number".to_string(),
8787+ LUMINA_POSTGRES_PORT,
8888 )
8989 })?);
9090 match std::env::var("LUMINA_POSTGRES_HOST") {
···1212 * it under the terms of the GNU Affero General Public License as published
1313 * by the Free Software Foundation, either version 3 of the License, or
1414 * (at your option) any later version.
1515- *
1515+ *w
1616 * This program is distributed in the hope that it will be useful,
1717 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1818 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
···5656 port: u16,
5757 host: IpAddr,
5858}
5959+6060+#[allow(non_camel_case_types)]
6161+#[derive(Debug, Clone, Copy)]
6262+enum EnvVar {
6363+ LUMINA_SERVER_ADDR,
6464+ LUMINA_SERVER_PORT,
6565+ LUMINA_POSTGRES_PORT,
6666+}
6767+impl std::fmt::Display for EnvVar {
6868+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6969+ write!(f, "{}",
7070+ match self {
7171+ EnvVar::LUMINA_SERVER_ADDR => "LUMINA_SERVER_ADDR",
7272+ EnvVar::LUMINA_SERVER_PORT => "LUMINA_SERVER_PORT",
7373+ EnvVar::LUMINA_POSTGRES_PORT => "LUMINA_POSTGRES_PORT",
7474+ }
7575+ )
7676+}}
7777+use crate::EnvVar::*;
5978use crate::database::{DatabaseConnections, PgConn};
6079use crate::errors::LuminaError;
6180use cynthia_con::{CynthiaColors, CynthiaStyles};
···6685 let addr = {
6786 let s = std::env::var("LUMINA_SERVER_ADDR").unwrap_or(String::from("127.0.0.1"));
6887 s.parse::<IpAddr>()
6969- .map_err(|_| LuminaError::ConfInvalid("LUMINA_SERVER_ADDR".to_string()))?
8888+ .map_err(|_| LuminaError::ConfInvalid(LUMINA_SERVER_ADDR))?
7089 };
7190 let port = {
7291 let s = std::env::var("LUMINA_SERVER_PORT").unwrap_or(String::from("8085"));
7392 s.parse::<u16>()
7474- .map_err(|_| LuminaError::ConfInvalid("LUMINA_SERVER_PORT".to_string()))?
9393+ .map_err(|_| LuminaError::ConfInvalid(LUMINA_SERVER_PORT))?
7594 };
7695 Ok(ServerConfig { port, host: addr })
7796}
···123142 error_elog!(
124143 ev_log,
125144 "Invalid environment variable: {}",
126126- a.color_bright_orange()
145145+ a.to_string().color_bright_orange()
127146 );
128147 None
129148 }
···427446 error_elog!(
428447 ev_log,
429448 "Invalid environment variable: {}",
430430- a.color_bright_orange()
449449+ a.to_string().color_bright_orange()
431450 );
432451 process::exit(1);
433452 }
+18-7
server/src/tests.rs
···9797#[test]
9898fn print_sizes() {
9999 println!("Size of LuminaError: {} bytes", mem::size_of::<LuminaError>());
100100- println!("Size of Rocket Error: {} bytes", mem::size_of::<rocket::Error>());
101101- println!("Size of Postgres Error: {} bytes", mem::size_of::<crate::postgres::Error>());
102102- println!("Size of Redis Error: {} bytes", mem::size_of::<redis::RedisError>());
103103- println!("Size of DbError: {} bytes", mem::size_of::<crate::errors::LuminaDbError>());
104104- println!("Size of bb8 RunError Postgres: {} bytes", mem::size_of::<bb8::RunError<crate::postgres::Error>>());
105105- println!("Size of bb8 RunError Redis: {} bytes", mem::size_of::<bb8::RunError<redis::RedisError>>());
106106- println!("Size of String: {} bytes", mem::size_of::<String>());
100100+ println!("Size of errors::LuminaDbError: {} bytes", mem::size_of::<crate::errors::LuminaDbError>());
101101+ println!("Size of EnvVar: {} bytes", mem::size_of::<crate::EnvVar>());
102102+ println!("Size of InnerAppState: {} bytes", mem::size_of::<crate::InnerAppState>());
103103+}
104104+105105+#[test]
106106+fn test_error_sizes() {
107107+ // We want to keep our error types small to minimize overhead when passing them around.
108108+ assert!(mem::size_of::<LuminaError>() <= 16, "LuminaError should be 16 bytes or less");
109109+ assert!(mem::size_of::<crate::errors::LuminaDbError>() <= 16, "LuminaDbError should be 16 bytes or less");
107110}
111111+112112+#[test]
113113+fn test_appstate_size() {
114114+ // Appstate is moved around a lot, so we want to keep it small, which is pretty easy since it just holds a single Arc pointer to a InnerAppState.
115115+ assert!(mem::size_of::<crate::AppState>() <= 8, "AppState should be 8 bytes or less");
116116+ // This constraint should lower over time as we optimize InnerAppState
117117+ assert!(mem::size_of::<crate::InnerAppState>() <= 88, "InnerAppState should be 88 bytes or less");
118118+}
+2-3
server/src/timeline.rs
···93939494 let cache_key = get_cache_key(timeline_id, page);
9595 let serialized = serde_json::to_string(&cached_page)
9696- .map_err(|e| LuminaError::SerializationError(e.to_string()))?;
9696+ ?;
97979898 let _: () = redis::cmd("SETEX")
9999 .arg(cache_key)
···132132133133 match cached_data {
134134 Some(data) => {
135135- let cached_page: CachedTimelinePage = serde_json::from_str(&data)
136136- .map_err(|e| LuminaError::SerializationError(e.to_string()))?;
135135+ let cached_page: CachedTimelinePage = serde_json::from_str(&data)?;
137136 Ok(Some(cached_page))
138137 }
139138 None => Ok(None),
+53-10
server/src/user.rs
···352352 .all(char::is_alphanumeric)
353353 {
354354 return Err(LuminaError::RegisterUsernameInvalid(
355355- "Invalid characters in username".to_string(),
355355+ OnRegisterUsernameInvalid::InvalidCharacters,
356356 ));
357357 }
358358 // Check if the username is too long
359359 if username.len() > 20 {
360360 return Err(LuminaError::RegisterUsernameInvalid(
361361- "Username too long".to_string(),
361361+ OnRegisterUsernameInvalid::TooLong,
362362 ));
363363 }
364364 // Check if the username is too short
365365 if username.len() < 4 {
366366 return Err(LuminaError::RegisterUsernameInvalid(
367367- "Username too short".to_string(),
367367+ OnRegisterUsernameInvalid::TooShort,
368368 ));
369369 }
370370 }
···376376 {
377377 if password.len() < 8 {
378378 return Err(LuminaError::RegisterPasswordNotValid(
379379- "Password too short".to_string(),
379379+ OnRegisterPasswordNotValid::TooShort,
380380 ));
381381 }
382382 if password.len() > 100 {
383383 return Err(LuminaError::RegisterPasswordNotValid(
384384- "Password too long".to_string(),
384384+ OnRegisterPasswordNotValid::TooLong
385385 ));
386386 }
387387 if !password.chars().any(char::is_uppercase) {
388388- return Err(LuminaError::RegisterPasswordNotValid(
389389- "Password must contain at least one uppercase letter".to_string(),
388388+ return Err(LuminaError::RegisterPasswordNotValid(
389389+ OnRegisterPasswordNotValid::MissingUppercase
390390 ));
391391 }
392392 if !password.chars().any(char::is_lowercase) {
393393 return Err(LuminaError::RegisterPasswordNotValid(
394394- "Password must contain at least one lowercase letter".to_string(),
394394+ OnRegisterPasswordNotValid::MissingLowercase
395395 ));
396396 }
397397 if !password.chars().any(char::is_numeric) {
398398- return Err(LuminaError::RegisterPasswordNotValid(
399399- "Password must contain at least one number".to_string(),
398398+ return Err(LuminaError::RegisterPasswordNotValid(OnRegisterPasswordNotValid::MissingNumber
400399 ));
401400 }
402401 }
403402 Ok(())
404403}
404404+405405+406406+#[derive(Debug)]
407407+pub(crate) enum OnRegisterUsernameInvalid {
408408+ TooLong,
409409+ TooShort,
410410+ InvalidCharacters
411411+}
412412+impl std::fmt::Display for OnRegisterUsernameInvalid {
413413+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
414414+ write!(f, "{}", match self {
415415+ OnRegisterUsernameInvalid::TooLong => "Username too long",
416416+ OnRegisterUsernameInvalid::TooShort => "Username too short",
417417+ OnRegisterUsernameInvalid::InvalidCharacters => {
418418+ "Username contains invalid characters"
419419+ }
420420+ })
421421+ }
422422+}
423423+#[derive(Debug)]
424424+pub(crate) enum OnRegisterPasswordNotValid {
425425+ TooShort,
426426+ TooLong,
427427+ MissingUppercase,
428428+ MissingLowercase,
429429+ MissingNumber,
430430+}
431431+impl std::fmt::Display for OnRegisterPasswordNotValid {
432432+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
433433+ write!(f, "{}", match self {
434434+ OnRegisterPasswordNotValid::TooShort => "Password too short",
435435+ OnRegisterPasswordNotValid::TooLong => "Password too long",
436436+ OnRegisterPasswordNotValid::MissingUppercase => {
437437+ "Password must contain at least one uppercase letter"
438438+ }
439439+ OnRegisterPasswordNotValid::MissingLowercase => {
440440+ "Password must contain at least one lowercase letter"
441441+ }
442442+ OnRegisterPasswordNotValid::MissingNumber => {
443443+ "Password must contain at least one number"
444444+ }
445445+ })
446446+ }
447447+}