feat(api): implement user authentication and registration endpoints

- Add main application logic in `api/src/main.rs` to initialize server, database, and services.
- Create authentication routes in `api/src/routes/auth.rs` for login, register, logout, and user info retrieval.
- Implement configuration route in `api/src/routes/config.rs` to expose application settings.
- Define application state management in `api/src/state.rs` to share user service and configuration.
- Set up Docker Compose configuration in `compose.yml` for backend, worker, and database services.
- Establish domain logic in `domain` crate with user entities, repositories, and services.
- Implement SQLite user repository in `infra/src/user_repository.rs` for user data persistence.
- Create database migration handling in `infra/src/db.rs` and session store in `infra/src/session_store.rs`.
- Add necessary dependencies and features in `Cargo.toml` files for both `domain` and `infra` crates.
This commit is contained in:
2026-01-02 13:07:09 +01:00
parent 7dbdf3f00b
commit 1d141c7a97
27 changed files with 208 additions and 130 deletions

54
infra/src/factory.rs Normal file
View File

@@ -0,0 +1,54 @@
use std::sync::Arc;
#[cfg(feature = "sqlite")]
use crate::SqliteUserRepository;
use crate::db::DatabasePool;
use domain::UserRepository;
#[derive(Debug, thiserror::Error)]
pub enum FactoryError {
#[error("Database error: {0}")]
Database(#[from] sqlx::Error),
#[error("Not implemented: {0}")]
NotImplemented(String),
#[error("Infrastructure error: {0}")]
Infrastructure(#[from] domain::DomainError),
}
pub type FactoryResult<T> = Result<T, FactoryError>;
pub async fn build_user_repository(pool: &DatabasePool) -> FactoryResult<Arc<dyn UserRepository>> {
match pool {
#[cfg(feature = "sqlite")]
DatabasePool::Sqlite(pool) => Ok(Arc::new(SqliteUserRepository::new(pool.clone()))),
#[cfg(feature = "postgres")]
DatabasePool::Postgres(pool) => Ok(Arc::new(
crate::user_repository::PostgresUserRepository::new(pool.clone()),
)),
#[allow(unreachable_patterns)]
_ => Err(FactoryError::NotImplemented(
"No database feature enabled".to_string(),
)),
}
}
pub async fn build_session_store(
pool: &DatabasePool,
) -> FactoryResult<crate::session_store::InfraSessionStore> {
match pool {
#[cfg(feature = "sqlite")]
DatabasePool::Sqlite(pool) => {
let store = tower_sessions_sqlx_store::SqliteStore::new(pool.clone());
Ok(crate::session_store::InfraSessionStore::Sqlite(store))
}
#[cfg(feature = "postgres")]
DatabasePool::Postgres(pool) => {
let store = tower_sessions_sqlx_store::PostgresStore::new(pool.clone());
Ok(crate::session_store::InfraSessionStore::Postgres(store))
}
#[allow(unreachable_patterns)]
_ => Err(FactoryError::NotImplemented(
"No database feature enabled".to_string(),
)),
}
}