feat: Transform project into a cargo-generate template with configurable authentication features and improved local user registration.

This commit is contained in:
2026-01-06 05:53:01 +01:00
parent 9219a586b1
commit c368293cd4
12 changed files with 213 additions and 45 deletions

View File

@@ -5,7 +5,7 @@ edition = "2024"
default-run = "api"
[features]
default = ["sqlite", "auth-axum-login", "auth-oidc", "auth-jwt"]
default = ["sqlite"]
sqlite = ["infra/sqlite", "tower-sessions-sqlx-store/sqlite"]
postgres = ["infra/postgres", "tower-sessions-sqlx-store/postgres"]
auth-axum-login = ["infra/auth-axum-login"]

63
api/Cargo.toml.template Normal file
View File

@@ -0,0 +1,63 @@
[package]
name = "api"
version = "0.1.0"
edition = "2024"
default-run = "api"
[features]
default = ["{{database}}"{% if auth_session %}, "auth-axum-login"{% endif %}{% if auth_oidc %}, "auth-oidc"{% endif %}{% if auth_jwt %}, "auth-jwt"{% endif %}]
sqlite = ["infra/sqlite", "tower-sessions-sqlx-store/sqlite"]
postgres = ["infra/postgres", "tower-sessions-sqlx-store/postgres"]
auth-axum-login = ["infra/auth-axum-login"]
auth-oidc = ["infra/auth-oidc"]
auth-jwt = ["infra/auth-jwt"]
auth-full = ["auth-axum-login", "auth-oidc", "auth-jwt"]
[dependencies]
k-core = { git = "https://git.gabrielkaszewski.dev/GKaszewski/k-core", features = [
"logging",
"db-sqlx",
"{{database}}",
"http",
"auth",
"sessions-db",
] }
domain = { path = "../domain" }
infra = { path = "../infra", default-features = false, features = ["{{database}}"] }
#Web framework
axum = { version = "0.8.8", features = ["macros"] }
tower = "0.5.2"
tower-http = { version = "0.6.2", features = ["cors", "trace"] }
# Authentication
# Moved to infra
tower-sessions-sqlx-store = { version = "0.15", features = ["{{database}}"] }
# password-auth removed
time = "0.3"
async-trait = "0.1.89"
# Async runtime
tokio = { version = "1.48.0", features = ["full"] }
# Serialization
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0"
# Validation via domain newtypes (Email, Password)
# Error handling
thiserror = "2.0.17"
anyhow = "1.0"
# Utilities
chrono = { version = "0.4.42", features = ["serde"] }
uuid = { version = "1.19.0", features = ["v4", "serde"] }
# Logging
tracing = "0.1"
tracing-subscriber = { version = "0.3.22", features = ["env-filter"] }
dotenvy = "0.15.7"
config = "0.15.19"
tower-sessions = "0.14.0"

View File

@@ -10,6 +10,7 @@ use uuid::Uuid;
/// Login request with validated email and password newtypes
#[derive(Debug, Deserialize)]
#[allow(dead_code)]
pub struct LoginRequest {
/// Email is validated on deserialization
pub email: Email,
@@ -19,6 +20,7 @@ pub struct LoginRequest {
/// Register request with validated email and password newtypes
#[derive(Debug, Deserialize)]
#[allow(dead_code)]
pub struct RegisterRequest {
/// Email is validated on deserialization
pub email: Email,

View File

@@ -131,20 +131,3 @@ async fn try_session_auth(parts: &mut Parts) -> Result<Option<User>, ApiError> {
Ok(None)
}
/// Fallback for when auth-axum-login is not enabled
#[cfg(not(feature = "auth-axum-login"))]
async fn try_session_auth(_parts: &mut Parts) -> Result<Option<User>, ApiError> {
Ok(None)
}
/// Fallback for when auth-jwt is not enabled but auth mode requires it
#[cfg(not(feature = "auth-jwt"))]
async fn try_jwt_auth(_parts: &mut Parts, state: &AppState) -> Result<Option<User>, ApiError> {
if matches!(state.config.auth_mode, AuthMode::Jwt) {
return Err(ApiError::Internal(
"JWT auth mode configured but auth-jwt feature not enabled".to_string(),
));
}
Ok(None)
}

View File

@@ -154,10 +154,13 @@ async fn register(
)));
}
// Using email as subject for local auth for now
// Hash password
let password_hash = infra::auth::backend::hash_password(payload.password.as_ref());
// Create user with password
let user = state
.user_service
.find_or_create(&email.as_ref().to_string(), email.as_ref())
.create_local(email.as_ref(), &password_hash)
.await?;
let auth_mode = state.config.auth_mode;