//! Authentication and API key management use serde::{Deserialize, Serialize}; use std::collections::HashMap; use uuid::Uuid; /// API key scope/permission level #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum ApiKeyScope { /// Full access - can manage keys, runners, jobs Admin, /// Can register new runners Registrar, /// Can create and manage jobs User, } impl ApiKeyScope { pub fn as_str(&self) -> &'static str { match self { ApiKeyScope::Admin => "admin", ApiKeyScope::Registrar => "registrar", ApiKeyScope::User => "user", } } } /// An API key with metadata #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ApiKey { /// The actual key value (UUID or custom string) pub key: String, /// Human-readable name for the key pub name: String, /// Permission scope pub scope: ApiKeyScope, /// When the key was created pub created_at: String, /// Optional expiration timestamp pub expires_at: Option, } impl ApiKey { /// Create a new API key with a generated UUID pub fn new(name: String, scope: ApiKeyScope) -> Self { Self { key: Uuid::new_v4().to_string(), name, scope, created_at: chrono::Utc::now().to_rfc3339(), expires_at: None, } } /// Create a new API key with a specific key value pub fn with_key(key: String, name: String, scope: ApiKeyScope) -> Self { Self { key, name, scope, created_at: chrono::Utc::now().to_rfc3339(), expires_at: None, } } } /// Response for auth verification #[derive(Debug, Clone, Serialize, Deserialize)] pub struct AuthVerifyResponse { pub valid: bool, pub name: String, pub scope: String, } /// Method authorization requirements /// Maps RPC method names to required scopes pub fn get_method_required_scopes(method: &str) -> Option> { use ApiKeyScope::*; match method { // Admin-only methods "key.create" | "key.generate" | "key.delete" | "key.list" | "supervisor.info" => { Some(vec![Admin]) } // Admin or Registrar methods "runner.create" | "runner.remove" => { Some(vec![Admin, Registrar]) } // Admin or User methods "job.create" | "job.run" | "job.start" | "job.stop" | "job.delete" => { Some(vec![Admin, User]) } // Public methods (no auth required) "rpc.discover" => None, // Any authenticated user (read-only operations) "runner.list" | "runner.ping" | "job.get" | "job.list" | "job.status" | "job.result" | "job.logs" | "auth.verify" => { Some(vec![Admin, Registrar, User]) } // Default: require authentication _ => Some(vec![Admin, Registrar, User]), } }