use std::path::Path;
use anyhow::Result;
use clap::Args;
#[derive(Args)]
pub struct InitArgs {
#[arg(default_value = ".")]
path: String,
#[arg(long, default_value_t = false)]
force: bool,
}
pub async fn run(args: InitArgs) -> Result<()> {
let dir = Path::new(&args.path);
if !dir.exists() {
std::fs::create_dir_all(dir)?;
tracing::info!(path = %dir.display(), "created directory");
}
let env_file = dir.join(".env.authx");
if env_file.exists() && !args.force {
anyhow::bail!(
"{} already exists — use --force to overwrite",
env_file.display()
);
}
let key_bytes: [u8; 32] = rand::random();
let key_hex = hex::encode(key_bytes);
let env_content = format!(
r#"# authx-rs configuration
# Generated by `authx init` — customize for your environment.
# Server
AUTHX_BIND=0.0.0.0:3000
AUTHX_SECURE_COOKIES=false
# Database (comment out for in-memory store)
# DATABASE_URL=postgres://user:pass@localhost/authx
# Session
AUTHX_SESSION_TTL=2592000
# CSRF
AUTHX_TRUSTED_ORIGINS=http://localhost:3000
# Rate limiting
AUTHX_RATE_LIMIT=30
AUTHX_RATE_LIMIT_WINDOW_SECS=60
# Account lockout
AUTHX_LOCKOUT_FAILURES=5
AUTHX_LOCKOUT_MINUTES=15
# Encryption (32 bytes hex — used for OAuth/federation token encryption)
AUTHX_ENCRYPTION_KEY={key_hex}
# OIDC Provider (uncomment to enable authx as an IdP)
# AUTHX_OIDC_ISSUER=http://localhost:3000
# AUTHX_OIDC_ACCESS_TOKEN_TTL=3600
# AUTHX_OIDC_REFRESH_TOKEN_TTL=2592000
# AUTHX_OIDC_DEVICE_CODE_TTL=600
# AUTHX_OIDC_VERIFICATION_URI=http://localhost:3000/oidc/device
# WebAuthn / Passkeys
# Use your effective domain in production (e.g. auth.example.com).
AUTHX_WEBAUTHN_RP_ID=localhost
AUTHX_WEBAUTHN_RP_ORIGIN=http://localhost:3000
AUTHX_WEBAUTHN_CHALLENGE_TTL=600
"#
);
std::fs::write(&env_file, env_content)?;
tracing::info!(path = %env_file.display(), "wrote config");
tracing::info!("Initialized authx project at {}", dir.display());
tracing::info!("Files created:");
tracing::info!(" {} — environment configuration", env_file.display());
tracing::info!("Next steps:");
tracing::info!(" 1. Edit {} for your environment", env_file.display());
tracing::info!(" 2. Set DATABASE_URL for PostgreSQL (or leave commented for in-memory)");
tracing::info!(" 3. Run: authx serve");
tracing::info!(" 4. Optionally seed demo data: authx seed");
Ok(())
}