summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Hader <[email protected]>2026-05-30 10:10:17 -0500
committerDaniel Hader <[email protected]>2026-05-30 10:10:17 -0500
commit929be68e691c1c4015fc6874111b19b9f5d68c02 (patch)
treeffc4ecb9c63d8dc242c33d69a592dc093dcfd122 /src
parent772c7844c4ca1de632f64eb9428e8e97eea64ac1 (diff)
registration page, me endpoint, and minor content tweaks
Diffstat (limited to 'src')
-rw-r--r--src/auth.rs56
-rw-r--r--src/database/sql/initialize.sql2
-rw-r--r--src/main.rs7
-rw-r--r--src/routes/auth.rs4
-rw-r--r--src/routes/user.rs16
5 files changed, 20 insertions, 65 deletions
diff --git a/src/auth.rs b/src/auth.rs
deleted file mode 100644
index a621756..0000000
--- a/src/auth.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-use axum::{extract::FromRequestParts, http::{StatusCode, request::Parts}};
-use serde::Serialize;
-use argon2::{Argon2, PasswordHash, PasswordVerifier, password_hash::{
- Error, PasswordHasher, SaltString, rand_core::OsRng
-}};
-
-pub fn hash_password(password: &str) -> Result<String, Error> {
- let argon2 = Argon2::default();
- let salt = SaltString::generate(&mut OsRng);
- Ok(argon2.hash_password(password.as_bytes(), &salt)?.to_string())
-}
-
-pub fn check_password(password: &str, password_hash: &str) -> Result<bool, Error> {
- let argon2 = Argon2::default();
- let hash = PasswordHash::new(password_hash)?;
- Ok(argon2.verify_password(password.as_bytes(), &hash).is_ok())
-}
-
-#[derive(Serialize)]
-pub struct Claims {
- pub sub: String,
- pub exp: usize,
- pub iat: usize,
- pub is_admin: bool,
-}
-
-//pub fn create_jwt(email: &str, is_admin: bool) -> Result
-
-pub struct AuthUser(pub Claims);
-
-impl<S: Send + Sync> FromRequestParts<S> for AuthUser {
- type Rejection = StatusCode;
-
- async fn from_request_parts(
- parts: &mut Parts,
- state: &S,
- ) -> Result<Self, Self::Rejection> {
- todo!();
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn test_password_hashing() {
-
- let passwords = vec!["password", "test1", "random"];
-
- for password in &passwords {
- let hash = hash_password(password).unwrap();
- assert!(check_password(password, &hash).unwrap());
- }
- }
-}
diff --git a/src/database/sql/initialize.sql b/src/database/sql/initialize.sql
index d5fb9e0..1c2a40f 100644
--- a/src/database/sql/initialize.sql
+++ b/src/database/sql/initialize.sql
@@ -47,7 +47,7 @@ INSERT INTO problem (title, description) VALUES (
INSERT INTO problem (title, description) VALUES (
'As Big a Number as Possible',
- 'This challenge is a bit different from the others. Instead of trying to make as small a program as possible, you are trying to make a program which prints out as big a number as possible. Your source code should be no longer than 512 bytes.'
+ 'This challenge is a bit different from the others. Instead of trying to make as small a program as possible, you are trying to make a program which prints out as big a number as possible in a fixed amount of code. Your source code should be no longer than 512 bytes and numbers should be printed in base 10. Before you get any funny ideas, keep in mind that your program has to finish running at some point; you can''t just print "9" in an infinite loop.'
);
INSERT INTO problem (title, description) VALUES (
diff --git a/src/main.rs b/src/main.rs
index 5629578..0fdd2fb 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,16 +2,14 @@ use std::env;
mod database;
mod routes;
-mod auth;
use axum::{
routing::{get, post},
Router,
};
-use jsonwebtoken::EncodingKey;
use routes::problem::{get_problems, create_problem};
-use routes::user::create_user;
+use routes::user::{create_user, me};
use routes::auth::login;
use tower_http::services::ServeDir;
@@ -42,10 +40,11 @@ async fn main() {
let static_files = ServeDir::new("./static");
let app = Router::new()
+ .route("/login", post(login))
.route("/problem", get(get_problems))
.route("/problem", post(create_problem))
.route("/user", post(create_user))
- .route("/login", post(login))
+ .route("/me", get(me))
.nest_service("/static", static_files)
.with_state(state);
diff --git a/src/routes/auth.rs b/src/routes/auth.rs
index 4fb9124..979e617 100644
--- a/src/routes/auth.rs
+++ b/src/routes/auth.rs
@@ -2,7 +2,7 @@ use std::time::{SystemTime, UNIX_EPOCH};
use axum::extract::{Json, State, FromRequestParts};
use axum::response::IntoResponse;
-use axum::http::{StatusCode, request::Parts};
+use axum::http::{request::Parts};
use axum_extra::extract::CookieJar;
use axum_extra::extract::cookie::{Cookie, SameSite};
use jsonwebtoken::{DecodingKey, EncodingKey, Header, Validation, decode, encode};
@@ -21,6 +21,7 @@ pub struct Claims {
pub sub: String,
pub exp: usize,
pub iat: usize,
+ pub username: String,
pub is_admin: bool,
}
@@ -92,6 +93,7 @@ pub async fn login(
sub: user.email().to_string(),
iat: now,
exp: now + 60 * 60 * 24,
+ username: user.username().to_string(),
is_admin: false
};
diff --git a/src/routes/user.rs b/src/routes/user.rs
index f64cb39..157cf09 100644
--- a/src/routes/user.rs
+++ b/src/routes/user.rs
@@ -1,14 +1,14 @@
use axum::extract::{Json, State};
use axum::http::StatusCode;
use axum::response::IntoResponse;
-use serde::Deserialize;
+use serde::{Deserialize, Serialize};
use crate::AppState;
-use crate::auth::hash_password;
+use crate::routes::auth::{AuthUser, hash_password};
use super::errors::RouteError;
#[derive(Deserialize)]
-pub struct CreateUserRequest {
+pub(crate) struct CreateUserRequest {
email: String,
username: String,
password: String,
@@ -42,3 +42,13 @@ pub async fn create_user(
return Ok((StatusCode::CREATED, Json(user)));
}
+#[derive(Serialize)]
+struct MeResponse {
+ username: String,
+}
+
+pub async fn me(
+ AuthUser(claims): AuthUser,
+) -> Result<impl IntoResponse, RouteError> {
+ Ok(Json(MeResponse { username: claims.username }))
+}