remove un-needed stuff

This commit is contained in:
Fran Jurmanović
2025-07-06 22:26:23 +02:00
parent 310dcf4556
commit 07407e4db1
4 changed files with 0 additions and 941 deletions

View File

@@ -1,168 +0,0 @@
-- Migration 002: Migrate servers and related tables from integer IDs to UUIDs
-- This migration handles: servers, configs, state_histories, steam_credentials, system_configs
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
-- Step 1: Create new servers table with UUID primary key
CREATE TABLE servers_new (
id TEXT PRIMARY KEY, -- UUID stored as TEXT in SQLite
name TEXT NOT NULL,
ip TEXT NOT NULL,
port INTEGER NOT NULL,
path TEXT NOT NULL, -- Updated from config_path to path to match Go model
service_name TEXT NOT NULL,
date_created DATETIME,
from_steam_cmd BOOLEAN NOT NULL DEFAULT 1 -- Added to match Go model
);
-- Step 2: Generate UUIDs for existing servers and migrate data
INSERT INTO servers_new (id, name, ip, port, path, service_name, from_steam_cmd)
SELECT
LOWER(HEX(RANDOMBLOB(4)) || '-' || HEX(RANDOMBLOB(2)) || '-' || '4' || SUBSTR(HEX(RANDOMBLOB(2)), 2) || '-' ||
SUBSTR('89AB', ABS(RANDOM()) % 4 + 1, 1) || SUBSTR(HEX(RANDOMBLOB(2)), 2) || '-' || HEX(RANDOMBLOB(6))) as id,
name,
COALESCE(ip, '') as ip,
COALESCE(port, 0) as port,
COALESCE(path, '') as path,
service_name,
1 as from_steam_cmd
FROM servers;
-- Step 3: Create mapping table to track old ID to new UUID mapping
CREATE TEMP TABLE server_id_mapping AS
SELECT
s_old.id as old_id,
s_new.id as new_id
FROM servers s_old
JOIN servers_new s_new ON s_old.name = s_new.name AND s_old.service_name = s_new.service_name;
-- Step 4: Drop old servers table and rename new one
DROP TABLE servers;
ALTER TABLE servers_new RENAME TO servers;
-- Step 5: Create new configs table with UUID references
CREATE TABLE configs_new (
id TEXT PRIMARY KEY, -- UUID for configs
server_id TEXT NOT NULL, -- UUID reference to servers (GORM expects snake_case)
config_file TEXT NOT NULL,
old_config TEXT,
new_config TEXT,
changed_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- Step 6: Migrate configs data with UUID references
INSERT INTO configs_new (id, server_id, config_file, old_config, new_config, changed_at)
SELECT
LOWER(HEX(RANDOMBLOB(4)) || '-' || HEX(RANDOMBLOB(2)) || '-' || '4' || SUBSTR(HEX(RANDOMBLOB(2)), 2) || '-' ||
SUBSTR('89AB', ABS(RANDOM()) % 4 + 1, 1) || SUBSTR(HEX(RANDOMBLOB(2)), 2) || '-' || HEX(RANDOMBLOB(6))) as id,
sim.new_id as server_id,
c.config_file,
c.old_config,
c.new_config,
c.changed_at
FROM configs c
JOIN server_id_mapping sim ON c.server_id = sim.old_id;
-- Step 7: Drop old configs table and rename new one
DROP TABLE configs;
ALTER TABLE configs_new RENAME TO configs;
-- Step 8: Create new state_histories table with UUID references
CREATE TABLE state_histories_new (
id TEXT PRIMARY KEY, -- UUID for state_histories records
server_id TEXT NOT NULL, -- UUID reference to servers (GORM expects snake_case)
session TEXT,
track TEXT,
player_count INTEGER,
date_created DATETIME,
session_start DATETIME,
session_duration_minutes INTEGER,
session_id TEXT NOT NULL -- Changed to TEXT to store UUID
);
-- Step 9: Migrate state_histories data with UUID references
INSERT INTO state_histories_new (id, server_id, session, track, player_count, date_created, session_start, session_duration_minutes, session_id)
SELECT
LOWER(HEX(RANDOMBLOB(4)) || '-' || HEX(RANDOMBLOB(2)) || '-' || '4' || SUBSTR(HEX(RANDOMBLOB(2)), 2) || '-' ||
SUBSTR('89AB', ABS(RANDOM()) % 4 + 1, 1) || SUBSTR(HEX(RANDOMBLOB(2)), 2) || '-' || HEX(RANDOMBLOB(6))) as id,
sim.new_id as server_id,
sh.session,
sh.track,
sh.player_count,
sh.date_created,
sh.session_start,
sh.session_duration_minutes,
LOWER(HEX(RANDOMBLOB(4)) || '-' || HEX(RANDOMBLOB(2)) || '-' || '4' || SUBSTR(HEX(RANDOMBLOB(2)), 2) || '-' ||
SUBSTR('89AB', ABS(RANDOM()) % 4 + 1, 1) || SUBSTR(HEX(RANDOMBLOB(2)), 2) || '-' || HEX(RANDOMBLOB(6))) as session_id
FROM state_histories sh
JOIN server_id_mapping sim ON sh.server_id = sim.old_id;
-- Step 10: Drop old state_histories table and rename new one
DROP TABLE state_histories;
ALTER TABLE state_histories_new RENAME TO state_histories;
-- Step 11: Create new steam_credentials table with UUID primary key
CREATE TABLE steam_credentials_new (
id TEXT PRIMARY KEY, -- UUID for steam_credentials
username TEXT NOT NULL,
password TEXT NOT NULL,
date_created DATETIME,
last_updated DATETIME
);
-- Step 12: Migrate steam_credentials data
INSERT INTO steam_credentials_new (id, username, password, date_created, last_updated)
SELECT
LOWER(HEX(RANDOMBLOB(4)) || '-' || HEX(RANDOMBLOB(2)) || '-' || '4' || SUBSTR(HEX(RANDOMBLOB(2)), 2) || '-' ||
SUBSTR('89AB', ABS(RANDOM()) % 4 + 1, 1) || SUBSTR(HEX(RANDOMBLOB(2)), 2) || '-' || HEX(RANDOMBLOB(6))) as id,
username,
password,
date_created,
last_updated
FROM steam_credentials;
-- Step 13: Drop old steam_credentials table and rename new one
DROP TABLE steam_credentials;
ALTER TABLE steam_credentials_new RENAME TO steam_credentials;
-- Step 14: Create new system_configs table with UUID primary key
CREATE TABLE system_configs_new (
id TEXT PRIMARY KEY, -- UUID for system_configs
key TEXT,
value TEXT,
default_value TEXT,
description TEXT,
date_modified TEXT
);
-- Step 15: Migrate system_configs data
INSERT INTO system_configs_new (id, key, value, default_value, description, date_modified)
SELECT
LOWER(HEX(RANDOMBLOB(4)) || '-' || HEX(RANDOMBLOB(2)) || '-' || '4' || SUBSTR(HEX(RANDOMBLOB(2)), 2) || '-' ||
SUBSTR('89AB', ABS(RANDOM()) % 4 + 1, 1) || SUBSTR(HEX(RANDOMBLOB(2)), 2) || '-' || HEX(RANDOMBLOB(6))) as id,
key,
value,
default_value,
description,
date_modified
FROM system_configs;
-- Step 16: Drop old system_configs table and rename new one
DROP TABLE system_configs;
ALTER TABLE system_configs_new RENAME TO system_configs;
-- Step 17: Create migration record
CREATE TABLE IF NOT EXISTS migration_records (
id INTEGER PRIMARY KEY AUTOINCREMENT,
migration_name TEXT UNIQUE NOT NULL,
applied_at TEXT NOT NULL,
success BOOLEAN NOT NULL,
notes TEXT
);
INSERT INTO migration_records (migration_name, applied_at, success, notes)
VALUES ('002_migrate_servers_to_uuid', datetime('now'), 1, 'Migrated servers, configs, state_histories, steam_credentials, and system_configs to UUID primary keys');
COMMIT;
PRAGMA foreign_keys=ON;

View File

@@ -1,148 +0,0 @@
package main
import (
"acc-server-manager/local/migrations"
"acc-server-manager/local/utl/logging"
"fmt"
"log"
"os"
"path/filepath"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
func main() {
// Initialize logging
logging.Init(true) // Enable debug logging
// Get database path from command line args or use default
dbPath := "acc.db"
if len(os.Args) > 1 {
dbPath = os.Args[1]
}
// Make sure we're running from the correct directory
if !fileExists(dbPath) {
// Try to find the database in common locations
possiblePaths := []string{
"acc.db",
"../acc.db",
"../../acc.db",
"cmd/api/acc.db",
"../cmd/api/acc.db",
}
found := false
for _, path := range possiblePaths {
if fileExists(path) {
dbPath = path
found = true
break
}
}
if !found {
log.Fatalf("Database file not found. Please run from the project root or specify the correct path.")
}
}
// Get absolute path for database
absDbPath, err := filepath.Abs(dbPath)
if err != nil {
log.Fatalf("Failed to get absolute path for database: %v", err)
}
logging.Info("Using database: %s", absDbPath)
// Open database connection
db, err := gorm.Open(sqlite.Open(absDbPath), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
})
if err != nil {
log.Fatalf("Failed to connect to database: %v", err)
}
sqlDB, err := db.DB()
if err != nil {
log.Fatalf("Failed to get underlying sql.DB: %v", err)
}
defer sqlDB.Close()
// Run migrations in order
logging.Info("Starting database migrations...")
// Migration 001: Password security upgrade (if it exists and hasn't run)
logging.Info("Checking Migration 001: Password Security Upgrade...")
if err := migrations.RunPasswordSecurityMigration(db); err != nil {
log.Fatalf("Migration 001 failed: %v", err)
}
// Migration 002: UUID migration
logging.Info("Checking Migration 002: UUID Migration...")
if err := migrations.RunUUIDMigration(db); err != nil {
log.Fatalf("Migration 002 failed: %v", err)
}
logging.Info("All migrations completed successfully!")
// Print summary of migration status
printMigrationStatus(db)
}
// fileExists checks if a file exists and is not a directory
func fileExists(filename string) bool {
info, err := os.Stat(filename)
if os.IsNotExist(err) {
return false
}
return !info.IsDir()
}
// printMigrationStatus prints a summary of applied migrations
func printMigrationStatus(db *gorm.DB) {
logging.Info("Migration Status Summary:")
logging.Info("========================")
// Check if migration_records table exists
var tableExists int
err := db.Raw("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='migration_records'").Scan(&tableExists).Error
if err != nil || tableExists == 0 {
logging.Info("No migration tracking table found - this may be a fresh database")
return
}
// Get all migration records
var records []struct {
MigrationName string `gorm:"column:migration_name"`
AppliedAt string `gorm:"column:applied_at"`
Success bool `gorm:"column:success"`
Notes string `gorm:"column:notes"`
}
err = db.Table("migration_records").Find(&records).Error
if err != nil {
logging.Error("Failed to fetch migration records: %v", err)
return
}
if len(records) == 0 {
logging.Info("No migrations have been applied yet")
return
}
for _, record := range records {
status := "✓ SUCCESS"
if !record.Success {
status = "✗ FAILED"
}
logging.Info(" %s - %s (%s)", record.MigrationName, status, record.AppliedAt)
if record.Notes != "" {
logging.Info(" Notes: %s", record.Notes)
}
}
fmt.Printf("\nTotal migrations applied: %d\n", len(records))
}

View File

@@ -1,392 +0,0 @@
package main
import (
"acc-server-manager/local/migrations"
"acc-server-manager/local/model"
"acc-server-manager/local/repository"
"acc-server-manager/local/service"
"acc-server-manager/local/utl/logging"
"context"
"fmt"
"log"
"os"
"github.com/google/uuid"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
func main() {
// Initialize logging
logging.Init(true) // Enable debug logging
// Create a test database
testDbPath := "test_migrations.db"
// Remove existing test database if it exists
if fileExists(testDbPath) {
os.Remove(testDbPath)
}
logging.Info("Creating test database: %s", testDbPath)
// Open database connection
db, err := gorm.Open(sqlite.Open(testDbPath), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
})
if err != nil {
log.Fatalf("Failed to connect to test database: %v", err)
}
sqlDB, err := db.DB()
if err != nil {
log.Fatalf("Failed to get underlying sql.DB: %v", err)
}
defer sqlDB.Close()
// Create initial schema with integer IDs to simulate old database
logging.Info("Creating initial schema with integer IDs...")
createOldSchema(db)
// Insert test data with integer IDs
logging.Info("Inserting test data...")
insertTestData(db)
// Run UUID migration
logging.Info("Running UUID migration...")
if err := migrations.RunUUIDMigration(db); err != nil {
log.Fatalf("UUID migration failed: %v", err)
}
// Verify migration worked
logging.Info("Verifying migration results...")
if err := verifyMigration(db); err != nil {
log.Fatalf("Migration verification failed: %v", err)
}
// Test role system
logging.Info("Testing role system...")
if err := testRoleSystem(db); err != nil {
log.Fatalf("Role system test failed: %v", err)
}
// Test Super Admin deletion prevention
logging.Info("Testing Super Admin deletion prevention...")
if err := testSuperAdminDeletionPrevention(db); err != nil {
log.Fatalf("Super Admin deletion prevention test failed: %v", err)
}
logging.Info("All tests passed successfully!")
// Clean up
os.Remove(testDbPath)
logging.Info("Test database cleaned up")
}
func createOldSchema(db *gorm.DB) {
// Create tables with integer primary keys to simulate old schema
db.Exec(`
CREATE TABLE IF NOT EXISTS servers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
ip TEXT NOT NULL,
port INTEGER NOT NULL,
config_path TEXT NOT NULL,
service_name TEXT NOT NULL,
date_created DATETIME,
from_steam_cmd BOOLEAN NOT NULL DEFAULT 1
)
`)
db.Exec(`
CREATE TABLE IF NOT EXISTS configs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
server_id INTEGER NOT NULL,
config_file TEXT NOT NULL,
old_config TEXT,
new_config TEXT,
changed_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`)
db.Exec(`
CREATE TABLE IF NOT EXISTS state_histories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
server_id INTEGER NOT NULL,
session TEXT,
track TEXT,
player_count INTEGER,
date_created DATETIME,
session_start DATETIME,
session_duration_minutes INTEGER,
session_id INTEGER NOT NULL DEFAULT 0
)
`)
db.Exec(`
CREATE TABLE IF NOT EXISTS steam_credentials (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL,
password TEXT NOT NULL,
date_created DATETIME,
last_updated DATETIME
)
`)
db.Exec(`
CREATE TABLE IF NOT EXISTS system_configs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
key TEXT,
value TEXT,
default_value TEXT,
description TEXT,
date_modified TEXT
)
`)
}
func insertTestData(db *gorm.DB) {
// Insert test server
db.Exec(`
INSERT INTO servers (name, ip, port, config_path, service_name, date_created, from_steam_cmd)
VALUES ('Test Server', '127.0.0.1', 9600, '/test/path', 'TestService', datetime('now'), 1)
`)
// Insert test config
db.Exec(`
INSERT INTO configs (server_id, config_file, old_config, new_config)
VALUES (1, 'test.json', '{"old": true}', '{"new": true}')
`)
// Insert test state history
db.Exec(`
INSERT INTO state_histories (server_id, session, track, player_count, date_created, session_duration_minutes, session_id)
VALUES (1, 'Practice', 'monza', 5, datetime('now'), 60, 1)
`)
// Insert test steam credentials
db.Exec(`
INSERT INTO steam_credentials (username, password, date_created, last_updated)
VALUES ('testuser', 'testpass', datetime('now'), datetime('now'))
`)
// Insert test system config
db.Exec(`
INSERT INTO system_configs (key, value, default_value, description, date_modified)
VALUES ('test_key', 'test_value', 'default_value', 'Test config', datetime('now'))
`)
}
func verifyMigration(db *gorm.DB) error {
// Check that all tables now have UUID primary keys
// Check servers table
var serverID string
err := db.Raw("SELECT id FROM servers LIMIT 1").Scan(&serverID).Error
if err != nil {
return fmt.Errorf("failed to query servers table: %v", err)
}
if _, err := uuid.Parse(serverID); err != nil {
return fmt.Errorf("servers table ID is not a valid UUID: %s", serverID)
}
// Check configs table
var configID, configServerID string
err = db.Raw("SELECT id, server_id FROM configs LIMIT 1").Row().Scan(&configID, &configServerID)
if err != nil {
return fmt.Errorf("failed to query configs table: %v", err)
}
if _, err := uuid.Parse(configID); err != nil {
return fmt.Errorf("configs table ID is not a valid UUID: %s", configID)
}
if _, err := uuid.Parse(configServerID); err != nil {
return fmt.Errorf("configs table server_id is not a valid UUID: %s", configServerID)
}
// Check state_histories table
var stateID, stateServerID string
err = db.Raw("SELECT id, server_id FROM state_histories LIMIT 1").Row().Scan(&stateID, &stateServerID)
if err != nil {
return fmt.Errorf("failed to query state_histories table: %v", err)
}
if _, err := uuid.Parse(stateID); err != nil {
return fmt.Errorf("state_histories table ID is not a valid UUID: %s", stateID)
}
if _, err := uuid.Parse(stateServerID); err != nil {
return fmt.Errorf("state_histories table server_id is not a valid UUID: %s", stateServerID)
}
// Check steam_credentials table
var steamID string
err = db.Raw("SELECT id FROM steam_credentials LIMIT 1").Scan(&steamID).Error
if err != nil {
return fmt.Errorf("failed to query steam_credentials table: %v", err)
}
if _, err := uuid.Parse(steamID); err != nil {
return fmt.Errorf("steam_credentials table ID is not a valid UUID: %s", steamID)
}
// Check system_configs table
var systemID string
err = db.Raw("SELECT id FROM system_configs LIMIT 1").Scan(&systemID).Error
if err != nil {
return fmt.Errorf("failed to query system_configs table: %v", err)
}
if _, err := uuid.Parse(systemID); err != nil {
return fmt.Errorf("system_configs table ID is not a valid UUID: %s", systemID)
}
logging.Info("✓ All tables successfully migrated to UUID primary keys")
return nil
}
func testRoleSystem(db *gorm.DB) error {
// Auto-migrate the models for role system
db.AutoMigrate(&model.Role{}, &model.Permission{}, &model.User{})
// Create repository and service
repo := repository.NewMembershipRepository(db)
service := service.NewMembershipService(repo)
ctx := context.Background()
// Setup initial data (this should create Super Admin, Admin, and Manager roles)
if err := service.SetupInitialData(ctx); err != nil {
return fmt.Errorf("failed to setup initial data: %v", err)
}
// Test that all three roles were created
roles, err := service.GetAllRoles(ctx)
if err != nil {
return fmt.Errorf("failed to get roles: %v", err)
}
expectedRoles := map[string]bool{
"Super Admin": false,
"Admin": false,
"Manager": false,
}
for _, role := range roles {
if _, exists := expectedRoles[role.Name]; exists {
expectedRoles[role.Name] = true
}
}
for roleName, found := range expectedRoles {
if !found {
return fmt.Errorf("role '%s' was not created", roleName)
}
}
// Test permissions for each role
superAdminRole, err := repo.FindRoleByName(ctx, "Super Admin")
if err != nil {
return fmt.Errorf("failed to find Super Admin role: %v", err)
}
adminRole, err := repo.FindRoleByName(ctx, "Admin")
if err != nil {
return fmt.Errorf("failed to find Admin role: %v", err)
}
managerRole, err := repo.FindRoleByName(ctx, "Manager")
if err != nil {
return fmt.Errorf("failed to find Manager role: %v", err)
}
// Load permissions for roles
db.Preload("Permissions").Find(superAdminRole)
db.Preload("Permissions").Find(adminRole)
db.Preload("Permissions").Find(managerRole)
// Super Admin and Admin should have all permissions
allPermissions := model.AllPermissions()
if len(superAdminRole.Permissions) != len(allPermissions) {
return fmt.Errorf("Super Admin should have all %d permissions, but has %d", len(allPermissions), len(superAdminRole.Permissions))
}
if len(adminRole.Permissions) != len(allPermissions) {
return fmt.Errorf("Admin should have all %d permissions, but has %d", len(allPermissions), len(adminRole.Permissions))
}
// Manager should have limited permissions (no create/delete for membership, role, user, server)
expectedManagerPermissions := []string{
model.ServerView,
model.ServerUpdate,
model.ServerStart,
model.ServerStop,
model.ConfigView,
model.ConfigUpdate,
model.UserView,
model.RoleView,
model.MembershipView,
}
if len(managerRole.Permissions) != len(expectedManagerPermissions) {
return fmt.Errorf("Manager should have %d permissions, but has %d", len(expectedManagerPermissions), len(managerRole.Permissions))
}
// Verify Manager doesn't have restricted permissions
restrictedPermissions := []string{
model.ServerCreate,
model.ServerDelete,
model.UserCreate,
model.UserDelete,
model.RoleCreate,
model.RoleDelete,
model.MembershipCreate,
}
for _, restrictedPerm := range restrictedPermissions {
for _, managerPerm := range managerRole.Permissions {
if managerPerm.Name == restrictedPerm {
return fmt.Errorf("Manager should not have permission '%s'", restrictedPerm)
}
}
}
logging.Info("✓ Role system working correctly")
logging.Info(" - Super Admin role: %d permissions", len(superAdminRole.Permissions))
logging.Info(" - Admin role: %d permissions", len(adminRole.Permissions))
logging.Info(" - Manager role: %d permissions", len(managerRole.Permissions))
return nil
}
func testSuperAdminDeletionPrevention(db *gorm.DB) error {
// Create repository and service
repo := repository.NewMembershipRepository(db)
service := service.NewMembershipService(repo)
ctx := context.Background()
// Find the default admin user (should be Super Admin)
adminUser, err := repo.FindUserByUsername(ctx, "admin")
if err != nil {
return fmt.Errorf("failed to find admin user: %v", err)
}
// Try to delete the Super Admin user (should fail)
err = service.DeleteUser(ctx, adminUser.ID)
if err == nil {
return fmt.Errorf("deleting Super Admin user should have failed, but it succeeded")
}
if err.Error() != "cannot delete Super Admin user" {
return fmt.Errorf("expected 'cannot delete Super Admin user' error, got: %v", err)
}
logging.Info("✓ Super Admin deletion prevention working correctly")
return nil
}
// fileExists checks if a file exists and is not a directory
func fileExists(filename string) bool {
info, err := os.Stat(filename)
if os.IsNotExist(err) {
return false
}
return !info.IsDir()
}