barycenter/src/settings.rs

147 lines
4.6 KiB
Rust
Raw Normal View History

use miette::{IntoDiagnostic, Result};
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Settings {
pub server: Server,
pub database: Database,
pub keys: Keys,
pub federation: Federation,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Server {
pub host: String,
pub port: u16,
/// If set, this is used as the issuer/public base URL, e.g., https://idp.example.com
pub public_base_url: Option<String>,
feat: add admin GraphQL API, background jobs, and user sync CLI Major Features: - Admin GraphQL API with dual endpoints (Seaography + custom) - Background job scheduler with execution tracking - Idempotent user sync CLI for Kubernetes deployments - Secure PUT /properties endpoint with Bearer token auth Admin GraphQL API: - Entity CRUD via Seaography at /admin/graphql - Custom job management API at /admin/jobs - Mutations: triggerJob - Queries: jobLogs, availableJobs - GraphiQL playgrounds for both endpoints Background Jobs: - tokio-cron-scheduler integration - Automated cleanup of expired sessions (hourly) - Automated cleanup of expired refresh tokens (hourly) - Job execution tracking in database - Manual job triggering via GraphQL User Sync CLI: - Command: barycenter sync-users --file users.json - Idempotent user synchronization from JSON - Creates new users with hashed passwords - Updates existing users (enabled, email_verified, email) - Syncs custom properties per user - Perfect for Kubernetes init containers Security Enhancements: - PUT /properties endpoint requires Bearer token - Users can only modify their own properties - Public registration disabled by default - Admin API on separate port for network isolation Database: - New job_executions table for job tracking - User update functions (update_user, update_user_email) - PostgreSQL + SQLite support maintained Configuration: - allow_public_registration setting (default: false) - admin_port setting (default: main port + 1) Documentation: - Comprehensive Kubernetes deployment guide - User sync JSON schema and examples - Init container and CronJob examples - Production deployment patterns Files Added: - src/admin_graphql.rs - GraphQL schema builders - src/admin_mutations.rs - Custom mutations and queries - src/jobs.rs - Job scheduler and tracking - src/user_sync.rs - User sync logic - src/entities/ - SeaORM entities (8 entities) - docs/kubernetes-deployment.md - K8s deployment guide - users.json.example - User sync example Dependencies: - tokio-cron-scheduler 0.13 - seaography 1.1.4 - async-graphql 7.0 - async-graphql-axum 7.0 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 18:06:50 +01:00
/// Enable public user registration. If false, only admin API can create users.
#[serde(default = "default_allow_public_registration")]
pub allow_public_registration: bool,
/// Admin GraphQL API port (defaults to port + 1)
pub admin_port: Option<u16>,
}
fn default_allow_public_registration() -> bool {
false // Secure by default - registration disabled
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Database {
feat: add admin GraphQL API, background jobs, and user sync CLI Major Features: - Admin GraphQL API with dual endpoints (Seaography + custom) - Background job scheduler with execution tracking - Idempotent user sync CLI for Kubernetes deployments - Secure PUT /properties endpoint with Bearer token auth Admin GraphQL API: - Entity CRUD via Seaography at /admin/graphql - Custom job management API at /admin/jobs - Mutations: triggerJob - Queries: jobLogs, availableJobs - GraphiQL playgrounds for both endpoints Background Jobs: - tokio-cron-scheduler integration - Automated cleanup of expired sessions (hourly) - Automated cleanup of expired refresh tokens (hourly) - Job execution tracking in database - Manual job triggering via GraphQL User Sync CLI: - Command: barycenter sync-users --file users.json - Idempotent user synchronization from JSON - Creates new users with hashed passwords - Updates existing users (enabled, email_verified, email) - Syncs custom properties per user - Perfect for Kubernetes init containers Security Enhancements: - PUT /properties endpoint requires Bearer token - Users can only modify their own properties - Public registration disabled by default - Admin API on separate port for network isolation Database: - New job_executions table for job tracking - User update functions (update_user, update_user_email) - PostgreSQL + SQLite support maintained Configuration: - allow_public_registration setting (default: false) - admin_port setting (default: main port + 1) Documentation: - Comprehensive Kubernetes deployment guide - User sync JSON schema and examples - Init container and CronJob examples - Production deployment patterns Files Added: - src/admin_graphql.rs - GraphQL schema builders - src/admin_mutations.rs - Custom mutations and queries - src/jobs.rs - Job scheduler and tracking - src/user_sync.rs - User sync logic - src/entities/ - SeaORM entities (8 entities) - docs/kubernetes-deployment.md - K8s deployment guide - users.json.example - User sync example Dependencies: - tokio-cron-scheduler 0.13 - seaography 1.1.4 - async-graphql 7.0 - async-graphql-axum 7.0 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 18:06:50 +01:00
/// SeaORM/SQLx connection string
/// Examples:
/// - SQLite: sqlite://barycenter.db?mode=rwc
/// - PostgreSQL: postgresql://user:password@localhost/barycenter
pub url: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Keys {
/// Path to persist JWKS (public keys). Default: data/jwks.json
pub jwks_path: PathBuf,
/// Optional explicit key id to set on generated keys
pub key_id: Option<String>,
/// JWS algorithm for ID tokens (currently RS256)
pub alg: String,
/// Path to persist the private key in PEM (PKCS#8). Default: data/private_key.pem
pub private_key_path: PathBuf,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Federation {
/// List of trust anchor URLs or fingerprints (placeholder for real federation)
pub trust_anchors: Vec<String>,
}
impl Default for Server {
fn default() -> Self {
Self {
host: "0.0.0.0".to_string(),
port: 8080,
public_base_url: None,
feat: add admin GraphQL API, background jobs, and user sync CLI Major Features: - Admin GraphQL API with dual endpoints (Seaography + custom) - Background job scheduler with execution tracking - Idempotent user sync CLI for Kubernetes deployments - Secure PUT /properties endpoint with Bearer token auth Admin GraphQL API: - Entity CRUD via Seaography at /admin/graphql - Custom job management API at /admin/jobs - Mutations: triggerJob - Queries: jobLogs, availableJobs - GraphiQL playgrounds for both endpoints Background Jobs: - tokio-cron-scheduler integration - Automated cleanup of expired sessions (hourly) - Automated cleanup of expired refresh tokens (hourly) - Job execution tracking in database - Manual job triggering via GraphQL User Sync CLI: - Command: barycenter sync-users --file users.json - Idempotent user synchronization from JSON - Creates new users with hashed passwords - Updates existing users (enabled, email_verified, email) - Syncs custom properties per user - Perfect for Kubernetes init containers Security Enhancements: - PUT /properties endpoint requires Bearer token - Users can only modify their own properties - Public registration disabled by default - Admin API on separate port for network isolation Database: - New job_executions table for job tracking - User update functions (update_user, update_user_email) - PostgreSQL + SQLite support maintained Configuration: - allow_public_registration setting (default: false) - admin_port setting (default: main port + 1) Documentation: - Comprehensive Kubernetes deployment guide - User sync JSON schema and examples - Init container and CronJob examples - Production deployment patterns Files Added: - src/admin_graphql.rs - GraphQL schema builders - src/admin_mutations.rs - Custom mutations and queries - src/jobs.rs - Job scheduler and tracking - src/user_sync.rs - User sync logic - src/entities/ - SeaORM entities (8 entities) - docs/kubernetes-deployment.md - K8s deployment guide - users.json.example - User sync example Dependencies: - tokio-cron-scheduler 0.13 - seaography 1.1.4 - async-graphql 7.0 - async-graphql-axum 7.0 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 18:06:50 +01:00
allow_public_registration: false,
admin_port: None, // Defaults to port + 1 if not set
}
}
}
impl Default for Database {
fn default() -> Self {
Self {
url: "sqlite://barycenter.db?mode=rwc".to_string(),
}
}
}
impl Default for Keys {
fn default() -> Self {
Self {
jwks_path: PathBuf::from("data/jwks.json"),
key_id: None,
alg: "RS256".to_string(),
private_key_path: PathBuf::from("data/private_key.pem"),
}
}
}
impl Settings {
pub fn load(path: &str) -> Result<Self> {
let mut builder = config::Config::builder()
.set_default("server.host", Server::default().host)
.into_diagnostic()?
.set_default("server.port", Server::default().port)
.into_diagnostic()?
.set_default("database.url", Database::default().url)
.into_diagnostic()?
.set_default(
"keys.jwks_path",
Keys::default().jwks_path.to_string_lossy().to_string(),
)
.into_diagnostic()?
.set_default("keys.alg", Keys::default().alg)
.into_diagnostic()?
.set_default(
"keys.private_key_path",
Keys::default()
.private_key_path
.to_string_lossy()
.to_string(),
)
.into_diagnostic()?;
// Optional file
if Path::new(path).exists() {
builder = builder.add_source(config::File::with_name(path));
}
// Environment overrides: CRABIDP__SERVER__PORT=9090, etc.
builder = builder.add_source(config::Environment::with_prefix("CRABIDP").separator("__"));
let cfg = builder.build().into_diagnostic()?;
let mut s: Settings = cfg.try_deserialize().into_diagnostic()?;
// Normalize jwks path to be relative to current dir
if s.keys.jwks_path.is_relative() {
s.keys.jwks_path = std::env::current_dir()
.into_diagnostic()?
.join(&s.keys.jwks_path);
}
if s.keys.private_key_path.is_relative() {
s.keys.private_key_path = std::env::current_dir()
.into_diagnostic()?
.join(&s.keys.private_key_path);
}
Ok(s)
}
pub fn issuer(&self) -> String {
if let Some(base) = &self.server.public_base_url {
base.trim_end_matches('/').to_string()
} else {
format!("http://{}:{}", self.server.host, self.server.port)
}
}
}