clean code errors!

This commit is contained in:
Artemis 2025-01-24 14:38:09 +01:00
parent e316023b37
commit 657b47d20b
10 changed files with 112 additions and 56 deletions

7
Cargo.lock generated
View file

@ -60,6 +60,12 @@ dependencies = [
"libc",
]
[[package]]
name = "anyhow"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
[[package]]
name = "async-stream"
version = "0.3.6"
@ -452,6 +458,7 @@ dependencies = [
name = "dolltags"
version = "0.1.0"
dependencies = [
"anyhow",
"chrono",
"rand",
"regex",

View file

@ -17,3 +17,4 @@ chrono = { version = "0.4", features = ["serde"] }
regex = "1.11"
rand = "0.8"
serde_json = "1.0"
anyhow = "1.0"

View file

@ -27,7 +27,7 @@ a profile is
- basic username / password thingy
- p2: optional email for forgotten password i guess
- "my registered tags" page
- ability to delete a tag (remove all data expect the ID to lock the ID)
- ability to delete a tag (remove all data except the ID to lock the ID)
- ability to delete the whole account (incl. all registered tags)
- deleting a tag keeping the account allows to re-use the tag later on. no one else can use it still
- pgsql migration? may make hosting easier for me as well as cleaner migrations and types

23
src/ids.rs Normal file
View file

@ -0,0 +1,23 @@
use rand::{distributions::Uniform, prelude::Distribution, thread_rng};
use regex::Regex;
pub fn generate_ids() -> Vec<i64> {
let uniform = Uniform::new_inclusive::<i64, i64>(100_000, 999_999);
let mut rng = thread_rng();
(1..=10).map(|_| uniform.sample(&mut rng)).collect()
}
pub fn id_public_to_db(id: &str) -> Option<i64> {
let id_re = Regex::new(r"^\d{6}$").unwrap();
if id_re.is_match(id) {
id.parse::<i64>().ok()
} else {
None
}
}
pub fn id_db_to_public(id: i64) -> String {
let first = id / 1000;
let second = id % 1000;
format!("{:0>3}-{:0>3}", first, second)
}

View file

@ -4,7 +4,6 @@ use std::collections::HashMap;
use db::migrate::run_migrations;
use db::schema::DollTags;
use regex::Regex;
use rocket::fairing::AdHoc;
use rocket::fs::{relative, FileServer};
use rocket_db_pools::Database;
@ -14,24 +13,9 @@ use routes::{error_handlers, form, public};
use serde_json::{to_value, Value};
pub mod db;
pub mod rng;
pub mod ids;
pub mod routes;
pub fn id_public_to_db(id: &str) -> Option<i64> {
let id_re = Regex::new(r"^\d{6}$").unwrap();
if id_re.is_match(id) {
id.parse::<i64>().ok()
} else {
None
}
}
pub fn id_db_to_public(id: i64) -> String {
let first = id / 1000;
let second = id % 1000;
format!("{:0>3}-{:0>3}", first, second)
}
#[launch]
fn rocket() -> _ {
rocket::build()
@ -40,7 +24,7 @@ fn rocket() -> _ {
.tera
.register_filter("pretty_id", |v: &Value, _: &HashMap<String, Value>| {
let value = try_get_value!("pretty_id", "value", i64, v);
Ok(to_value(id_db_to_public(value)).unwrap())
Ok(to_value(ids::id_db_to_public(value)).unwrap())
});
}))
.attach(DollTags::init())

View file

@ -1,7 +0,0 @@
use rand::{distributions::Uniform, prelude::Distribution, thread_rng};
pub fn generate_ids() -> Vec<i64> {
let uniform = Uniform::new_inclusive::<i64, i64>(100_000, 999_999);
let mut rng = thread_rng();
(1..=10).map(|_| uniform.sample(&mut rng)).collect()
}

View file

@ -1,6 +1,46 @@
use rocket::response::{Redirect, Responder};
use rocket_dyn_templates::{context, Template};
#[catch(404)]
pub fn not_found() -> Template {
Template::render("error/not-found", context! {})
}
#[derive(Responder)]
pub enum PageResponse {
Page(Template),
Redirect(Redirect),
}
impl From<Template> for PageResponse {
fn from(value: Template) -> Self {
PageResponse::Page(value)
}
}
impl From<Redirect> for PageResponse {
fn from(value: Redirect) -> Self {
PageResponse::Redirect(value)
}
}
#[derive(Responder)]
#[response(status = 500)]
pub struct Fail(Template);
impl From<anyhow::Error> for Fail {
fn from(value: anyhow::Error) -> Self {
error!("Internal error: {:?}", value);
Fail(Template::render("error/internal", context! {}))
}
}
impl From<sqlx::Error> for Fail {
fn from(value: sqlx::Error) -> Self {
error!("DB error: {:?}", value);
Fail(Template::render("error/internal", context! {}))
}
}
pub type RawResult<T> = Result<T, Fail>;
pub type PageResult = RawResult<PageResponse>;

View file

@ -9,28 +9,29 @@ use crate::{
doll,
schema::{CreateDollProfile, DollTagsDb},
},
id_public_to_db,
rng::generate_ids,
ids::{generate_ids, id_public_to_db},
routes::error_handlers::PageResult,
};
#[get("/register")]
pub async fn show_register(db: DollTagsDb) -> Template {
pub async fn show_register(db: DollTagsDb) -> PageResult {
let mut ids_bundle = generate_ids();
let occupied_ids = doll::check_ids(db, &ids_bundle).await.expect("fuck");
let occupied_ids = doll::check_ids(db, &ids_bundle).await?;
ids_bundle.retain(|&id| !occupied_ids.contains(&id));
let ids = ids_bundle.iter().take(5).collect::<Vec<&i64>>();
Template::render(
Ok(Template::render(
"register",
context! {
ids
},
)
.into())
}
#[derive(Debug, FromForm)]
pub struct TagForm<'a> {
#[field(validate=len(1..=6))]
#[field(validate=validate_id())]
pub ident: &'a str,
#[field(validate=len(..32))]
pub microchip_id: &'a str,
@ -66,6 +67,14 @@ pub struct TagForm<'a> {
pub chassis_color: &'a str,
}
fn validate_id<'v>(id: &str) -> form::Result<'v, ()> {
if let None = id_public_to_db(id) {
Err(form::Error::validation("id not formatted properly"))?;
}
Ok(())
}
fn validate_chassis<'v>(a: &str, b: &str, c: &str, field: &str) -> form::Result<'v, ()> {
let all_empty = a.len() == 0 && b.len() == 0 && c.len() == 0;
let all_full = a.len() != 0
@ -86,23 +95,17 @@ fn validate_chassis<'v>(a: &str, b: &str, c: &str, field: &str) -> form::Result<
}
#[post("/register", data = "<tag>")]
pub async fn handle_register(
mut db: DollTagsDb,
tag: Form<TagForm<'_>>,
) -> Result<Template, Redirect> {
pub async fn handle_register(mut db: DollTagsDb, tag: Form<TagForm<'_>>) -> PageResult {
println!("register: {:?}", tag);
let id = id_public_to_db(&tag.ident).expect("wrong fmt");
let id = id_public_to_db(&tag.ident).expect("id format was wrong but is now right??");
let pronouns = format!(
"{}/{}/{}",
tag.pronoun_subject, tag.pronoun_object, tag.pronoun_possessive
);
let microchip_id = tag.microchip_id.to_lowercase();
if doll::id_exists(&mut *db, id, &microchip_id)
.await
.expect("fuck")
{
return Err(Redirect::found(uri!("/register")));
if doll::id_exists(&mut *db, id, &microchip_id).await? {
return Ok(Redirect::found(uri!("/register")).into());
}
doll::create(
@ -159,8 +162,7 @@ pub async fn handle_register(
},
},
)
.await
.expect("fuck");
.await?;
Ok(Template::render("register", context! {ids: vec![123456]}))
Ok(Template::render("register", context! {ids: vec![123456]}).into())
}

View file

@ -3,9 +3,11 @@ use rocket_dyn_templates::{context, Template};
use crate::{
db::{doll, schema::DollTagsDb},
id_public_to_db,
ids::id_public_to_db,
};
use super::error_handlers::PageResult;
#[get("/?<miss>&<ident>&<microchip_id>")]
pub fn index(miss: Option<bool>, ident: Option<&str>, microchip_id: Option<&str>) -> Template {
Template::render(
@ -23,18 +25,15 @@ pub async fn show_profile(
db: DollTagsDb,
ident: Option<&str>,
microchip_id: Option<&str>,
) -> Result<Template, Redirect> {
) -> PageResult {
let internal_id = ident.and_then(|v| id_public_to_db(v)).unwrap_or(0);
let microchip_id = microchip_id.unwrap_or("");
let profile = doll::get(db, internal_id, microchip_id)
.await
.expect("fuck")
.ok_or(Redirect::to(uri!(index(
Some(true),
ident,
Some(microchip_id)
))))?;
let profile = match doll::get(db, internal_id, microchip_id).await? {
Some(p) => p,
None => return Ok(Redirect::to(uri!(index(Some(true), ident, Some(microchip_id)))).into()),
};
let has_notable_traits = profile.has_notable_traits();
let has_chassis_info = profile.chassis_id.is_some()
&& profile.chassis_type.is_some()
@ -48,5 +47,6 @@ pub async fn show_profile(
has_notable_traits,
has_chassis_info,
},
))
)
.into())
}

View file

@ -0,0 +1,6 @@
{% extends "base" %}
{% block title %}500 Server error - {% endblock title %}
{% block main %}
<h1>The server couldn't handle this request</h1>
<p>something's broken on the server side, please bear with me while i fix it</p>
{% endblock main %}