feat: Add .env.example for configuration and update README with new features, setup, and API endpoints.
This commit is contained in:
83
.env.example
Normal file
83
.env.example
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
# ============================================================================
|
||||||
|
# K-Template Configuration
|
||||||
|
# ============================================================================
|
||||||
|
# Copy this file to .env and adjust values for your environment.
|
||||||
|
# All values shown are defaults or examples.
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Server Configuration
|
||||||
|
# ============================================================================
|
||||||
|
HOST=127.0.0.1
|
||||||
|
PORT=3000
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Database Configuration
|
||||||
|
# ============================================================================
|
||||||
|
# SQLite (default)
|
||||||
|
DATABASE_URL=sqlite:data.db?mode=rwc
|
||||||
|
|
||||||
|
# PostgreSQL (alternative - requires postgres feature)
|
||||||
|
# DATABASE_URL=postgres://user:password@localhost:5432/mydb
|
||||||
|
|
||||||
|
# Connection pool settings
|
||||||
|
DB_MAX_CONNECTIONS=5
|
||||||
|
DB_MIN_CONNECTIONS=1
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Authentication Mode
|
||||||
|
# ============================================================================
|
||||||
|
# Options: session, jwt, both
|
||||||
|
# - session: Cookie-based sessions (requires auth-axum-login feature)
|
||||||
|
# - jwt: Bearer token authentication (requires auth-jwt feature)
|
||||||
|
# - both: Support both methods (try JWT first, fall back to session)
|
||||||
|
AUTH_MODE=jwt
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Session Configuration (for session/both modes)
|
||||||
|
# ============================================================================
|
||||||
|
# Must be at least 64 characters in production
|
||||||
|
SESSION_SECRET=your-super-secret-key-must-be-at-least-64-characters-long-for-security
|
||||||
|
|
||||||
|
# Set to true in production for HTTPS-only cookies
|
||||||
|
SECURE_COOKIE=false
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# JWT Configuration (for jwt/both modes)
|
||||||
|
# ============================================================================
|
||||||
|
# Must be at least 32 characters in production
|
||||||
|
JWT_SECRET=your-jwt-secret-key-at-least-32-chars
|
||||||
|
|
||||||
|
# Optional: JWT issuer and audience for token validation
|
||||||
|
JWT_ISSUER=your-app-name
|
||||||
|
JWT_AUDIENCE=your-app-audience
|
||||||
|
|
||||||
|
# Token expiry in hours (default: 24)
|
||||||
|
JWT_EXPIRY_HOURS=24
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# OIDC Configuration (optional - requires auth-oidc feature)
|
||||||
|
# ============================================================================
|
||||||
|
# Your OIDC provider's issuer URL (e.g., Keycloak, Auth0, Zitadel)
|
||||||
|
OIDC_ISSUER=https://your-oidc-provider.com
|
||||||
|
|
||||||
|
# Client credentials from your OIDC provider
|
||||||
|
OIDC_CLIENT_ID=your-client-id
|
||||||
|
OIDC_CLIENT_SECRET=your-client-secret
|
||||||
|
|
||||||
|
# Callback URL (must match what's configured in your OIDC provider)
|
||||||
|
OIDC_REDIRECT_URL=http://localhost:3000/api/v1/auth/callback
|
||||||
|
|
||||||
|
# Optional: Resource ID for audience verification
|
||||||
|
# OIDC_RESOURCE_ID=your-resource-id
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# CORS Configuration
|
||||||
|
# ============================================================================
|
||||||
|
# Comma-separated list of allowed origins
|
||||||
|
CORS_ALLOWED_ORIGINS=http://localhost:5173,http://localhost:3000
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# Production Mode
|
||||||
|
# ============================================================================
|
||||||
|
# Set to true/production/1 to enable production checks (secret length, etc.)
|
||||||
|
PRODUCTION=false
|
||||||
220
README.md
220
README.md
@@ -1,100 +1,164 @@
|
|||||||
# k-template
|
# k-template
|
||||||
|
|
||||||
A production-ready, modular Rust template for K-Suite applications, following Hexagonal Architecture principles.
|
A production-ready, modular Rust API template for K-Suite applications, following Hexagonal Architecture principles.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Hexagonal Architecture**: Clear separation of concerns between Domain, Infrastructure, and API layers.
|
- **Hexagonal Architecture**: Clear separation between Domain, Infrastructure, and API layers
|
||||||
- **Modular & Swappable**: Vendor implementations (databases, message brokers) are behind feature flags and trait objects.
|
- **Multiple Auth Modes**: Session-based, JWT, or both - fully configurable
|
||||||
- **Feature-Gated Dependencies**: Compile only what you need. Unused dependencies are not included in the build.
|
- **OIDC Integration**: Connect to any OpenID Connect provider (Keycloak, Auth0, Zitadel, etc.)
|
||||||
- **Cargo Generate Ready**: Pre-configured for `cargo-generate` to easily scaffold new services.
|
- **Database Flexibility**: SQLite (default) or PostgreSQL via feature flags
|
||||||
- **Testable**: Domain logic is pure and easily testable; Infrastructure is tested with integration tests.
|
- **Type-Safe Configuration**: Newtypes with built-in validation for all security-sensitive values
|
||||||
|
- **Cargo Generate Ready**: Pre-configured for scaffolding new services
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### 1. Clone and Configure
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/GKaszewski/k-template.git my-api
|
||||||
|
cd my-api
|
||||||
|
cp .env.example .env
|
||||||
|
# Edit .env with your configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Development (with hot reload via cargo-watch)
|
||||||
|
cargo watch -x run
|
||||||
|
|
||||||
|
# Or simply
|
||||||
|
cargo run
|
||||||
|
```
|
||||||
|
|
||||||
|
The API will be available at `http://localhost:3000/api/v1/`.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
All configuration is done via environment variables. See [.env.example](.env.example) for all options.
|
||||||
|
|
||||||
|
### Authentication Modes
|
||||||
|
|
||||||
|
Set `AUTH_MODE` to one of:
|
||||||
|
|
||||||
|
| Mode | Description | Required Features |
|
||||||
|
|------|-------------|-------------------|
|
||||||
|
| `session` | Cookie-based sessions | `auth-axum-login` |
|
||||||
|
| `jwt` | Bearer token authentication | `auth-jwt` |
|
||||||
|
| `both` | Try JWT first, fall back to session | `auth-axum-login`, `auth-jwt` |
|
||||||
|
|
||||||
|
### OIDC Integration
|
||||||
|
|
||||||
|
To enable OIDC login (e.g., "Login with Google"):
|
||||||
|
|
||||||
|
1. Enable the `auth-oidc` feature (enabled by default)
|
||||||
|
2. Configure your OIDC provider in `.env`:
|
||||||
|
```env
|
||||||
|
OIDC_ISSUER=https://your-provider.com
|
||||||
|
OIDC_CLIENT_ID=your-client-id
|
||||||
|
OIDC_CLIENT_SECRET=your-secret
|
||||||
|
OIDC_REDIRECT_URL=http://localhost:3000/api/v1/auth/callback
|
||||||
|
```
|
||||||
|
3. Users can login via `GET /api/v1/auth/login/oidc`
|
||||||
|
|
||||||
|
## Feature Flags
|
||||||
|
|
||||||
|
Features are configured in `api/Cargo.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[features]
|
||||||
|
default = ["sqlite", "auth-axum-login", "auth-oidc", "auth-jwt"]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Feature | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| `sqlite` | SQLite database support (default) |
|
||||||
|
| `postgres` | PostgreSQL database support |
|
||||||
|
| `auth-axum-login` | Session-based authentication |
|
||||||
|
| `auth-oidc` | OpenID Connect integration |
|
||||||
|
| `auth-jwt` | JWT token authentication |
|
||||||
|
| `auth-full` | All auth features combined |
|
||||||
|
|
||||||
|
### Common Configurations
|
||||||
|
|
||||||
|
**JWT-only API (stateless)**:
|
||||||
|
```toml
|
||||||
|
default = ["sqlite", "auth-jwt"]
|
||||||
|
```
|
||||||
|
|
||||||
|
**OIDC + JWT (typical SPA backend)**:
|
||||||
|
```toml
|
||||||
|
default = ["sqlite", "auth-oidc", "auth-jwt"]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Full-featured (all auth methods)**:
|
||||||
|
```toml
|
||||||
|
default = ["sqlite", "auth-full"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
|
||||||
|
| Method | Endpoint | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `POST` | `/api/v1/auth/login` | Login with email/password |
|
||||||
|
| `POST` | `/api/v1/auth/register` | Register new user |
|
||||||
|
| `POST` | `/api/v1/auth/logout` | Logout (session mode) |
|
||||||
|
| `GET` | `/api/v1/auth/me` | Get current user |
|
||||||
|
| `POST` | `/api/v1/auth/token` | Get JWT for session user |
|
||||||
|
| `GET` | `/api/v1/auth/login/oidc` | Start OIDC login flow |
|
||||||
|
| `GET` | `/api/v1/auth/callback` | OIDC callback |
|
||||||
|
|
||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
The workspace consists of three main crates:
|
```
|
||||||
|
k-template/
|
||||||
- **`template-domain`**: The core business logic.
|
├── domain/ # Core business logic (no I/O dependencies)
|
||||||
- Contains Entities, Value Objects, Repository Interfaces (Ports), and Services.
|
│ └── src/
|
||||||
- **Dependencies**: Pure Rust only (no I/O, no heavy frameworks).
|
│ ├── entities.rs # User entity
|
||||||
|
│ ├── value_objects.rs # Email, Password, OIDC newtypes
|
||||||
- **`template-infra`**: The adapters layer.
|
│ ├── repositories.rs # Repository interfaces (ports)
|
||||||
- Implements the Repository interfaces defined in `template-domain`.
|
│ └── services.rs # Domain services
|
||||||
- Content is heavily feature-gated (e.g., `sqlite`, `postgres`, `broker-nats`).
|
│
|
||||||
|
├── infra/ # Infrastructure adapters
|
||||||
- **`template-api`**: The application entry point (Driving Adapter).
|
│ └── src/
|
||||||
- Wires everything together using dependency injection.
|
│ ├── auth/ # Auth backends (OIDC, JWT)
|
||||||
- Handles HTTP/REST/gRPC interfaces.
|
│ └── user_repository.rs
|
||||||
|
│
|
||||||
## Getting Started
|
├── api/ # HTTP API layer
|
||||||
|
│ └── src/
|
||||||
### Prerequisites
|
│ ├── routes/ # API endpoints
|
||||||
|
│ ├── config.rs # Configuration
|
||||||
- Rust (latest stable)
|
│ └── state.rs # Application state
|
||||||
- `cargo-generate` (`cargo install cargo-generate`)
|
│
|
||||||
|
├── .env.example # Configuration template
|
||||||
### Creating a New Project
|
└── compose.yml # Docker Compose for local dev
|
||||||
|
|
||||||
Use `cargo-generate` to scaffold a new project from this template:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cargo generate --git https://github.com/your-org/k-template.git
|
|
||||||
```
|
```
|
||||||
|
|
||||||
You will be prompted for:
|
## Development
|
||||||
1. **Project Name**: The name of your new service.
|
|
||||||
2. **Database**: Choose between `sqlite` (default) or `postgres`.
|
|
||||||
|
|
||||||
The template will automatically clean up unused repository implementations based on your choice.
|
|
||||||
|
|
||||||
### Running Tests
|
### Running Tests
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Run all tests
|
# All tests
|
||||||
cargo test
|
cargo test --all-features
|
||||||
|
|
||||||
# Run tests for a specific feature (e.g., postgres)
|
# Domain tests only
|
||||||
cargo test -p template-infra --no-default-features --features postgres
|
cargo test -p domain
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuration & Feature Flags
|
### Database Migrations
|
||||||
|
|
||||||
This template uses Cargo features to control compilation of infrastructure adapters.
|
```bash
|
||||||
|
# SQLite
|
||||||
|
sqlx migrate run --source migrations_sqlite
|
||||||
|
|
||||||
| Feature | Description | Crate |
|
# PostgreSQL
|
||||||
|---------|-------------|-------|
|
sqlx migrate run --source migrations_postgres
|
||||||
| `sqlite` | Enables SQLite repository implementations and dependencies | `template-infra`, `template-api` |
|
|
||||||
| `postgres` | Enables PostgreSQL repository implementations and dependencies | `template-infra`, `template-api` |
|
|
||||||
| `broker-nats`| Enables NATS messaging support | `template-infra` |
|
|
||||||
|
|
||||||
|
|
||||||
### Switching Databases
|
|
||||||
|
|
||||||
To switch from the default SQLite to PostgreSQL in an existing project, update `Cargo.toml`:
|
|
||||||
|
|
||||||
**`template-api/Cargo.toml`**:
|
|
||||||
```toml
|
|
||||||
[features]
|
|
||||||
default = ["postgres"]
|
|
||||||
# ...
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**`template-infra/Cargo.toml`**:
|
## License
|
||||||
```toml
|
|
||||||
[features]
|
|
||||||
default = ["postgres"]
|
|
||||||
# ...
|
|
||||||
```
|
|
||||||
|
|
||||||
## Architecture Guide
|
MIT
|
||||||
|
|
||||||
### Adding a New Feature
|
|
||||||
|
|
||||||
1. **Domain**: Define the Entity, Value Objects, and Repository Interface in `template-domain`.
|
|
||||||
2. **Infra**: Implement the Repository Interface in `template-infra`.
|
|
||||||
- **Important**: Wrap your implementation in a feature flag (e.g., `#[cfg(feature = "my-feature")]`).
|
|
||||||
3. **API**: Wire the new service in `template-api/src/main.rs` or a dedicated module.
|
|
||||||
|
|
||||||
### Vendor Isolation
|
|
||||||
|
|
||||||
All external dependencies (SQLx, NATS, etc.) should stay within `template-infra` or `template-api`. The `template-domain` crate should remain agnostic to specific technologies.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user