diff options
| author | Daniel Hader <[email protected]> | 2026-06-05 19:29:40 -0500 |
|---|---|---|
| committer | Daniel Hader <[email protected]> | 2026-06-05 19:29:40 -0500 |
| commit | c071aca5c5c16d56aafe38ace2b2c158e1b875fc (patch) | |
| tree | aa947a0f6fa53be3de6fb879aa5c4d96bc087cf1 /src/routes | |
| parent | 3ac68b8b59f150e08731a62026ce3ac825655614 (diff) | |
server text sanitation, username/email filters, and code length measurement
Diffstat (limited to 'src/routes')
| -rw-r--r-- | src/routes/errors.rs | 4 | ||||
| -rw-r--r-- | src/routes/submission.rs | 16 | ||||
| -rw-r--r-- | src/routes/user.rs | 16 |
3 files changed, 32 insertions, 4 deletions
diff --git a/src/routes/errors.rs b/src/routes/errors.rs index f6a0901..5161e9a 100644 --- a/src/routes/errors.rs +++ b/src/routes/errors.rs @@ -3,6 +3,7 @@ use serde_json::{json}; pub enum RouteError { Internal(String), + MalformedField(String), UserCreateEmailExists(String), UserCreateUsernameExists(String), UnregisteredEmail(String), @@ -30,6 +31,9 @@ impl IntoResponse for RouteError { }, RouteError::NotFound(resource) => { (StatusCode::NOT_FOUND, format!("{resource} not found")) + }, + RouteError::MalformedField(field) => { + (StatusCode::BAD_REQUEST, format!("malformed {field}")) } }; diff --git a/src/routes/submission.rs b/src/routes/submission.rs index b3cf2b9..99767c2 100644 --- a/src/routes/submission.rs +++ b/src/routes/submission.rs @@ -1,3 +1,4 @@ +use ammonia::clean_text; use axum::{Json, extract::{Path, State}, http::StatusCode, response::IntoResponse}; use serde::Deserialize; @@ -18,15 +19,22 @@ pub async fn create_submission( ) -> Result<impl IntoResponse, RouteError> { let user_id = claims.sub; + let code_length = request.code.len() as i64; + + let language = clean_text(&request.language); + let details = clean_text(&request.details); + let code = clean_text(&request.code); + match state.database.insert_submission( user_id, request.problem_id, - &request.language, - &request.details, - &request.code + &language, + &details, + &code, + code_length, ) { Ok(submission) => Ok((StatusCode::CREATED, Json(submission))), - Err(_) => Err(RouteError::Internal(format!("unable to insert submission"))) + Err(e) => Err(RouteError::Internal(format!("unable to insert submission {e:?}"))) } } diff --git a/src/routes/user.rs b/src/routes/user.rs index 178a272..31a5824 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -1,6 +1,7 @@ use axum::extract::{Json, State}; use axum::http::StatusCode; use axum::response::IntoResponse; +use regex::Regex; use serde::{Deserialize, Serialize}; use crate::AppState; @@ -12,6 +13,7 @@ pub(crate) struct CreateUserRequest { email: String, username: String, password: String, + register_code: String, } pub async fn create_user( @@ -19,6 +21,20 @@ pub async fn create_user( Json(request): Json<CreateUserRequest> ) -> Result<impl IntoResponse, RouteError> { + if request.register_code != state.register_code { + return Err(RouteError::AuthorizationFailure()); + } + + let email_re = Regex::new(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$").unwrap(); + if !email_re.is_match(&request.email) { + return Err(RouteError::MalformedField("email".into())); + } + + let username_re = Regex::new(r"^[a-zA-Z0-9_\-]+$").unwrap(); + if !username_re.is_match(&request.username) { + return Err(RouteError::MalformedField("username".into())); + } + match state.database.fetch_user_by_email(&request.email) { Err(_) => return Err(RouteError::Internal("database action failed".into())), Ok(Some(_)) => return Err(RouteError::UserCreateEmailExists(request.email)), |
