scaffold: Backend API routes, DB queries, and middleware stubs
88 handler stubs across 13 route files, 66 DB query stubs across 11 modules, auth/license extractors, and rate limit middleware. All bodies are todo!() — ready for Phase 1b implementation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
31
backend/src/db/chat.rs
Normal file
31
backend/src/db/chat.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
use sqlx::PgPool;
|
||||
use uuid::Uuid;
|
||||
use anyhow::Result;
|
||||
|
||||
// TODO: Define ChatMessage struct (id, server_id, steam_id, player_name, message, channel, flagged, timestamp)
|
||||
// TODO: Define PlayerAction struct (id, server_id, steam_id, action_type, reason, performed_by, created_at)
|
||||
|
||||
/// Store an incoming chat message from the game server.
|
||||
pub async fn insert_chat_message(pool: &PgPool, server_id: Uuid, steam_id: &str, player_name: &str, message: &str, channel: &str) -> Result<Uuid> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Retrieve chat messages for a server with pagination.
|
||||
pub async fn get_chat_messages(pool: &PgPool, server_id: Uuid, limit: i64, offset: i64) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Flag a chat message for review (toxic, spam, etc.).
|
||||
pub async fn flag_message(pool: &PgPool, message_id: Uuid, flagged: bool) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Get moderation actions taken against a player.
|
||||
pub async fn get_player_actions(pool: &PgPool, server_id: Uuid, steam_id: &str) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Record a moderation action (kick, ban, mute, warn).
|
||||
pub async fn create_player_action(pool: &PgPool, server_id: Uuid, steam_id: &str, action_type: &str, reason: &str, performed_by: Uuid) -> Result<Uuid> {
|
||||
todo!()
|
||||
}
|
||||
35
backend/src/db/licenses.rs
Normal file
35
backend/src/db/licenses.rs
Normal file
@@ -0,0 +1,35 @@
|
||||
use sqlx::PgPool;
|
||||
use uuid::Uuid;
|
||||
use anyhow::Result;
|
||||
|
||||
// TODO: Define License struct (id, user_id, license_key, status, tier, modules, max_servers, activated_at, expires_at, created_at)
|
||||
|
||||
/// Create a new license record.
|
||||
pub async fn create_license(pool: &PgPool, user_id: Uuid, license_key: &str, tier: &str) -> Result<Uuid> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Look up a license by its key string (used during activation).
|
||||
pub async fn get_license_by_key(pool: &PgPool, license_key: &str) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Fetch a license by its primary key.
|
||||
pub async fn get_license_by_id(pool: &PgPool, license_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Fetch all licenses belonging to a user.
|
||||
pub async fn get_license_by_user(pool: &PgPool, user_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Mark a license as activated and record the activation timestamp.
|
||||
pub async fn activate_license(pool: &PgPool, license_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Update the status of a license (active, suspended, expired, revoked).
|
||||
pub async fn update_license_status(pool: &PgPool, license_id: Uuid, status: &str) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
36
backend/src/db/maps.rs
Normal file
36
backend/src/db/maps.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
use sqlx::PgPool;
|
||||
use uuid::Uuid;
|
||||
use anyhow::Result;
|
||||
|
||||
// TODO: Define Map struct (id, server_id, name, file_path, size_bytes, uploaded_at)
|
||||
// TODO: Define MapRotation struct (id, server_id, map_ids, current_index, auto_rotate)
|
||||
|
||||
/// Upload/register a new custom map.
|
||||
pub async fn create_map(pool: &PgPool, server_id: Uuid, name: &str, file_path: &str, size_bytes: i64) -> Result<Uuid> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Get all maps for a server.
|
||||
pub async fn get_maps(pool: &PgPool, server_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Fetch a single map by ID.
|
||||
pub async fn get_map_by_id(pool: &PgPool, map_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Delete a map record (and its associated file reference).
|
||||
pub async fn delete_map(pool: &PgPool, map_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Get the current map rotation configuration for a server.
|
||||
pub async fn get_map_rotation(pool: &PgPool, server_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Update the map rotation (set map order, current index, toggle auto-rotate).
|
||||
pub async fn update_map_rotation(pool: &PgPool, server_id: Uuid, map_ids: &[Uuid], auto_rotate: bool) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
14
backend/src/db/mod.rs
Normal file
14
backend/src/db/mod.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
// Database query modules — each corresponds to a domain
|
||||
// Queries use sqlx with compile-time verification against PostgreSQL
|
||||
|
||||
pub mod users;
|
||||
pub mod licenses;
|
||||
pub mod servers;
|
||||
pub mod wipes;
|
||||
pub mod maps;
|
||||
pub mod plugins;
|
||||
pub mod teams;
|
||||
pub mod notifications;
|
||||
pub mod chat;
|
||||
pub mod stats;
|
||||
pub mod store;
|
||||
15
backend/src/db/notifications.rs
Normal file
15
backend/src/db/notifications.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
use sqlx::PgPool;
|
||||
use uuid::Uuid;
|
||||
use anyhow::Result;
|
||||
|
||||
// TODO: Define NotificationConfig struct (id, server_id, discord_webhook_url, events jsonb, enabled, created_at, updated_at)
|
||||
|
||||
/// Fetch the notification configuration for a server.
|
||||
pub async fn get_notification_config(pool: &PgPool, server_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Insert or update the notification configuration for a server.
|
||||
pub async fn upsert_notification_config(pool: &PgPool, server_id: Uuid, discord_webhook_url: Option<&str>, events: &str, enabled: bool) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
30
backend/src/db/plugins.rs
Normal file
30
backend/src/db/plugins.rs
Normal file
@@ -0,0 +1,30 @@
|
||||
use sqlx::PgPool;
|
||||
use uuid::Uuid;
|
||||
use anyhow::Result;
|
||||
|
||||
// TODO: Define Plugin struct (id, server_id, name, version, author, is_enabled, config_json, wipe_on_map, wipe_on_bp, created_at, updated_at)
|
||||
|
||||
/// Insert or update a plugin record (upsert by server_id + name).
|
||||
pub async fn upsert_plugin(pool: &PgPool, server_id: Uuid, name: &str, version: &str, author: Option<&str>) -> Result<Uuid> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Get all plugins for a server.
|
||||
pub async fn get_plugins(pool: &PgPool, server_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Update the JSON configuration blob for a plugin.
|
||||
pub async fn update_plugin_config(pool: &PgPool, plugin_id: Uuid, config_json: &str) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Update wipe-related settings for a plugin (wipe on map, wipe on BP).
|
||||
pub async fn update_plugin_wipe_settings(pool: &PgPool, plugin_id: Uuid, wipe_on_map: bool, wipe_on_bp: bool) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Remove a plugin record.
|
||||
pub async fn delete_plugin(pool: &PgPool, plugin_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
52
backend/src/db/servers.rs
Normal file
52
backend/src/db/servers.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
use sqlx::PgPool;
|
||||
use uuid::Uuid;
|
||||
use anyhow::Result;
|
||||
|
||||
// TODO: Define ServerConnection struct (id, license_id, name, host, rcon_port, rcon_password_encrypted, query_port, created_at)
|
||||
// TODO: Define ServerConfig struct (id, server_id, seed, world_size, max_players, hostname, description, header_image_url, etc.)
|
||||
// TODO: Define GameAdmin struct (id, server_id, steam_id, role, added_at)
|
||||
|
||||
/// Register a new server connection (RCON credentials).
|
||||
pub async fn create_server_connection(pool: &PgPool, license_id: Uuid, name: &str, host: &str, rcon_port: i32) -> Result<Uuid> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Fetch a server connection by ID.
|
||||
pub async fn get_server_connection(pool: &PgPool, server_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Update server connection details.
|
||||
pub async fn update_server_connection(pool: &PgPool, server_id: Uuid, name: Option<&str>, host: Option<&str>, rcon_port: Option<i32>) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Create the initial server configuration record.
|
||||
pub async fn create_server_config(pool: &PgPool, server_id: Uuid) -> Result<Uuid> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Fetch server configuration.
|
||||
pub async fn get_server_config(pool: &PgPool, server_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Update server configuration fields.
|
||||
pub async fn update_server_config(pool: &PgPool, server_id: Uuid, seed: Option<i32>, world_size: Option<i32>, max_players: Option<i32>) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Get all game admins (moderators/owners) for a server.
|
||||
pub async fn get_game_admins(pool: &PgPool, server_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Add a game admin by Steam ID.
|
||||
pub async fn create_game_admin(pool: &PgPool, server_id: Uuid, steam_id: &str, role: &str) -> Result<Uuid> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Remove a game admin.
|
||||
pub async fn delete_game_admin(pool: &PgPool, admin_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
26
backend/src/db/stats.rs
Normal file
26
backend/src/db/stats.rs
Normal file
@@ -0,0 +1,26 @@
|
||||
use sqlx::PgPool;
|
||||
use uuid::Uuid;
|
||||
use anyhow::Result;
|
||||
|
||||
// TODO: Define ServerStats struct (id, server_id, player_count, fps, memory_usage, entities, timestamp)
|
||||
// TODO: Define HourlyStats struct (id, server_id, hour, avg_players, avg_fps, avg_memory, peak_players)
|
||||
|
||||
/// Insert a raw stats snapshot from the game server.
|
||||
pub async fn insert_server_stats(pool: &PgPool, server_id: Uuid, player_count: i32, fps: f64, memory_usage: i64, entities: i32) -> Result<Uuid> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Get the most recent stats snapshots for a server.
|
||||
pub async fn get_recent_stats(pool: &PgPool, server_id: Uuid, limit: i64) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Get hourly aggregated stats for charting.
|
||||
pub async fn get_hourly_stats(pool: &PgPool, server_id: Uuid, hours: i64) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Roll up raw stats into hourly aggregates (called by a scheduled job).
|
||||
pub async fn aggregate_hourly_stats(pool: &PgPool, server_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
53
backend/src/db/store.rs
Normal file
53
backend/src/db/store.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
use sqlx::PgPool;
|
||||
use uuid::Uuid;
|
||||
use anyhow::Result;
|
||||
|
||||
// TODO: Define WebstoreConfig struct (id, server_id, enabled, currency, stripe_key_encrypted, tebex_secret_encrypted, created_at, updated_at)
|
||||
// TODO: Define Category struct (id, server_id, name, sort_order, created_at)
|
||||
// TODO: Define Item struct (id, category_id, name, description, price, commands, image_url, is_active, created_at)
|
||||
// TODO: Define Transaction struct (id, server_id, steam_id, item_id, amount, currency, status, provider, provider_ref, created_at, completed_at)
|
||||
|
||||
/// Get the webstore configuration for a server.
|
||||
pub async fn get_webstore_config(pool: &PgPool, server_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Insert or update the webstore configuration.
|
||||
pub async fn upsert_webstore_config(pool: &PgPool, server_id: Uuid, enabled: bool, currency: &str) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Get all item categories for a server's webstore.
|
||||
pub async fn get_categories(pool: &PgPool, server_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Create a new item category.
|
||||
pub async fn create_category(pool: &PgPool, server_id: Uuid, name: &str, sort_order: i32) -> Result<Uuid> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Get all items, optionally filtered by category.
|
||||
pub async fn get_items(pool: &PgPool, server_id: Uuid, category_id: Option<Uuid>) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Create a new store item.
|
||||
pub async fn create_item(pool: &PgPool, category_id: Uuid, name: &str, description: &str, price: i64, commands: &str) -> Result<Uuid> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Create a new purchase transaction record.
|
||||
pub async fn create_transaction(pool: &PgPool, server_id: Uuid, steam_id: &str, item_id: Uuid, amount: i64, currency: &str, provider: &str) -> Result<Uuid> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Update transaction status (pending -> completed/failed/refunded).
|
||||
pub async fn update_transaction_status(pool: &PgPool, transaction_id: Uuid, status: &str, provider_ref: Option<&str>) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Get transactions for a server with optional status filter.
|
||||
pub async fn get_transactions(pool: &PgPool, server_id: Uuid, status: Option<&str>, limit: i64, offset: i64) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
46
backend/src/db/teams.rs
Normal file
46
backend/src/db/teams.rs
Normal file
@@ -0,0 +1,46 @@
|
||||
use sqlx::PgPool;
|
||||
use uuid::Uuid;
|
||||
use anyhow::Result;
|
||||
|
||||
// TODO: Define TeamMember struct (id, license_id, user_id, role_id, invited_at, accepted_at)
|
||||
// TODO: Define Role struct (id, license_id, name, permissions jsonb, created_at)
|
||||
|
||||
/// Get all team members for a license.
|
||||
pub async fn get_team_members(pool: &PgPool, license_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Add a user to a license team.
|
||||
pub async fn create_team_member(pool: &PgPool, license_id: Uuid, user_id: Uuid, role_id: Uuid) -> Result<Uuid> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Change a team member's role.
|
||||
pub async fn update_team_member_role(pool: &PgPool, member_id: Uuid, role_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Remove a team member from the license.
|
||||
pub async fn remove_team_member(pool: &PgPool, member_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Get all roles defined for a license.
|
||||
pub async fn get_roles(pool: &PgPool, license_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Create a custom role with a permissions set.
|
||||
pub async fn create_role(pool: &PgPool, license_id: Uuid, name: &str, permissions: &str) -> Result<Uuid> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Update a role's name or permissions.
|
||||
pub async fn update_role(pool: &PgPool, role_id: Uuid, name: Option<&str>, permissions: Option<&str>) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Delete a custom role.
|
||||
pub async fn delete_role(pool: &PgPool, role_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
30
backend/src/db/users.rs
Normal file
30
backend/src/db/users.rs
Normal file
@@ -0,0 +1,30 @@
|
||||
use sqlx::PgPool;
|
||||
use uuid::Uuid;
|
||||
use anyhow::Result;
|
||||
|
||||
// TODO: Define User struct (id, email, password_hash, display_name, avatar_url, created_at, updated_at, last_login_at)
|
||||
|
||||
/// Create a new user record.
|
||||
pub async fn create_user(pool: &PgPool, email: &str, password_hash: &str, display_name: &str) -> Result<Uuid> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Fetch a user by their primary key.
|
||||
pub async fn get_user_by_id(pool: &PgPool, user_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Fetch a user by email address (for login lookups).
|
||||
pub async fn get_user_by_email(pool: &PgPool, email: &str) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Update mutable user profile fields.
|
||||
pub async fn update_user(pool: &PgPool, user_id: Uuid, display_name: Option<&str>, avatar_url: Option<&str>) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Bump the last_login_at timestamp for a user.
|
||||
pub async fn update_last_login(pool: &PgPool, user_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
42
backend/src/db/wipes.rs
Normal file
42
backend/src/db/wipes.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
use sqlx::PgPool;
|
||||
use uuid::Uuid;
|
||||
use anyhow::Result;
|
||||
|
||||
// TODO: Define WipeProfile struct (id, server_id, name, wipe_type, commands, plugin_actions, created_at)
|
||||
// TODO: Define WipeSchedule struct (id, profile_id, cron_expression, next_run_at, enabled)
|
||||
// TODO: Define WipeHistory struct (id, profile_id, started_at, completed_at, status, log)
|
||||
|
||||
/// Create a new wipe profile (template for a wipe operation).
|
||||
pub async fn create_wipe_profile(pool: &PgPool, server_id: Uuid, name: &str, wipe_type: &str) -> Result<Uuid> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Get all wipe profiles for a server.
|
||||
pub async fn get_wipe_profiles(pool: &PgPool, server_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Create a cron-based schedule for a wipe profile.
|
||||
pub async fn create_wipe_schedule(pool: &PgPool, profile_id: Uuid, cron_expression: &str) -> Result<Uuid> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Get all schedules for a wipe profile.
|
||||
pub async fn get_wipe_schedules(pool: &PgPool, profile_id: Uuid) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Record the start of a wipe execution.
|
||||
pub async fn create_wipe_history(pool: &PgPool, profile_id: Uuid) -> Result<Uuid> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Update a wipe history entry with completion status and log output.
|
||||
pub async fn update_wipe_history(pool: &PgPool, history_id: Uuid, status: &str, log: Option<&str>) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Get wipe history for a profile, ordered by most recent first.
|
||||
pub async fn get_wipe_history(pool: &PgPool, profile_id: Uuid, limit: i64) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
Reference in New Issue
Block a user