Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/db/diesel.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,9 @@ file = "src/schema.rs"
patch_file = "src/schema.patch"
custom_type_derives = ["diesel::query_builder::QueryId"]

[print_schema.auth]
file = "src/schemas/auth_schema.rs"
schema = "auth"

[migrations_directory]
dir = "migrations"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP SCHEMA IF EXISTS auth;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CREATE SCHEMA auth;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE IF EXISTS auth.users;
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CREATE TABLE auth.users (
user_id SERIAL PRIMARY KEY,
username TEXT UNIQUE NOT NULL
);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE IF EXISTS auth.auth_method_password_bcrypt;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-- Your SQL goes here
CREATE TABLE auth.auth_method_password_bcrypt (
user_id INTEGER PRIMARY KEY,
password_hash TEXT NOT NULL,
work_factor INTEGER,
FOREIGN KEY (user_id) REFERENCES auth.users(user_id)
ON DELETE CASCADE
);
3 changes: 3 additions & 0 deletions packages/db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
use std::fmt::Debug;

pub mod schema;
pub mod schemas {
pub mod auth_schema;
}

#[cfg(feature = "embedded")]
pub mod embedded;
Expand Down
25 changes: 25 additions & 0 deletions packages/db/src/schemas/auth_schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// @generated automatically by Diesel CLI.

pub mod auth {
diesel::table! {
auth.auth_method_password_bcrypt (user_id) {
user_id -> Int4,
password_hash -> Text,
work_factor -> Nullable<Int4>,
}
}

diesel::table! {
auth.users (user_id) {
user_id -> Int4,
username -> Text,
}
}

diesel::joinable!(auth_method_password_bcrypt -> users (user_id));

diesel::allow_tables_to_appear_in_same_query!(
auth_method_password_bcrypt,
users,
);
}
69 changes: 69 additions & 0 deletions packages/service/src/auth/authentication.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use warp::{Reply};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use retrom_db::Pool;

use diesel::{prelude::*};
use diesel_async::RunQueryDsl;
use retrom_db::schemas::auth_schema;

#[derive(Queryable, Selectable)]
#[diesel(table_name = auth_schema::auth::users)]
pub struct User {
pub user_id: i32,
pub username: String,
}

// Request/Response DTOs
#[derive(Deserialize)]
pub struct LoginRequest {
pub username: String,
pub password: String,
}

#[derive(Serialize)]
pub struct LoginResponse {
pub token: String,
}

// TODO: Implement password validation
// TODO: Implement token generation and validation
// TODO: Return proper error responses

pub async fn handle_login(
request: LoginRequest,
pool: Arc<Pool>,
) -> Result<impl Reply, warp::Rejection> {

tracing::info!("Login attempt for user: {}", request.username);

let mut conn = pool.get().await.map_err(|e| {
tracing::error!("Failed to get database connection: {}", e);
warp::reject()
})?;

let user_result: QueryResult<User> = auth_schema::auth::users::table
.filter(auth_schema::auth::users::username.eq(&request.username))
.select((auth_schema::auth::users::user_id, auth_schema::auth::users::username))
.first::<User>(&mut conn)
.await;

match user_result {
Ok(user) => {
tracing::info!("Found user - ID: {}, Username: {}", user.user_id, user.username);
},
Err(diesel::NotFound) => {
tracing::warn!("User not found: {}", request.username);
return Err(warp::reject::not_found());
},
Err(e) => {
tracing::error!("Database error querying user: {}", e);
return Err(warp::reject());
}
}

let response = LoginResponse {
token: String::new(),
};
return Ok(warp::reply::json(&response));
}
30 changes: 30 additions & 0 deletions packages/service/src/auth/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use warp::{filters::BoxedFilter, Filter, Reply};
use std::sync::Arc;
use retrom_db::Pool;

pub mod authentication;

// Adds HTTP routes for auth endpoints
#[tracing::instrument(skip(pool))]
pub fn auth(
pool: Arc<Pool>,
) -> BoxedFilter<(impl Reply,)> {

let login = warp::path("login")
.and(warp::post())
.and(warp::body::json::<authentication::LoginRequest>())
.and(with_db_pool(pool.clone()))
.and_then(authentication::handle_login);

warp::path("auth")
.and(login)
.with(warp::filters::trace::request())
.boxed()
}

// Database pool filter helper (following your REST pattern)
pub fn with_db_pool(
pool: Arc<Pool>,
) -> impl Filter<Extract = (Arc<Pool>,), Error = std::convert::Infallible> + Clone {
warp::any().map(move || pool.clone())
}
1 change: 1 addition & 0 deletions packages/service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub mod meta;
mod providers;
mod rest;
pub mod trace;
pub mod auth;

pub const DEFAULT_PORT: i32 = 5101;
pub const DEFAULT_DB_URL: &str = "postgres://postgres:postgres@localhost/retrom";
Expand Down
10 changes: 8 additions & 2 deletions packages/service/src/rest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use warp::{
Filter,
};
use web::web;
use crate::auth::auth;

pub mod error;
pub mod file;
Expand Down Expand Up @@ -40,8 +41,13 @@ pub fn rest_service(
let headers = warp::reply::with::headers(headers);

let routes = warp::path("rest")
.and(file(pool.clone()).or(game(pool.clone())).or(public()))
.or(web());
.and(
file(pool.clone())
.or(game(pool.clone()))
.or(public())
)
.or(web())
.or(auth(pool.clone()));

let cors = warp::cors().allow_any_origin();

Expand Down