Major restructure

This commit is contained in:
Imbus 2023-10-20 06:06:55 +02:00
parent 5b8d1cbdb1
commit 27386d5d18
9 changed files with 87 additions and 110 deletions

7
server/src/routes/mod.rs Normal file
View file

@ -0,0 +1,7 @@
mod post;
mod users;
mod vote;
pub use post::*;
pub use users::*;
pub use vote::*;

27
server/src/routes/post.rs Executable file
View file

@ -0,0 +1,27 @@
use crate::jwt::token_factory;
use crate::types::{NewPost, Post};
use crate::ServerState;
use actix_web::web::{Data, Path};
use actix_web::{get, post, web::Json, HttpResponse, Responder, Result};
use argon2::password_hash::rand_core::OsRng;
use argon2::password_hash::SaltString;
use argon2::password_hash::*;
use argon2::Argon2;
use argon2::PasswordHasher;
use argon2::PasswordVerifier;
use log::*;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[get("/posts")]
pub async fn get_posts(data: Data<ServerState>) -> impl Responder {
HttpResponse::InternalServerError().body("Unimplemented")
}
#[post("/posts")]
pub async fn new_post(new_post: Json<NewPost>, data: Data<ServerState>) -> impl Responder {
let post = Post::from(new_post.into_inner());
info!("Created post {:?}", post.uuid);
HttpResponse::Ok().json("Post added!")
}

100
server/src/routes/users.rs Executable file
View file

@ -0,0 +1,100 @@
use crate::jwt::token_factory;
use crate::types::{NewPost, Post};
use crate::ServerState;
use actix_web::web::{Data, Path};
use actix_web::{get, post, web::Json, HttpResponse, Responder, Result};
use argon2::password_hash::rand_core::OsRng;
use argon2::password_hash::SaltString;
use argon2::password_hash::*;
use argon2::Argon2;
use argon2::PasswordHasher;
use argon2::PasswordVerifier;
use log::*;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Serialize, Deserialize)]
pub struct RegisterData {
username: String,
password: String,
captcha: String,
}
#[post("/register")]
pub async fn register(
data: Json<RegisterData>,
state: Data<ServerState>,
) -> Result<impl Responder> {
let q = "SELECT password FROM users WHERE username = ?";
let query = sqlx::query(q).bind(&data.username);
let result = query.fetch_one(&state.pool).await.ok();
if result.is_some() {
info!("User \"{}\" already exists", data.username);
return Ok(HttpResponse::BadRequest().json("Error"));
}
let password = data.password.clone();
let salt = SaltString::generate(&mut OsRng);
let phc_hash = Argon2::default().hash_password(password.as_bytes(), &salt);
if let Ok(phc_hash) = phc_hash {
info!("User: {} registered", data.username);
let phc_hash = phc_hash.to_string();
let q = "INSERT INTO users (username, password) VALUES (?, ?)";
let query = sqlx::query(q).bind(&data.username).bind(&phc_hash);
query.execute(&state.pool).await.unwrap();
} else {
return Ok(HttpResponse::BadRequest().json("Error"));
}
Ok(HttpResponse::Ok().json("User registered"))
}
#[derive(Debug, Serialize, Deserialize)]
pub struct LoginData {
username: String,
password: String,
}
use sqlx::Row;
#[derive(Debug, Serialize, Deserialize)]
struct LoginResponse {
username: String,
token: String,
}
#[post("/login")]
pub async fn login(data: Json<LoginData>, state: Data<ServerState>) -> Result<impl Responder> {
let q = "SELECT password FROM users WHERE username = ?";
let query = sqlx::query(q).bind(&data.username);
let result = query.fetch_one(&state.pool).await.ok();
if let Some(row) = result {
let phc_from_db = row.get::<String, _>("password");
let pwhash = PasswordHash::new(&phc_from_db).unwrap_or_else(|_| {
warn!(
"Invalid hash for user {} fetched from database (not a valid PHC string)",
data.username
);
panic!();
});
match Argon2::default().verify_password(data.password.as_bytes(), &pwhash) {
Ok(_) => {
info!("User {} logged in", data.username);
let token = token_factory(&data.username).unwrap();
println!("{:?}", token);
return Ok(HttpResponse::Ok().json(LoginResponse {
username: data.username.clone(),
token: token,
}));
}
Err(_) => {
info!("User \"{}\" failed to log in", data.username);
return Ok(HttpResponse::BadRequest().json("Error"));
}
}
}
Ok(HttpResponse::Ok().json("What happens here???"))
}

16
server/src/routes/vote.rs Normal file
View file

@ -0,0 +1,16 @@
use crate::state::ServerState;
use actix_web::web::{Data, Path};
use actix_web::{get, post, web::Json, HttpResponse, Responder, Result};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Serialize, Deserialize)]
enum VoteDirection {
Up,
Down,
}
#[post("vote/{uuid}")]
pub async fn vote(params: Path<(Uuid, VoteDirection)>, data: Data<ServerState>) -> impl Responder {
HttpResponse::InternalServerError().body("Unimplemented")
}