authx-cli 0.1.2

authx command-line interface — serve, migrate, and manage users
use std::path::Path;

use anyhow::Result;
use clap::Args;

#[derive(Args)]
pub struct InitArgs {
    /// Target directory (defaults to current directory).
    #[arg(default_value = ".")]
    path: String,

    /// Force overwrite if files already exist.
    #[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()
        );
    }

    // Generate a random 32-byte encryption key
    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(())
}