diff --git a/Cargo.lock b/Cargo.lock index 33deb384..ef9ecce2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -255,6 +255,7 @@ dependencies = [ "dotenv", "jsonwebtoken", "serde", + "serde_json", "sqlx", "uuid", ] @@ -2176,6 +2177,7 @@ dependencies = [ "async-io 1.13.0", "async-std", "bytes", + "chrono", "crc", "crossbeam-queue", "either", @@ -2250,6 +2252,7 @@ dependencies = [ "bitflags 2.9.0", "byteorder", "bytes", + "chrono", "crc", "digest", "dotenvy", @@ -2291,6 +2294,7 @@ dependencies = [ "base64", "bitflags 2.9.0", "byteorder", + "chrono", "crc", "dotenvy", "etcetera", @@ -2325,6 +2329,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f85ca71d3a5b24e64e1d08dd8fe36c6c95c339a896cc33068148906784620540" dependencies = [ "atoi", + "chrono", "flume", "futures-channel", "futures-core", diff --git a/Cargo.toml b/Cargo.toml index 6b43707d..712d4efa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,9 +6,14 @@ edition = "2024" [dependencies] actix-web = "4" # there is a possibility to add TLS support (https://github.com/launchbadge/sqlx?tab=readme-ov-file#install) -sqlx = { version = "0.8", features = ["runtime-async-std", "postgres"] } +sqlx = { version = "0.8", features = [ + "runtime-async-std", + "postgres", + "chrono", +] } dotenv = "0.15.0" serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" chrono = { version = "0.4", features = ["serde"] } uuid = { version = "1.15.1", features = ["serde", "v4"] } jsonwebtoken = "9.3.1" diff --git a/README.md b/README.md index 851444d4..caa4cc89 100644 --- a/README.md +++ b/README.md @@ -8,4 +8,11 @@ Copy `.env` to `.env.local` and replace the values with yours ### Optional -The `docker/` folder contains some containers to various services used by `actix-index`. Feel free to use these or a local install of them \ No newline at end of file +The `docker/` folder contains some containers to various services used by `actix-index`. Feel free to use these or a local install of them + + +## Developing + +``` +cargo run +``` \ No newline at end of file diff --git a/migrations/20250312215600_initdb.sql b/migrations/20250312215600_initdb.sql index 06e83500..f350f77c 100644 --- a/migrations/20250312215600_initdb.sql +++ b/migrations/20250312215600_initdb.sql @@ -1,10 +1,10 @@ CREATE TABLE users ( id SERIAL PRIMARY KEY, - username VARCHAR(20) NOT NULL, + username VARCHAR(20) UNIQUE NOT NULL, email VARCHAR(255) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, - registered_from_ip INET NOT NULL, + registered_from_ip VARCHAR(15) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, description TEXT NOT NULL DEFAULT '', uploaded BIGINT NOT NULL DEFAULT 1, diff --git a/src/handlers/auth_handler.rs b/src/handlers/auth_handler.rs index 76e250c0..341b27d5 100644 --- a/src/handlers/auth_handler.rs +++ b/src/handlers/auth_handler.rs @@ -37,7 +37,7 @@ pub async fn register( .to_string(); match create_user(&pool, &new_user, &client_ip, &password_hash).await { - Ok(user) => HttpResponse::Created().json(user), + Ok(user) => HttpResponse::Created().json(serde_json::json!(user)), Err(err) => HttpResponse::InternalServerError().json(err.to_string()), } } diff --git a/src/models/user.rs b/src/models/user.rs index c1dd3eb7..181340fa 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -1,37 +1,37 @@ -use std::{net::IpAddr, time::Duration}; - +use chrono::NaiveDateTime; use serde::{Deserialize, Serialize}; +use sqlx::prelude::FromRow; -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, FromRow)] pub struct User { - pub id: u32, + pub id: i32, pub username: String, pub email: String, pub password_hash: String, - pub registered_from_ip: IpAddr, - pub created_at: chrono::NaiveDateTime, + pub registered_from_ip: String, + pub created_at: NaiveDateTime, pub description: String, - pub uploaded: u64, - pub downloaded: u64, + pub uploaded: i64, + pub downloaded: i64, pub ratio: f64, pub required_ratio: f64, - pub last_seen: chrono::NaiveDateTime, + pub last_seen: NaiveDateTime, pub class: String, - pub forum_posts: u32, - pub forum_threads: u32, - pub group_comments: u32, - pub torrent_comments: u32, - pub request_comments: u32, - pub artist_comments: u64, - pub seeding: u32, - pub leeching: u32, - pub snatched: u32, - pub seeding_size: u64, - pub requests_filled: u64, - pub collages_started: u64, - pub requests_voted: u64, - pub average_seeding_time: Duration, - pub invited: u64, + pub forum_posts: i32, + pub forum_threads: i32, + pub group_comments: i32, + pub torrent_comments: i32, + pub request_comments: i32, + pub artist_comments: i64, + pub seeding: i32, + pub leeching: i32, + pub snatched: i32, + pub seeding_size: i64, + pub requests_filled: i64, + pub collages_started: i64, + pub requests_voted: i64, + pub average_seeding_time: i64, //in seconds + pub invited: i64, } #[derive(Debug, Serialize, Deserialize)] diff --git a/src/repositories/auth_repository.rs b/src/repositories/auth_repository.rs index 3bed62a1..358e1375 100644 --- a/src/repositories/auth_repository.rs +++ b/src/repositories/auth_repository.rs @@ -1,6 +1,7 @@ -use crate::models::user::Register; +use crate::models::user::{Register, User}; use actix_web::web; use sqlx::PgPool; +use sqlx::postgres::{PgQueryResult, PgRow}; use std::error::Error; use std::net::IpAddr; @@ -9,24 +10,31 @@ pub async fn create_user( user: &Register, from_ip: &IpAddr, password_hash: &str, -) -> Result<(), Box> { +) -> Result> { // let user = user.into_inner(); let query = r#" INSERT INTO users (username, email, password_hash, registered_from_ip) VALUES ($1, $2, $3, $4::inet) + RETURNING * "#; - let result = sqlx::query(query) + let result = sqlx::query_as::<_, User>(query) .bind(&user.username) .bind(&user.email) .bind(password_hash) .bind(from_ip.to_string()) - .execute(pool.get_ref()) + .fetch_one(pool.get_ref()) .await; match result { - Ok(_) => Ok(()), - Err(e) => Err(format!("Failed to create user: {:?}", e).into()), + Ok(_) => Ok(result.unwrap()), + Err(e) => { + let error_message = match e { + sqlx::Error::Database(db_error) => db_error.message().to_string(), + _ => "Unknown error".to_string(), + }; + Err(format!("Failed to create user: {}", error_message).into()) + } } }