diff --git a/Dockerfile b/Dockerfile index e5bda92..4ec4612 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ COPY . . RUN cargo build --release # Small runtime image -FROM alpine:3.22.4 +FROM alpine:3.22 WORKDIR /app COPY --from=builder /app/target/release/rhythm-backend /app/executable diff --git a/compose.prod.yaml b/compose.prod.yaml new file mode 100644 index 0000000..258426a --- /dev/null +++ b/compose.prod.yaml @@ -0,0 +1,37 @@ +services: + api-prod: + image: git.kanopo.dev/rhythm/rhythm-backend:latest + container_name: rhythm-api-prod + restart: unless-stopped + ports: + - "6969:6969" + environment: + DATABASE_URL: postgres://${DB_USERNAME}:${DB_PASSWORD}@db-prod:${DB_PORT}/${DB_NAME}?schema=public&sslmode=disable + env_file: + - ".env" + depends_on: + db-prod: + condition: service_healthy + profiles: + - prod + + db-prod: + image: postgres:18.0-alpine + restart: unless-stopped + container_name: rhythm-db-prod + environment: + POSTGRES_USER: ${DB_USERNAME} + POSTGRES_PASSWORD: ${DB_PASSWORD} + POSTGRES_DB: ${DB_NAME} + volumes: + - db:/var/lib/postgresql/data + profiles: + - prod + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${DB_USERNAME} -d ${DB_NAME}"] + interval: 5s + timeout: 10s + retries: 3 + +volumes: + db: diff --git a/src/main.rs b/src/main.rs index 5f803f6..0d8bdcb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ mod logging; mod server; mod service; mod state; +mod utils; use errors::MainError; #[tokio::main] diff --git a/src/service/auth_service.rs b/src/service/auth_service.rs index 445b761..41daf29 100644 --- a/src/service/auth_service.rs +++ b/src/service/auth_service.rs @@ -1,8 +1,10 @@ use axum::Json; use crate::controller::model::auth_model::*; +use crate::db::repository::user_repository; use crate::errors::AppError; use crate::state::AppState; +use crate::utils::hash; pub async fn login(state: &AppState, req: LoginRequest) -> Result, AppError> { todo!() @@ -11,5 +13,7 @@ pub async fn register( state: &AppState, req: RegisterRequest, ) -> Result, AppError> { - todo!() + let h = hash::hash(&req.password)?; + let user = user_repository::create_user(&state.db, req.email, h); + todo!("generate jwt and refresh token") } diff --git a/src/utils/hash.rs b/src/utils/hash.rs new file mode 100644 index 0000000..1fcf691 --- /dev/null +++ b/src/utils/hash.rs @@ -0,0 +1,28 @@ +use argon2::{ + Argon2, PasswordHash, PasswordHasher, PasswordVerifier, + password_hash::{SaltString, rand_core::OsRng}, +}; + +use crate::errors::AppError; + +pub fn hash(text: &str) -> Result { + let salt = SaltString::generate(&mut OsRng); + let argon2 = Argon2::default(); + + let res = argon2 + .hash_password(text.as_bytes(), &salt) + .map_err(|e| AppError::InvalidConfig(format!("Invalid hash {}", e)))?; + + Ok(res.to_string()) +} +pub fn verify(text: &str, hash: &str) -> Result { + let parsed_hash = PasswordHash::new(hash) + .map_err(|e| AppError::InvalidConfig(format!("Invalid hash {}", e)))?; + + let argon2 = Argon2::default(); + let res = argon2 + .verify_password(text.as_bytes(), &parsed_hash) + .is_ok(); + + Ok(res) +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs new file mode 100644 index 0000000..ec5d33c --- /dev/null +++ b/src/utils/mod.rs @@ -0,0 +1 @@ +pub mod hash;