April: 07
Prepare the side account for the IRS bill.
Firecracker VM
Section titled “Firecracker VM”the idea here is that while we have edge functions for micro services, I was thinking that we use firecrackers for the python scripts. This means if we need to quickly utilize ffmpeg or maybe take a PNG and convert its background to PNG, all of these random tasks can be done using a python script. Later on we can even go as far as extending it out so that it automatically creates shader atlas from PNG images too.
However, the main focus is to get a couple functional services out and about, with them all operating safely.
TempleState
Section titled “TempleState”-
12:47AM
Next part of the
jedipackage will be to refactor the wholeTempleStateto use the fred package instead of theredispackage. Hmm, this will be a big change, but I think it will be worth it in the end.
These are the notes from Remy regarding the first file of the kbve package!
I am going to place them here and then move them into the library.
For Password character checking, Remy suggested this:
match password.chars().count() { // Check if the password is long enough (e.g., at least 8 characters) 0..=7 => return Err("Password is too short"),
// Check if the password is not too long (e.g., no more than 255 characters) 256..=usize::MAX => return Err("Password is too long"),
_ => () }Here is an example of the fold method for checking the characters:
let conditions = password.chars().fold([false; 4], |mut acc, c| { let acc1 = [char::is_uppercase, char::is_lowercase, |c: char| c.is_digit(10), |c: char| !c.is_alphanumeric()].map(|f| f(c)); (0..4).for_each(|i| acc[i] |= acc1[i]); acc });
if conditions.into_iter().fold(false, |acc, cond| (acc|!cond)) { return Err( "Password must include uppercase, lowercase, digits, and special characters" ); }If we expand the acc1, then we can do this instead:
let conditions = password.chars().fold([false; 4], |mut acc, c| { let acc1 = [char::is_uppercase, char::is_lowercase, |c: char| c.is_digit(10), |c: char| !c.is_alphanumeric()].map(|f| f(c)); (0..acc1.len()).for_each(|i| acc[i] |= acc1[i]); acc });
if conditions.into_iter().fold(false, |acc, cond| (acc|!cond)) { return Err( "Password must include uppercase, lowercase, digits, and special characters" ); }Here is a better way of writing the sanitize_path function:
pub fn sanitize_path(input: &str) -> String { let mut sanitized: String = input .chars() .filter(|c| matches!(c, 'a'..='z'|'A'..='Z'|'/'|'?'|'@'|'%'|'$'|'#') ) .collect();
if sanitized.chars().count() > 255 { sanitized.truncate(255); }
sanitized}Next, we have a better way to do the ulid string to bytes:
pub fn convert_ulid_string_to_bytes(ulid_str: &str) -> Result<Vec<u8>, String> { Ulid::from_str(ulid_str) .map(|o| ulid.to_bytes().to_vec()) .map_err(|_| "Invalid ULID string".to_string())}And vice versa, for bytes to string:
pub fn convert_ulid_bytes_to_string(ulid_bytes: &[u8]) -> Result<String, String> { let 16 = ulid_bytes.len() else { return Err("Invalid ULID bytes length".to_string()); };
// Convert the slice to an array let ulid_array_ref: [u8; 16] = ulid_bytes.try_into().map_err(|_|"Failed to convert slice to array")?;
// Convert the Ulid to a string Ok(Ulid::from_bytes(ulid_array_ref).to_string())}We could clean up the cors_service() function as well:
pub fn cors_service() -> CorsLayer { let orgins = [ "https://herbmail.com", "https://kbve.com", "https://discord.sh", "https://hoppscotch.io", "http://localhost:3000", "http://localhost:4321", "https://kbve.itch.io", "https://html-classic.itch.zone", ].map(|url| url.parse::<HeaderValue>().unwrap());
CorsLayer::new() .allow_origin(orgins) .allow_methods([Method::PUT, Method::GET, Method::DELETE, Method::POST]) .allow_credentials(true) .allow_headers([ AUTHORIZATION, ACCEPT, CONTENT_TYPE, HeaderName::from_static("x-kbve-shieldwall"), HeaderName::from_static("x-kbve-api"), ])}Last two were the health check, which would look like this:
pub async fn health_check(Extension(pool): Extension<Arc<Pool>>) -> Result< Json<WizardResponse>, StatusCode> { let connection_result = task::spawn_blocking(move || { pool.get() }).await.flatten();
match connection_result { Ok(_conn) => { Ok( Json(WizardResponse { data: serde_json::json!({"status": "online"}), message: serde_json::json!({"health": "ok"}), }) ) } _ => { Err(StatusCode::SERVICE_UNAVAILABLE) } }}and finally the speed_test, which would look like this:
pub async fn speed_test(Extension(pool): Extension<Arc<Pool>>) -> Result< Json<WizardResponse>, StatusCode> { let start_time = Instant::now();
// Use `block_in_place` or `spawn_blocking` for the blocking database operation let query_result = task::block_in_place(|| { let mut conn = pool.get().map_err(|_| StatusCode::SERVICE_UNAVAILABLE)?;
// Execute a simple query diesel ::sql_query("SELECT 1") .execute(&mut conn) .map_err(|_| StatusCode::SERVICE_UNAVAILABLE) });
query_result?;
let elapsed_time = start_time.elapsed().as_millis() as u64; Ok( Json(WizardResponse { data: serde_json::json!({"status": "time"}), message: serde_json::json!({"time": elapsed_time.to_string()}), }) )}Bonus function , getting the environmental variable function:
fn get_env_var(name: &str) -> Result<String, String> { let file_path = env::var(name); if let Ok(_) = &file_path { return file_path; };
let Ok(file_path) = env::var(format!("{}_FILE", name)) else { return Err(format!( "Environment variable {} or {}_FILE must be set", name, name )); };
fs::read_to_string(file_path).map_err(|err| format!("Error reading file for {}: {}", name, err))