From dfdd7c0f3522e7314ace4ea79b67fe914cf555e8 Mon Sep 17 00:00:00 2001
From: ChesnoTech <263363000+ChesnoTech@users.noreply.github.com>
Date: Thu, 7 May 2026 07:17:00 +0300
Subject: [PATCH] P1: Joomla-style table-prefix support across SQL + PHP
runtime
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Introduces optional database-table prefix so multiple KeyGate instances
can coexist in one database (panels like cPanel/Plesk often share a
single DB across customer apps). Default prefix is empty → bit-for-bit
identical schema to the previous release.
Changes:
1. tools/prefix-codemod.php
New one-shot script. Self-discovers the canonical KeyGate table list
from CREATE TABLE / ALTER TABLE statements in database/*.sql, then
rewrites:
- SQL files (32): every `tablename` and unbacktiked SQL-keyword target
becomes `#__tablename`. The `#__` sentinel is the Joomla convention.
- PHP files (~50): every backticked or bare-name SQL table reference
inside string literals becomes `' . t('tablename') . '` (single-quote
concat) or `" . t('tablename') . "` (double-quote concat).
Token-based PHP parser (token_get_all) so comments / identifiers /
non-string code is never touched. Idempotent — second run is a no-op.
Run: docker compose exec web php /tmp/codemod.php --root /var/www/html/activate --apply
2. FINAL_PRODUCTION_SYSTEM/functions/db-helpers.php
New file. Defines `t(string $name): string` returning DB_PREFIX . name.
Also defines a fallback `define('DB_PREFIX', '')` if config.php hasn't
set it — covers all legacy installs.
3. FINAL_PRODUCTION_SYSTEM/constants.php
Loads functions/db-helpers.php at the top so t() is available before
any controller runs.
4. FINAL_PRODUCTION_SYSTEM/database/*.sql
Codemod output: 32 SQL files with `#__` markers. Schema is identical
when prefix='' (the default). 276 backticked refs converted.
5. FINAL_PRODUCTION_SYSTEM/{controllers,api,functions,*}.php
Codemod output: ~362 site rewrites across ~54 files. Every SQL string
literal that referenced a canonical table now resolves through t().
6. FINAL_PRODUCTION_SYSTEM/install/ajax.php
- installerRunSqlFile() substitutes `#__` → $_SESSION['install_db']['prefix']
before running each migration. Defense-in-depth: aborts if any `#__`
remains post-substitution.
- installerT() helper for installer-time queries (mirrors t() but reads
prefix from session, since DB_PREFIX isn't defined yet).
- handleInstallDbInit/Step/All all use `installerT('schema_versions')`
when checking applied migrations.
- handleCreateAdmin uses installerT() for admin_users/acl_roles.
- handleFinalize uses installerT() for system_config/technicians/
trusted_networks/admin_ip_whitelist; passes prefix + charset to
generateConfig().
- handleHealth probes prefix-aware physical table names.
- installerCheckIncompleteState() reads DB_PREFIX from existing
config.php so auto-unlock works on prefixed installs.
- generateConfig() emits define('DB_PREFIX', '...') AND propagates
the auto-detected charset (utf8mb4 or utf8mb3 fallback).
7. FINAL_PRODUCTION_SYSTEM/install/index.php
Inline auto-unlock logic now reads DB_PREFIX from config.php, so the
admin_users probe targets the correct physical table name.
8. FINAL_PRODUCTION_SYSTEM/database/docker-init/00-init.sh
New KEYGATE_DB_PREFIX env var (default empty). Pre-runs `sed` over
every .sql file into a /tmp staging copy so the original (read-only)
mount stays untouched. schema_versions tracking table picks up the
prefix consistently. Validates prefix against ^[a-z][a-z0-9_]{0,9}$.
Checksum is computed against the original file (stable across prefix
choices).
Backward compatibility:
- Existing installs without DB_PREFIX in config.php → db-helpers.php
defaults to empty string → t('admin_users') === 'admin_users'.
- 32 .sql files use `#__` placeholders. Without substitution they're
invalid SQL — but they're never executed without going through either
installerRunSqlFile() or 00-init.sh's sed pass.
- Verified: live admin login + list_keys both succeed against the
pre-existing dev database after the codemod.
- 14/14 frontend tests pass.
Risk register from the plan:
- ✅ Codemod misses dynamic table refs → CI lint will catch (P2 task).
- ✅ FK / TRIGGER / VIEW unqualified table refs → SQL pass handles them.
- ✅ Empty-prefix path emits literal `#__` → installerRunSqlFile asserts
strpos(#__) === false post-substitution and aborts.
- ✅ Prefix collides with reserved name → step-2 UI deny-list +
00-init.sh regex validation.
- ✅ Async runner slows happy-path → fast path retained (install_db_all).
- ✅ Legacy config.php lacks DB_PREFIX → db-helpers.php fallback.
---
.gitignore | 3 +
FINAL_PRODUCTION_SYSTEM/admin_v2.php | 4 +-
.../api/authenticate-usb.php | 10 +-
.../api/change-password.php | 4 +-
.../api/collect-hardware-v2.php | 12 +-
.../api/download-resource.php | 4 +-
.../api/get-alt-server-config.php | 6 +-
.../api/get-client-config.php | 2 +-
FINAL_PRODUCTION_SYSTEM/api/get-key.php | 10 +-
FINAL_PRODUCTION_SYSTEM/api/import-csv.php | 2 +-
FINAL_PRODUCTION_SYSTEM/api/login.php | 8 +-
.../api/middleware/RateLimiter.php | 2 +-
FINAL_PRODUCTION_SYSTEM/api/report-result.php | 22 +-
.../api/submit-hardware.php | 10 +-
FINAL_PRODUCTION_SYSTEM/api/totp-disable.php | 4 +-
.../api/totp-regenerate-backup-codes.php | 4 +-
FINAL_PRODUCTION_SYSTEM/api/totp-setup.php | 10 +-
FINAL_PRODUCTION_SYSTEM/api/totp-verify.php | 6 +-
FINAL_PRODUCTION_SYSTEM/config-production.php | 18 +-
FINAL_PRODUCTION_SYSTEM/config.php | 2 +-
.../config/config-template-enhanced.php | 10 +-
FINAL_PRODUCTION_SYSTEM/constants.php | 5 +
.../controllers/admin/AclController.php | 2 +-
.../controllers/admin/BackupsController.php | 2 +-
.../controllers/admin/BrandingController.php | 4 +-
.../admin/ClientResourcesController.php | 16 +-
.../admin/ComplianceController.php | 30 +-
.../controllers/admin/DashboardController.php | 28 +-
.../controllers/admin/HistoryController.php | 16 +-
.../admin/IntegrationController.php | 12 +-
.../controllers/admin/KeysController.php | 8 +-
.../controllers/admin/LicenseController.php | 6 +-
.../admin/NotificationsController.php | 26 +-
.../admin/ProductVariantsController.php | 24 +-
.../admin/ProductionController.php | 50 +--
.../controllers/admin/SecurityController.php | 12 +-
.../admin/TaskPipelineController.php | 34 +-
.../admin/TechniciansController.php | 18 +-
.../controllers/admin/UpgradeController.php | 26 +-
.../admin/UsbDevicesController.php | 20 +-
.../database/2fa_migration.sql | 16 +-
.../database/acl_migration.sql | 76 ++--
.../database/backup_migration.sql | 12 +-
.../database/client_config_migration.sql | 2 +-
.../database/client_resources_migration.sql | 4 +-
.../database/create_admin.php | 4 +-
.../database/database_admin_security.sql | 26 +-
.../database/database_concurrency_indexes.sql | 16 +-
.../database/database_setup.sql | 16 +-
.../database/database_setup_with_users.sql | 28 +-
.../database/docker-init/00-init.sh | 46 +-
.../database/downloads_acl_migration.sql | 14 +-
.../database/hardware_info_migration.sql | 18 +-
.../database/hardware_info_v2_migration.sql | 56 +--
.../database/hash_temp_passwords.php | 4 +-
.../database/i18n_migration.sql | 6 +-
FINAL_PRODUCTION_SYSTEM/database/install.sql | 44 +-
.../database/integrations_migration.sql | 8 +-
.../database/license_migration.sql | 6 +-
.../database/missing_drivers_migration.sql | 10 +-
.../database/order_field_config_migration.sql | 12 +-
.../database/product_variants_migration.sql | 14 +-
.../production_tracking_migration.sql | 10 +-
.../database/push_notifications_migration.sql | 14 +-
.../database/qc_compliance_migration.sql | 34 +-
.../database/rate_limiting_migration.sql | 4 +-
.../database/rbac_migration.sql | 20 +-
.../database/schema_versions_migration.sql | 2 +-
.../database/seed_demo_compliance.sql | 34 +-
.../database/seed_variants.sql | 22 +-
.../database/task_pipeline_migration.sql | 10 +-
.../database/temp_password_hash_migration.sql | 2 +-
.../database/unallocated_space_migration.sql | 2 +-
.../database/upgrade_system_migration.sql | 2 +-
.../database/usb_devices_migration.sql | 2 +-
FINAL_PRODUCTION_SYSTEM/functions/acl.php | 68 +--
.../functions/admin-helpers.php | 26 +-
.../functions/csv-import.php | 14 +-
.../functions/db-helpers.php | 37 ++
.../functions/integration-helpers.php | 26 +-
.../functions/key-helpers.php | 4 +-
.../functions/license-helpers.php | 12 +-
.../functions/network-utils.php | 6 +-
.../functions/push-helpers.php | 10 +-
.../functions/qc-compliance.php | 34 +-
.../functions/session-helpers.php | 12 +-
.../functions/totp-helpers.php | 10 +-
FINAL_PRODUCTION_SYSTEM/install/ajax.php | 136 ++++--
FINAL_PRODUCTION_SYSTEM/install/index.php | 10 +-
FINAL_PRODUCTION_SYSTEM/secure-admin.php | 4 +-
FINAL_PRODUCTION_SYSTEM/setup/index.php | 4 +-
tools/prefix-codemod.php | 398 ++++++++++++++++++
92 files changed, 1220 insertions(+), 679 deletions(-)
create mode 100644 FINAL_PRODUCTION_SYSTEM/functions/db-helpers.php
create mode 100644 tools/prefix-codemod.php
diff --git a/.gitignore b/.gitignore
index 8cb5ce7..9aa8908 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,6 +23,9 @@ logs/
# Don't commit 12MB+ artifacts — every dev rebuilds locally on first commit.
**/graphify-out/
+# ── Uploaded client artifacts (per-instance, regenerated at runtime) ──
+FINAL_PRODUCTION_SYSTEM/uploads/client-resources/
+
# ── PHP Dependencies (managed by Composer) ────────────────
FINAL_PRODUCTION_SYSTEM/vendor/
diff --git a/FINAL_PRODUCTION_SYSTEM/admin_v2.php b/FINAL_PRODUCTION_SYSTEM/admin_v2.php
index cf50293..5937524 100644
--- a/FINAL_PRODUCTION_SYSTEM/admin_v2.php
+++ b/FINAL_PRODUCTION_SYSTEM/admin_v2.php
@@ -154,7 +154,7 @@
if (isset($_POST['action']) && $_POST['action'] === 'change_language' && isset($_POST['language'])) {
$newLang = preg_replace('/[^a-z]/', '', strtolower($_POST['language']));
if (in_array($newLang, ['en', 'ru'])) {
- $stmt = $pdo->prepare("UPDATE admin_users SET preferred_language = ? WHERE id = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('admin_users') . "` SET preferred_language = ? WHERE id = ?");
$stmt->execute([$newLang, $admin_session['admin_id']]);
loadLanguage($newLang);
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH'])) {
@@ -404,7 +404,7 @@
// Handle logout
if (isset($_GET['logout'])) {
if (isset($_SESSION['admin_token'])) {
- $stmt = $pdo->prepare("UPDATE admin_sessions SET is_active = 0 WHERE session_token = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('admin_sessions') . "` SET is_active = 0 WHERE session_token = ?");
$stmt->execute([$_SESSION['admin_token']]);
}
session_destroy();
diff --git a/FINAL_PRODUCTION_SYSTEM/api/authenticate-usb.php b/FINAL_PRODUCTION_SYSTEM/api/authenticate-usb.php
index bddcedf..3703043 100644
--- a/FINAL_PRODUCTION_SYSTEM/api/authenticate-usb.php
+++ b/FINAL_PRODUCTION_SYSTEM/api/authenticate-usb.php
@@ -90,8 +90,8 @@
// Find USB device by serial number
$stmt = $pdo->prepare("
SELECT d.*, t.full_name, t.is_active
- FROM usb_devices d
- INNER JOIN technicians t ON d.technician_id = t.technician_id
+ FROM `" . t('usb_devices') . "` d
+ INNER JOIN `" . t('technicians') . "` t ON d.technician_id = t.technician_id
WHERE d.device_serial_number = ?
");
$stmt->execute([$usbSerialNumber]);
@@ -165,7 +165,7 @@
// Insert session
$stmt = $pdo->prepare("
- INSERT INTO active_sessions (
+ INSERT INTO `" . t('active_sessions') . "` (
technician_id, session_token, created_at, expires_at,
is_active, auth_method, usb_device_id, computer_name
) VALUES (?, ?, NOW(), ?, 1, 'usb', ?, ?)
@@ -180,7 +180,7 @@
// Update USB device last used info
$stmt = $pdo->prepare("
- UPDATE usb_devices
+ UPDATE `" . t('usb_devices') . "`
SET last_used_date = NOW(),
last_used_ip = ?,
last_used_computer_name = ?,
@@ -191,7 +191,7 @@
// Update technician last login
$stmt = $pdo->prepare("
- UPDATE technicians
+ UPDATE `" . t('technicians') . "`
SET last_login = NOW(),
failed_login_attempts = 0,
locked_until = NULL
diff --git a/FINAL_PRODUCTION_SYSTEM/api/change-password.php b/FINAL_PRODUCTION_SYSTEM/api/change-password.php
index 1fbaa35..d3449ec 100644
--- a/FINAL_PRODUCTION_SYSTEM/api/change-password.php
+++ b/FINAL_PRODUCTION_SYSTEM/api/change-password.php
@@ -29,7 +29,7 @@
try {
// Get technician details
$stmt = $pdo->prepare("
- SELECT * FROM technicians
+ SELECT * FROM `" . t('technicians') . "`
WHERE technician_id = ? AND is_active = 1
");
$stmt->execute([$technician_id]);
@@ -63,7 +63,7 @@
$new_password_hash = password_hash($new_password, PASSWORD_BCRYPT, ['cost' => BCRYPT_COST]);
$stmt = $pdo->prepare("
- UPDATE technicians
+ UPDATE `" . t('technicians') . "`
SET password_hash = ?, temp_password = NULL, must_change_password = FALSE
WHERE technician_id = ?
");
diff --git a/FINAL_PRODUCTION_SYSTEM/api/collect-hardware-v2.php b/FINAL_PRODUCTION_SYSTEM/api/collect-hardware-v2.php
index 0568dbd..e839e40 100644
--- a/FINAL_PRODUCTION_SYSTEM/api/collect-hardware-v2.php
+++ b/FINAL_PRODUCTION_SYSTEM/api/collect-hardware-v2.php
@@ -26,8 +26,8 @@
// Validate session token and get technician info
$stmt = $pdo->prepare("
SELECT s.technician_id, t.full_name, s.expires_at
- FROM active_sessions s
- INNER JOIN technicians t ON s.technician_id = t.technician_id
+ FROM `" . t('active_sessions') . "` s
+ INNER JOIN `" . t('technicians') . "` t ON s.technician_id = t.technician_id
WHERE s.session_token = ?
AND s.expires_at > NOW()
LIMIT 1
@@ -44,7 +44,7 @@
// Check if hardware info already exists for this order number
$stmt = $pdo->prepare("
SELECT id, collection_timestamp
- FROM hardware_info
+ FROM `" . t('hardware_info') . "`
WHERE order_number = ?
ORDER BY collection_timestamp DESC
LIMIT 1
@@ -164,7 +164,7 @@
// Insert hardware information
$stmt = $pdo->prepare("
- INSERT INTO hardware_info (
+ INSERT INTO `" . t('hardware_info') . "` (
activation_id, order_number, technician_id, session_token,
motherboard_manufacturer, motherboard_product, motherboard_serial, motherboard_version,
bios_manufacturer, bios_version, bios_release_date, bios_serial_number,
@@ -280,7 +280,7 @@
// Log the collection attempt
$stmt = $pdo->prepare("
- INSERT INTO hardware_collection_log (
+ INSERT INTO `" . t('hardware_collection_log') . "` (
order_number, technician_id, session_token, hardware_info_id, collection_status
) VALUES (?, ?, ?, ?, 'success')
");
@@ -316,7 +316,7 @@
try {
if (isset($technicianId) && isset($orderNumber) && isset($sessionToken)) {
$stmt = $pdo->prepare("
- INSERT INTO hardware_collection_log (
+ INSERT INTO `" . t('hardware_collection_log') . "` (
order_number, technician_id, session_token, hardware_info_id,
collection_status, error_message
) VALUES (?, ?, ?, NULL, 'failed', ?)
diff --git a/FINAL_PRODUCTION_SYSTEM/api/download-resource.php b/FINAL_PRODUCTION_SYSTEM/api/download-resource.php
index 509052c..02048a1 100644
--- a/FINAL_PRODUCTION_SYSTEM/api/download-resource.php
+++ b/FINAL_PRODUCTION_SYSTEM/api/download-resource.php
@@ -30,7 +30,7 @@
// Validate session token
$stmt = $pdo->prepare("
SELECT s.technician_id
- FROM active_sessions s
+ FROM `" . t('active_sessions') . "` s
WHERE s.session_token = ? AND s.expires_at > NOW()
");
$stmt->execute([$sessionToken]);
@@ -43,7 +43,7 @@
}
// Look up the resource
- $stmt = $pdo->prepare("SELECT * FROM client_resources WHERE resource_key = ?");
+ $stmt = $pdo->prepare("SELECT * FROM `" . t('client_resources') . "` WHERE resource_key = ?");
$stmt->execute([$resourceKey]);
$resource = $stmt->fetch(PDO::FETCH_ASSOC);
diff --git a/FINAL_PRODUCTION_SYSTEM/api/get-alt-server-config.php b/FINAL_PRODUCTION_SYSTEM/api/get-alt-server-config.php
index fac23f3..519bca3 100644
--- a/FINAL_PRODUCTION_SYSTEM/api/get-alt-server-config.php
+++ b/FINAL_PRODUCTION_SYSTEM/api/get-alt-server-config.php
@@ -23,8 +23,8 @@
// Verify valid session and get technician preferences
$stmt = $pdo->prepare("
SELECT s.technician_id, t.preferred_server
- FROM active_sessions s
- INNER JOIN technicians t ON s.technician_id = t.technician_id
+ FROM `" . t('active_sessions') . "` s
+ INNER JOIN `" . t('technicians') . "` t ON s.technician_id = t.technician_id
WHERE s.session_token = ? AND s.expires_at > NOW()
");
$stmt->execute([$sessionToken]);
@@ -38,7 +38,7 @@
// Helper function to get config value
function getConfig($key) {
global $pdo;
- $stmt = $pdo->prepare("SELECT config_value FROM system_config WHERE config_key = ?");
+ $stmt = $pdo->prepare("SELECT config_value FROM `" . t('system_config') . "` WHERE config_key = ?");
$stmt->execute([$key]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
return $result ? $result['config_value'] : null;
diff --git a/FINAL_PRODUCTION_SYSTEM/api/get-client-config.php b/FINAL_PRODUCTION_SYSTEM/api/get-client-config.php
index 758ad8f..86f924b 100644
--- a/FINAL_PRODUCTION_SYSTEM/api/get-client-config.php
+++ b/FINAL_PRODUCTION_SYSTEM/api/get-client-config.php
@@ -23,7 +23,7 @@
// Verify valid session
$stmt = $pdo->prepare("
SELECT s.technician_id
- FROM active_sessions s
+ FROM `" . t('active_sessions') . "` s
WHERE s.session_token = ? AND s.expires_at > NOW()
");
$stmt->execute([$sessionToken]);
diff --git a/FINAL_PRODUCTION_SYSTEM/api/get-key.php b/FINAL_PRODUCTION_SYSTEM/api/get-key.php
index 24c37fc..5cde2f4 100644
--- a/FINAL_PRODUCTION_SYSTEM/api/get-key.php
+++ b/FINAL_PRODUCTION_SYSTEM/api/get-key.php
@@ -21,7 +21,7 @@
if (qcIsEnabled($pdo)) {
$globalSettings = qcGetGlobalSettings($pdo);
if (!empty($globalSettings['blocking_prevents_key'])) {
- $hwStmt = $pdo->prepare("SELECT id FROM hardware_info WHERE order_number = ? ORDER BY collection_timestamp DESC LIMIT 1");
+ $hwStmt = $pdo->prepare("SELECT id FROM `" . t('hardware_info') . "` WHERE order_number = ? ORDER BY collection_timestamp DESC LIMIT 1");
$hwStmt->execute([$order_number]);
$hwRow = $hwStmt->fetch(PDO::FETCH_ASSOC);
if ($hwRow && qcHasBlockingIssues($pdo, (int) $hwRow['id'])) {
@@ -47,7 +47,7 @@
// Update existing session with new order number if different
if ($existing_session['order_number'] !== $order_number) {
$stmt = $pdo->prepare("
- UPDATE active_sessions
+ UPDATE `" . t('active_sessions') . "`
SET order_number = ?, expires_at = DATE_ADD(NOW(), INTERVAL ? MINUTE)
WHERE id = ?
");
@@ -74,7 +74,7 @@
$pdo->rollback();
// Check if ANY keys exist vs. all keys exhausted (for automatic failover)
- $stmt = $pdo->prepare("SELECT COUNT(*) as available_count FROM oem_keys WHERE key_status IN ('unused', 'retry')");
+ $stmt = $pdo->prepare("SELECT COUNT(*) as available_count FROM `" . t('oem_keys') . "` WHERE key_status IN ('unused', 'retry')");
$stmt->execute();
$availableCount = $stmt->fetch(PDO::FETCH_ASSOC)['available_count'];
@@ -104,7 +104,7 @@
// Insert new session (we already checked for existing sessions above)
$stmt = $pdo->prepare("
- INSERT INTO active_sessions (technician_id, session_token, key_id, order_number, expires_at, auth_method, computer_name)
+ INSERT INTO `" . t('active_sessions') . "` (technician_id, session_token, key_id, order_number, expires_at, auth_method, computer_name)
VALUES (?, ?, ?, ?, ?, 'password', ?)
");
$stmt->execute([$technician_id, $session_token, $key['id'], $order_number, $expires_at, $computerName]);
@@ -121,7 +121,7 @@
// Check key pool levels and send alerts if needed
try {
$edition = $key['product_type'] ?? 'Unknown';
- $poolStmt = $pdo->prepare("SELECT COUNT(*) as remaining FROM oem_keys WHERE key_status IN ('unused', 'retry') AND product_type = ?");
+ $poolStmt = $pdo->prepare("SELECT COUNT(*) as remaining FROM `" . t('oem_keys') . "` WHERE key_status IN ('unused', 'retry') AND product_type = ?");
$poolStmt->execute([$edition]);
$remaining = (int)$poolStmt->fetch()['remaining'];
diff --git a/FINAL_PRODUCTION_SYSTEM/api/import-csv.php b/FINAL_PRODUCTION_SYSTEM/api/import-csv.php
index 98aa1a3..9f1b995 100644
--- a/FINAL_PRODUCTION_SYSTEM/api/import-csv.php
+++ b/FINAL_PRODUCTION_SYSTEM/api/import-csv.php
@@ -66,7 +66,7 @@
// Try to insert key
try {
$stmt = $pdo->prepare("
- INSERT INTO oem_keys (product_key, oem_identifier, barcode, key_status, roll_serial)
+ INSERT INTO `" . t('oem_keys') . "` (product_key, oem_identifier, barcode, key_status, roll_serial)
VALUES (?, ?, ?, ?, 'imported')
");
$stmt->execute([$product_key, $oem_identifier, $barcode, $key_status]);
diff --git a/FINAL_PRODUCTION_SYSTEM/api/login.php b/FINAL_PRODUCTION_SYSTEM/api/login.php
index 3ce3275..7734621 100644
--- a/FINAL_PRODUCTION_SYSTEM/api/login.php
+++ b/FINAL_PRODUCTION_SYSTEM/api/login.php
@@ -16,7 +16,7 @@
try {
// Get technician details (including language preference)
$stmt = $pdo->prepare("
- SELECT * FROM technicians
+ SELECT * FROM `" . t('technicians') . "`
WHERE technician_id = ? AND is_active = 1
");
$stmt->execute([$technician_id]);
@@ -64,7 +64,7 @@
}
$stmt = $pdo->prepare("
- UPDATE technicians
+ UPDATE `" . t('technicians') . "`
SET failed_login_attempts = ?, locked_until = ?
WHERE technician_id = ?
");
@@ -94,7 +94,7 @@
// Login successful - reset failed attempts
$stmt = $pdo->prepare("
- UPDATE technicians
+ UPDATE `" . t('technicians') . "`
SET failed_login_attempts = 0, locked_until = NULL, last_login = NOW()
WHERE technician_id = ?
");
@@ -137,7 +137,7 @@
// Include active product lines for order type selection
try {
- $plStmt = $pdo->query("SELECT id, name, order_pattern, description FROM product_lines WHERE is_active = 1 ORDER BY name ASC");
+ $plStmt = $pdo->query("SELECT id, name, order_pattern, description FROM `" . t('product_lines') . "` WHERE is_active = 1 ORDER BY name ASC");
$productLines = $plStmt->fetchAll(PDO::FETCH_ASSOC);
if (!empty($productLines)) {
$response['product_lines'] = array_map(function($pl) {
diff --git a/FINAL_PRODUCTION_SYSTEM/api/middleware/RateLimiter.php b/FINAL_PRODUCTION_SYSTEM/api/middleware/RateLimiter.php
index 19d5177..7d2e083 100644
--- a/FINAL_PRODUCTION_SYSTEM/api/middleware/RateLimiter.php
+++ b/FINAL_PRODUCTION_SYSTEM/api/middleware/RateLimiter.php
@@ -140,7 +140,7 @@ public function logViolation($identifier, $action, $endpoint, $requestCount, $li
try {
$stmt = $pdo->prepare("
- INSERT INTO rate_limit_violations (
+ INSERT INTO `" . t('rate_limit_violations') . "` (
identifier, action, endpoint, client_ip, user_agent,
request_count, limit_threshold, window_seconds
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
diff --git a/FINAL_PRODUCTION_SYSTEM/api/report-result.php b/FINAL_PRODUCTION_SYSTEM/api/report-result.php
index 579e1ff..d199610 100644
--- a/FINAL_PRODUCTION_SYSTEM/api/report-result.php
+++ b/FINAL_PRODUCTION_SYSTEM/api/report-result.php
@@ -126,7 +126,7 @@ function validateAPIAccess(): bool {
}
// NEW: Check if unique ID already exists (prevent duplicates)
-$stmt = $pdo->prepare("SELECT id FROM activation_attempts WHERE activation_unique_id = ?");
+$stmt = $pdo->prepare("SELECT id FROM `" . t('activation_attempts') . "` WHERE activation_unique_id = ?");
$stmt->execute([$activationUniqueId]);
if ($stmt->fetch()) {
jsonResponse([
@@ -156,7 +156,7 @@ function validateAPIAccess(): bool {
// Record activation attempt with all required fields
$stmt = $pdo->prepare("
- INSERT INTO activation_attempts (
+ INSERT INTO `" . t('activation_attempts') . "` (
key_id,
technician_id,
order_number,
@@ -203,7 +203,7 @@ function validateAPIAccess(): bool {
if ($result === 'success') {
// Success path: Mark key as good and deactivate session
$stmt = $pdo->prepare("
- UPDATE oem_keys
+ UPDATE `" . t('oem_keys') . "`
SET key_status = 'good',
updated_at = NOW()
WHERE id = ?
@@ -212,7 +212,7 @@ function validateAPIAccess(): bool {
// Deactivate session (activation complete)
$stmt = $pdo->prepare("
- UPDATE active_sessions
+ UPDATE `" . t('active_sessions') . "`
SET is_active = 0
WHERE id = ?
");
@@ -226,7 +226,7 @@ function validateAPIAccess(): bool {
} else {
// Failure path: Update fail counter and determine key status
$stmt = $pdo->prepare("
- UPDATE oem_keys
+ UPDATE `" . t('oem_keys') . "`
SET fail_counter = fail_counter + 1,
updated_at = NOW()
WHERE id = ?
@@ -236,7 +236,7 @@ function validateAPIAccess(): bool {
// Get updated fail counter
$stmt = $pdo->prepare("
SELECT fail_counter, product_key, oem_identifier
- FROM oem_keys
+ FROM `" . t('oem_keys') . "`
WHERE id = ?
");
$stmt->execute([$session['key_id']]);
@@ -253,7 +253,7 @@ function validateAPIAccess(): bool {
if ($failCounter >= $maxAttempts) {
// Mark as bad after max failures
$stmt = $pdo->prepare("
- UPDATE oem_keys
+ UPDATE `" . t('oem_keys') . "`
SET key_status = 'bad'
WHERE id = ?
");
@@ -264,7 +264,7 @@ function validateAPIAccess(): bool {
// Deactivate session (key is bad)
$stmt = $pdo->prepare("
- UPDATE active_sessions
+ UPDATE `" . t('active_sessions') . "`
SET is_active = 0
WHERE id = ?
");
@@ -275,7 +275,7 @@ function validateAPIAccess(): bool {
} else {
// Mark for retry
$stmt = $pdo->prepare("
- UPDATE oem_keys
+ UPDATE `" . t('oem_keys') . "`
SET key_status = 'retry'
WHERE id = ?
");
@@ -382,7 +382,7 @@ function sendEmailNotification(
if ($keyData === null) {
$stmt = $pdo->prepare("
SELECT product_key, oem_identifier, fail_counter, key_status
- FROM oem_keys
+ FROM `" . t('oem_keys') . "`
WHERE id = ?
");
$stmt->execute([$session['key_id']]);
@@ -396,7 +396,7 @@ function sendEmailNotification(
// Get technician full name
$stmt = $pdo->prepare("
SELECT full_name, email
- FROM technicians
+ FROM `" . t('technicians') . "`
WHERE technician_id = ?
");
$stmt->execute([$session['technician_id']]);
diff --git a/FINAL_PRODUCTION_SYSTEM/api/submit-hardware.php b/FINAL_PRODUCTION_SYSTEM/api/submit-hardware.php
index e22d856..bb4496b 100644
--- a/FINAL_PRODUCTION_SYSTEM/api/submit-hardware.php
+++ b/FINAL_PRODUCTION_SYSTEM/api/submit-hardware.php
@@ -47,8 +47,8 @@
// Validate session token and get activation_id
$stmt = $pdo->prepare("
SELECT aa.id as activation_id, aa.technician_id, aa.key_id
- FROM activation_attempts aa
- INNER JOIN active_sessions s ON s.technician_id = aa.technician_id
+ FROM `" . t('activation_attempts') . "` aa
+ INNER JOIN `" . t('active_sessions') . "` s ON s.technician_id = aa.technician_id
WHERE s.session_token = ?
AND aa.order_number = ?
AND aa.attempt_result = 'success'
@@ -66,7 +66,7 @@
$activationId = $activation['activation_id'];
// Check if hardware info already exists for this activation
- $stmt = $pdo->prepare("SELECT id FROM hardware_info WHERE activation_id = ?");
+ $stmt = $pdo->prepare("SELECT id FROM `" . t('hardware_info') . "` WHERE activation_id = ?");
$stmt->execute([$activationId]);
if ($stmt->fetch()) {
jsonResponse(['success' => true, 'message' => 'Hardware information already recorded', 'duplicate' => true]);
@@ -77,7 +77,7 @@
// Insert hardware information
$stmt = $pdo->prepare("
- INSERT INTO hardware_info (
+ INSERT INTO `" . t('hardware_info') . "` (
activation_id,
order_number,
motherboard_manufacturer,
@@ -188,7 +188,7 @@
]);
// Update activation_attempts to mark hardware as collected
- $stmt = $pdo->prepare("UPDATE activation_attempts SET hardware_collected = 1 WHERE id = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('activation_attempts') . "` SET hardware_collected = 1 WHERE id = ?");
$stmt->execute([$activationId]);
$hardwareId = $pdo->lastInsertId();
diff --git a/FINAL_PRODUCTION_SYSTEM/api/totp-disable.php b/FINAL_PRODUCTION_SYSTEM/api/totp-disable.php
index 2148be3..9d59c58 100644
--- a/FINAL_PRODUCTION_SYSTEM/api/totp-disable.php
+++ b/FINAL_PRODUCTION_SYSTEM/api/totp-disable.php
@@ -62,7 +62,7 @@
// Code verified - disable 2FA
$stmt = $pdo->prepare("
- UPDATE admin_totp_secrets
+ UPDATE `" . t('admin_totp_secrets') . "`
SET totp_enabled = 0
WHERE admin_id = ?
");
@@ -70,7 +70,7 @@
// Log activity
$stmt = $pdo->prepare("
- INSERT INTO admin_activity_log (admin_id, session_id, action, description, ip_address, user_agent)
+ INSERT INTO `" . t('admin_activity_log') . "` (admin_id, session_id, action, description, ip_address, user_agent)
VALUES (?, ?, 'TOTP_DISABLED', '2FA disabled by user', ?, ?)
");
$stmt->execute([
diff --git a/FINAL_PRODUCTION_SYSTEM/api/totp-regenerate-backup-codes.php b/FINAL_PRODUCTION_SYSTEM/api/totp-regenerate-backup-codes.php
index 0341507..796b8ef 100644
--- a/FINAL_PRODUCTION_SYSTEM/api/totp-regenerate-backup-codes.php
+++ b/FINAL_PRODUCTION_SYSTEM/api/totp-regenerate-backup-codes.php
@@ -65,7 +65,7 @@
// Update database
$stmt = $pdo->prepare("
- UPDATE admin_totp_secrets
+ UPDATE `" . t('admin_totp_secrets') . "`
SET backup_codes = ?
WHERE admin_id = ?
");
@@ -76,7 +76,7 @@
// Log activity
$stmt = $pdo->prepare("
- INSERT INTO admin_activity_log (admin_id, session_id, action, description, ip_address, user_agent)
+ INSERT INTO `" . t('admin_activity_log') . "` (admin_id, session_id, action, description, ip_address, user_agent)
VALUES (?, ?, 'TOTP_BACKUP_REGEN', 'Regenerated 2FA backup codes', ?, ?)
");
$stmt->execute([
diff --git a/FINAL_PRODUCTION_SYSTEM/api/totp-setup.php b/FINAL_PRODUCTION_SYSTEM/api/totp-setup.php
index a6f799c..9e8ca57 100644
--- a/FINAL_PRODUCTION_SYSTEM/api/totp-setup.php
+++ b/FINAL_PRODUCTION_SYSTEM/api/totp-setup.php
@@ -24,7 +24,7 @@
// Verify session is valid in DB
$stmt = $pdo->prepare("
- SELECT admin_id FROM admin_sessions
+ SELECT admin_id FROM `" . t('admin_sessions') . "`
WHERE id = ? AND admin_id = ? AND is_active = 1
");
$stmt->execute([$sessionId, $adminId]);
@@ -33,7 +33,7 @@
}
// Get admin info
-$stmt = $pdo->prepare("SELECT username, email FROM admin_users WHERE id = ?");
+$stmt = $pdo->prepare("SELECT username, email FROM `" . t('admin_users') . "` WHERE id = ?");
$stmt->execute([$adminId]);
$admin = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -75,7 +75,7 @@
// Store in database (not yet enabled)
if ($existing) {
$stmt = $pdo->prepare("
- UPDATE admin_totp_secrets
+ UPDATE `" . t('admin_totp_secrets') . "`
SET totp_secret = ?, backup_codes = ?, totp_enabled = 0, verified_at = NULL, created_at = NOW()
WHERE admin_id = ?
");
@@ -86,7 +86,7 @@
]);
} else {
$stmt = $pdo->prepare("
- INSERT INTO admin_totp_secrets (admin_id, totp_secret, backup_codes, totp_enabled)
+ INSERT INTO `" . t('admin_totp_secrets') . "` (admin_id, totp_secret, backup_codes, totp_enabled)
VALUES (?, ?, ?, 0)
");
$stmt->execute([
@@ -108,7 +108,7 @@
// Log activity
$stmt = $pdo->prepare("
- INSERT INTO admin_activity_log (admin_id, session_id, action, description, ip_address, user_agent)
+ INSERT INTO `" . t('admin_activity_log') . "` (admin_id, session_id, action, description, ip_address, user_agent)
VALUES (?, ?, 'TOTP_SETUP', 'Started 2FA setup', ?, ?)
");
$stmt->execute([
diff --git a/FINAL_PRODUCTION_SYSTEM/api/totp-verify.php b/FINAL_PRODUCTION_SYSTEM/api/totp-verify.php
index 93196a6..441ec30 100644
--- a/FINAL_PRODUCTION_SYSTEM/api/totp-verify.php
+++ b/FINAL_PRODUCTION_SYSTEM/api/totp-verify.php
@@ -69,7 +69,7 @@
// If this is initial setup verification, enable 2FA
if ($isSetup && $totpData['totp_enabled'] == 0) {
$stmt = $pdo->prepare("
- UPDATE admin_totp_secrets
+ UPDATE `" . t('admin_totp_secrets') . "`
SET totp_enabled = 1, verified_at = NOW()
WHERE admin_id = ?
");
@@ -77,7 +77,7 @@
// Log activity
$stmt = $pdo->prepare("
- INSERT INTO admin_activity_log (admin_id, session_id, action, description, ip_address, user_agent)
+ INSERT INTO `" . t('admin_activity_log') . "` (admin_id, session_id, action, description, ip_address, user_agent)
VALUES (?, NULL, 'TOTP_ENABLED', '2FA successfully enabled', ?, ?)
");
$stmt->execute([
@@ -89,7 +89,7 @@
// Log successful verification
$stmt = $pdo->prepare("
- INSERT INTO admin_activity_log (admin_id, session_id, action, description, ip_address, user_agent, totp_verified)
+ INSERT INTO `" . t('admin_activity_log') . "` (admin_id, session_id, action, description, ip_address, user_agent, totp_verified)
VALUES (?, NULL, 'TOTP_VERIFIED', ?, ?, ?, 1)
");
$stmt->execute([
diff --git a/FINAL_PRODUCTION_SYSTEM/config-production.php b/FINAL_PRODUCTION_SYSTEM/config-production.php
index e2850c2..8d004f9 100644
--- a/FINAL_PRODUCTION_SYSTEM/config-production.php
+++ b/FINAL_PRODUCTION_SYSTEM/config-production.php
@@ -89,7 +89,7 @@ function getConfig($key, $useCache = true) {
}
try {
- $stmt = $pdo->prepare("SELECT config_value FROM system_config WHERE config_key = ?");
+ $stmt = $pdo->prepare("SELECT config_value FROM `" . t('system_config') . "` WHERE config_key = ?");
$stmt->execute([$key]);
$result = $stmt->fetch();
$value = $result ? $result['config_value'] : null;
@@ -192,9 +192,9 @@ function validateSession($token) {
try {
$stmt = $pdo->prepare("
SELECT s.*, k.product_key, k.key_status, t.is_active as tech_active
- FROM active_sessions s
- LEFT JOIN oem_keys k ON s.key_id = k.id
- LEFT JOIN technicians t ON s.technician_id = t.technician_id
+ FROM `" . t('active_sessions') . "` s
+ LEFT JOIN `" . t('oem_keys') . "` k ON s.key_id = k.id
+ LEFT JOIN `" . t('technicians') . "` t ON s.technician_id = t.technician_id
WHERE s.session_token = ?
AND s.is_active = 1
AND s.expires_at > NOW()
@@ -233,7 +233,7 @@ function allocateKeyAtomically($pdo, $technician_id, $order_number) {
// Select and lock the best available key
$stmt = $pdo->prepare("
- SELECT * FROM oem_keys
+ SELECT * FROM `" . t('oem_keys') . "`
WHERE key_status IN ('unused', 'retry')
AND (fail_counter < 3 OR key_status = 'unused')
ORDER BY
@@ -250,7 +250,7 @@ function allocateKeyAtomically($pdo, $technician_id, $order_number) {
if ($key) {
// Mark key as in use immediately
$stmt = $pdo->prepare("
- UPDATE oem_keys
+ UPDATE `" . t('oem_keys') . "`
SET key_status = 'allocated',
last_use_date = CURDATE(),
last_use_time = CURTIME(),
@@ -295,7 +295,7 @@ function allocateKeyAtomically($pdo, $technician_id, $order_number) {
function cleanupExpiredSessions($pdo) {
try {
$stmt = $pdo->prepare("
- UPDATE active_sessions
+ UPDATE `" . t('active_sessions') . "`
SET is_active = 0
WHERE expires_at < NOW() AND is_active = 1
LIMIT 1000
@@ -321,8 +321,8 @@ function getActiveSession($pdo, $technician_id) {
$stmt = $pdo->prepare("
SELECT s.*, k.product_key, k.oem_identifier, k.key_status, k.fail_counter
- FROM active_sessions s
- LEFT JOIN oem_keys k ON s.key_id = k.id
+ FROM `" . t('active_sessions') . "` s
+ LEFT JOIN `" . t('oem_keys') . "` k ON s.key_id = k.id
WHERE s.technician_id = ?
AND s.is_active = 1
AND s.expires_at > NOW()
diff --git a/FINAL_PRODUCTION_SYSTEM/config.php b/FINAL_PRODUCTION_SYSTEM/config.php
index 6268dfd..29304e0 100644
--- a/FINAL_PRODUCTION_SYSTEM/config.php
+++ b/FINAL_PRODUCTION_SYSTEM/config.php
@@ -108,7 +108,7 @@ function getConfig($key, $useCache = true) {
}
try {
- $stmt = $pdo->prepare("SELECT config_value FROM system_config WHERE config_key = ?");
+ $stmt = $pdo->prepare("SELECT config_value FROM `" . t('system_config') . "` WHERE config_key = ?");
$stmt->execute([$key]);
$result = $stmt->fetch();
$value = $result ? $result['config_value'] : null;
diff --git a/FINAL_PRODUCTION_SYSTEM/config/config-template-enhanced.php b/FINAL_PRODUCTION_SYSTEM/config/config-template-enhanced.php
index 05474de..289a853 100644
--- a/FINAL_PRODUCTION_SYSTEM/config/config-template-enhanced.php
+++ b/FINAL_PRODUCTION_SYSTEM/config/config-template-enhanced.php
@@ -46,7 +46,7 @@
function getConfig($key, $default = null) {
global $pdo;
try {
- $stmt = $pdo->prepare("SELECT config_value FROM system_config WHERE config_key = ?");
+ $stmt = $pdo->prepare("SELECT config_value FROM `" . t('system_config') . "` WHERE config_key = ?");
$stmt->execute([$key]);
$result = $stmt->fetch();
return $result ? $result['config_value'] : $default;
@@ -61,7 +61,7 @@ function setConfig($key, $value, $description = '') {
global $pdo;
try {
$stmt = $pdo->prepare("
- INSERT INTO system_config (config_key, config_value, description)
+ INSERT INTO `" . t('system_config') . "` (config_key, config_value, description)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE
config_value = VALUES(config_value),
@@ -102,7 +102,7 @@ function validateTechnician($technician_id, $password) {
try {
$stmt = $pdo->prepare("
- SELECT * FROM technicians
+ SELECT * FROM `" . t('technicians') . "`
WHERE technician_id = ? AND is_active = 1
");
$stmt->execute([$technician_id]);
@@ -121,7 +121,7 @@ function validateTechnician($technician_id, $password) {
if (password_verify($password, $technician['password_hash'])) {
// Reset failed attempts on successful login
$stmt = $pdo->prepare("
- UPDATE technicians
+ UPDATE `" . t('technicians') . "`
SET failed_login_attempts = 0, locked_until = NULL, last_login = NOW()
WHERE technician_id = ?
");
@@ -132,7 +132,7 @@ function validateTechnician($technician_id, $password) {
// Increment failed attempts
$stmt = $pdo->prepare("
- UPDATE technicians
+ UPDATE `" . t('technicians') . "`
SET failed_login_attempts = failed_login_attempts + 1,
locked_until = IF(failed_login_attempts + 1 >= 5, DATE_ADD(NOW(), INTERVAL 15 MINUTE), NULL)
WHERE technician_id = ?
diff --git a/FINAL_PRODUCTION_SYSTEM/constants.php b/FINAL_PRODUCTION_SYSTEM/constants.php
index fdb4101..45fc95e 100644
--- a/FINAL_PRODUCTION_SYSTEM/constants.php
+++ b/FINAL_PRODUCTION_SYSTEM/constants.php
@@ -7,6 +7,11 @@
* Import this file wherever constants are needed.
*/
+// ── DB table prefix helper (must load before any PDO query) ────────
+// Empty default for backward-compat with installs that pre-date the
+// prefix release. The web installer overwrites DB_PREFIX in config.php.
+require_once __DIR__ . '/functions/db-helpers.php';
+
// ── Authentication ─────────────────────────────────────────────────
define('BCRYPT_COST', 12);
define('PASSWORD_MIN_LENGTH', 8);
diff --git a/FINAL_PRODUCTION_SYSTEM/controllers/admin/AclController.php b/FINAL_PRODUCTION_SYSTEM/controllers/admin/AclController.php
index a05b65d..8c9e914 100644
--- a/FINAL_PRODUCTION_SYSTEM/controllers/admin/AclController.php
+++ b/FINAL_PRODUCTION_SYSTEM/controllers/admin/AclController.php
@@ -62,7 +62,7 @@ function handle_acl_create_role(PDO $pdo, array $admin_session, ?array $json_inp
}
// Rate limit: max 20 custom roles
- $stmt = $pdo->prepare("SELECT COUNT(*) FROM acl_roles WHERE is_system_role = 0");
+ $stmt = $pdo->prepare("SELECT COUNT(*) FROM `" . t('acl_roles') . "` WHERE is_system_role = 0");
$stmt->execute();
if ((int)$stmt->fetchColumn() >= 20) {
jsonResponse(['success' => false, 'error' => 'Maximum custom roles limit reached (20)']);
diff --git a/FINAL_PRODUCTION_SYSTEM/controllers/admin/BackupsController.php b/FINAL_PRODUCTION_SYSTEM/controllers/admin/BackupsController.php
index 89a5d0c..78f283e 100644
--- a/FINAL_PRODUCTION_SYSTEM/controllers/admin/BackupsController.php
+++ b/FINAL_PRODUCTION_SYSTEM/controllers/admin/BackupsController.php
@@ -8,7 +8,7 @@ function handle_list_backups(PDO $pdo, array $admin_session): void {
requirePermission('view_backups', $admin_session);
$stmt = $pdo->query("
- SELECT * FROM backup_history
+ SELECT * FROM `" . t('backup_history') . "`
ORDER BY created_at DESC
LIMIT 50
");
diff --git a/FINAL_PRODUCTION_SYSTEM/controllers/admin/BrandingController.php b/FINAL_PRODUCTION_SYSTEM/controllers/admin/BrandingController.php
index ea96a58..a23d8ea 100644
--- a/FINAL_PRODUCTION_SYSTEM/controllers/admin/BrandingController.php
+++ b/FINAL_PRODUCTION_SYSTEM/controllers/admin/BrandingController.php
@@ -140,7 +140,7 @@ function handle_upload_brand_asset(PDO $pdo, array $admin_session): void {
// Store relative path in system_config
$relativePath = 'uploads/branding/' . $storedFilename;
$stmt = $pdo->prepare("
- INSERT INTO system_config (config_key, config_value, description, updated_at)
+ INSERT INTO `" . t('system_config') . "` (config_key, config_value, description, updated_at)
VALUES (?, ?, '', NOW())
ON DUPLICATE KEY UPDATE config_value = ?, updated_at = NOW()
");
@@ -181,7 +181,7 @@ function handle_delete_brand_asset(PDO $pdo, array $admin_session, ?array $json_
// Clear config value
$stmt = $pdo->prepare("
- INSERT INTO system_config (config_key, config_value, description, updated_at)
+ INSERT INTO `" . t('system_config') . "` (config_key, config_value, description, updated_at)
VALUES (?, '', '', NOW())
ON DUPLICATE KEY UPDATE config_value = '', updated_at = NOW()
");
diff --git a/FINAL_PRODUCTION_SYSTEM/controllers/admin/ClientResourcesController.php b/FINAL_PRODUCTION_SYSTEM/controllers/admin/ClientResourcesController.php
index 5447c94..a9ce0e0 100644
--- a/FINAL_PRODUCTION_SYSTEM/controllers/admin/ClientResourcesController.php
+++ b/FINAL_PRODUCTION_SYSTEM/controllers/admin/ClientResourcesController.php
@@ -68,7 +68,7 @@ function handle_upload_client_resource(PDO $pdo, array $admin_session): void {
$destPath = $uploadDir . '/' . $storedFilename;
// Delete existing resource with same key (replace mode)
- $existing = $pdo->prepare("SELECT filename FROM client_resources WHERE resource_key = ?");
+ $existing = $pdo->prepare("SELECT filename FROM `" . t('client_resources') . "` WHERE resource_key = ?");
$existing->execute([$resourceKey]);
$oldFile = $existing->fetchColumn();
if ($oldFile) {
@@ -76,7 +76,7 @@ function handle_upload_client_resource(PDO $pdo, array $admin_session): void {
if (file_exists($oldPath)) {
unlink($oldPath);
}
- $pdo->prepare("DELETE FROM client_resources WHERE resource_key = ?")->execute([$resourceKey]);
+ $pdo->prepare("DELETE FROM `" . t('client_resources') . "` WHERE resource_key = ?")->execute([$resourceKey]);
}
// Move uploaded file
@@ -95,7 +95,7 @@ function handle_upload_client_resource(PDO $pdo, array $admin_session): void {
// Insert DB record
$stmt = $pdo->prepare("
- INSERT INTO client_resources (resource_key, filename, original_filename, file_size, mime_type, checksum_sha256, description, uploaded_by)
+ INSERT INTO `" . t('client_resources') . "` (resource_key, filename, original_filename, file_size, mime_type, checksum_sha256, description, uploaded_by)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
");
$stmt->execute([$resourceKey, $storedFilename, $originalName, $fileSize, $mimeType, $checksum, $description, $adminId]);
@@ -134,7 +134,7 @@ function handle_delete_client_resource(PDO $pdo, array $admin_session, ?array $j
return;
}
- $stmt = $pdo->prepare("SELECT filename FROM client_resources WHERE resource_key = ?");
+ $stmt = $pdo->prepare("SELECT filename FROM `" . t('client_resources') . "` WHERE resource_key = ?");
$stmt->execute([$resourceKey]);
$filename = $stmt->fetchColumn();
@@ -151,7 +151,7 @@ function handle_delete_client_resource(PDO $pdo, array $admin_session, ?array $j
}
// Delete DB record
- $pdo->prepare("DELETE FROM client_resources WHERE resource_key = ?")->execute([$resourceKey]);
+ $pdo->prepare("DELETE FROM `" . t('client_resources') . "` WHERE resource_key = ?")->execute([$resourceKey]);
logAdminActivity(
$admin_session['admin_id'],
@@ -172,8 +172,8 @@ function handle_list_client_resources(PDO $pdo, array $admin_session): void {
$stmt = $pdo->prepare("
SELECT cr.*, au.username AS uploaded_by_name
- FROM client_resources cr
- LEFT JOIN admin_users au ON cr.uploaded_by = au.id
+ FROM `" . t('client_resources') . "` cr
+ LEFT JOIN `" . t('admin_users') . "` au ON cr.uploaded_by = au.id
ORDER BY cr.created_at DESC
");
$stmt->execute();
@@ -200,7 +200,7 @@ function handle_download_client_resource(PDO $pdo, array $admin_session): void {
return;
}
- $stmt = $pdo->prepare("SELECT filename, original_filename, mime_type, file_size, checksum_sha256 FROM client_resources WHERE resource_key = ?");
+ $stmt = $pdo->prepare("SELECT filename, original_filename, mime_type, file_size, checksum_sha256 FROM `" . t('client_resources') . "` WHERE resource_key = ?");
$stmt->execute([$resourceKey]);
$resource = $stmt->fetch(PDO::FETCH_ASSOC);
diff --git a/FINAL_PRODUCTION_SYSTEM/controllers/admin/ComplianceController.php b/FINAL_PRODUCTION_SYSTEM/controllers/admin/ComplianceController.php
index 6c4395a..94a4350 100644
--- a/FINAL_PRODUCTION_SYSTEM/controllers/admin/ComplianceController.php
+++ b/FINAL_PRODUCTION_SYSTEM/controllers/admin/ComplianceController.php
@@ -23,7 +23,7 @@ function handle_qc_save_settings(PDO $pdo, array $admin_session, ?array $json_in
foreach ($allowedKeys as $key) {
if (isset($json_input[$key])) {
- $stmt = $pdo->prepare("UPDATE qc_global_settings SET setting_value = ?, updated_by = ? WHERE setting_key = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('qc_global_settings') . "` SET setting_value = ?, updated_by = ? WHERE setting_key = ?");
$stmt->execute([$json_input[$key], $admin_session['admin_id'], $key]);
}
}
@@ -95,7 +95,7 @@ function handle_qc_list_motherboards(PDO $pdo, array $admin_session, ?array $jso
unset($row);
// Distinct manufacturers for filter dropdown
- $mfrs = $pdo->query("SELECT DISTINCT manufacturer FROM qc_motherboard_registry ORDER BY manufacturer")->fetchAll(PDO::FETCH_COLUMN);
+ $mfrs = $pdo->query("SELECT DISTINCT manufacturer FROM `" . t('qc_motherboard_registry') . "` ORDER BY manufacturer")->fetchAll(PDO::FETCH_COLUMN);
jsonResponse([
'success' => true,
@@ -111,7 +111,7 @@ function handle_qc_get_motherboard(PDO $pdo, array $admin_session, ?array $json_
requirePermission('view_compliance', $admin_session);
$id = (int) ($_GET['id'] ?? 0);
- $stmt = $pdo->prepare("SELECT * FROM qc_motherboard_registry WHERE id = ?");
+ $stmt = $pdo->prepare("SELECT * FROM `" . t('qc_motherboard_registry') . "` WHERE id = ?");
$stmt->execute([$id]);
$board = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -161,7 +161,7 @@ function handle_qc_update_motherboard(PDO $pdo, array $admin_session, ?array $js
$params[] = $admin_session['admin_id'];
$params[] = $id;
- $stmt = $pdo->prepare("UPDATE qc_motherboard_registry SET " . implode(", ", $fields) . " WHERE id = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('qc_motherboard_registry') . "` SET " . implode(", ", $fields) . " WHERE id = ?");
$stmt->execute($params);
logAdminActivity($admin_session['admin_id'], $admin_session['id'], 'QC_MOTHERBOARD_UPDATE', "Updated motherboard registry #$id");
@@ -174,14 +174,14 @@ function handle_qc_list_manufacturers(PDO $pdo, array $admin_session, ?array $js
requirePermission('view_compliance', $admin_session);
// Configured manufacturers
- $stmt = $pdo->query("SELECT * FROM qc_manufacturer_defaults ORDER BY manufacturer");
+ $stmt = $pdo->query("SELECT * FROM `" . t('qc_manufacturer_defaults') . "` ORDER BY manufacturer");
$configured = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Unconfigured: manufacturers seen in registry but no defaults entry
$stmt = $pdo->query("
SELECT DISTINCT r.manufacturer
- FROM qc_motherboard_registry r
- LEFT JOIN qc_manufacturer_defaults md ON r.manufacturer = md.manufacturer
+ FROM `" . t('qc_motherboard_registry') . "` r
+ LEFT JOIN `" . t('qc_manufacturer_defaults') . "` md ON r.manufacturer = md.manufacturer
WHERE md.id IS NULL
ORDER BY r.manufacturer
");
@@ -200,7 +200,7 @@ function handle_qc_update_manufacturer(PDO $pdo, array $admin_session, ?array $j
}
$stmt = $pdo->prepare("
- INSERT INTO qc_manufacturer_defaults (manufacturer, secure_boot_required, secure_boot_enforcement, min_bios_version, recommended_bios_version, bios_enforcement, hackbgrt_enforcement, notes, updated_by)
+ INSERT INTO `" . t('qc_manufacturer_defaults') . "` (manufacturer, secure_boot_required, secure_boot_enforcement, min_bios_version, recommended_bios_version, bios_enforcement, hackbgrt_enforcement, notes, updated_by)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
secure_boot_required = VALUES(secure_boot_required),
@@ -454,7 +454,7 @@ function handle_qc_get_stats(PDO $pdo, array $admin_session, ?array $json_input
requirePermission('view_compliance', $admin_session);
// Result counts
- $stmt = $pdo->query("SELECT check_result, COUNT(*) as cnt FROM qc_compliance_results GROUP BY check_result");
+ $stmt = $pdo->query("SELECT check_result, COUNT(*) as cnt FROM `" . t('qc_compliance_results') . "` GROUP BY check_result");
$resultCounts = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
$total = array_sum($resultCounts);
@@ -463,8 +463,8 @@ function handle_qc_get_stats(PDO $pdo, array $admin_session, ?array $json_input
// Top failing boards
$stmt = $pdo->query("
SELECT hi.motherboard_manufacturer, hi.motherboard_product, COUNT(*) as fail_count
- FROM qc_compliance_results cr
- JOIN hardware_info hi ON cr.hardware_info_id = hi.id
+ FROM `" . t('qc_compliance_results') . "` cr
+ JOIN `" . t('hardware_info') . "` hi ON cr.hardware_info_id = hi.id
WHERE cr.check_result = 'fail'
GROUP BY hi.motherboard_manufacturer, hi.motherboard_product
ORDER BY fail_count DESC
@@ -473,19 +473,19 @@ function handle_qc_get_stats(PDO $pdo, array $admin_session, ?array $json_input
$topFailing = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Unresolved blocking
- $stmt = $pdo->query("SELECT COUNT(DISTINCT hardware_info_id) FROM qc_compliance_results WHERE enforcement_level = 3 AND check_result = 'fail'");
+ $stmt = $pdo->query("SELECT COUNT(DISTINCT hardware_info_id) FROM `" . t('qc_compliance_results') . "` WHERE enforcement_level = 3 AND check_result = 'fail'");
$unresolvedBlocking = (int) $stmt->fetchColumn();
// Registry stats
- $stmt = $pdo->query("SELECT COUNT(*) FROM qc_motherboard_registry");
+ $stmt = $pdo->query("SELECT COUNT(*) FROM `" . t('qc_motherboard_registry') . "`");
$registeredBoards = (int) $stmt->fetchColumn();
- $stmt = $pdo->query("SELECT COUNT(*) FROM qc_manufacturer_defaults");
+ $stmt = $pdo->query("SELECT COUNT(*) FROM `" . t('qc_manufacturer_defaults') . "`");
$mfrsWithDefaults = (int) $stmt->fetchColumn();
// Check type breakdown
$stmt = $pdo->query("
SELECT check_type, check_result, COUNT(*) as cnt
- FROM qc_compliance_results
+ FROM `" . t('qc_compliance_results') . "`
GROUP BY check_type, check_result
");
$byType = [];
diff --git a/FINAL_PRODUCTION_SYSTEM/controllers/admin/DashboardController.php b/FINAL_PRODUCTION_SYSTEM/controllers/admin/DashboardController.php
index 41ee81f..dee6f2c 100644
--- a/FINAL_PRODUCTION_SYSTEM/controllers/admin/DashboardController.php
+++ b/FINAL_PRODUCTION_SYSTEM/controllers/admin/DashboardController.php
@@ -17,7 +17,7 @@ function buildReportHtml(PDO $pdo, string $reportType): string {
switch ($reportType) {
case 'summary':
- $stmt = $pdo->query("SELECT key_status, COUNT(*) as count FROM oem_keys GROUP BY key_status");
+ $stmt = $pdo->query("SELECT key_status, COUNT(*) as count FROM `" . t('oem_keys') . "` GROUP BY key_status");
$keyStats = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
$totalKeys = array_sum($keyStats);
@@ -32,7 +32,7 @@ function buildReportHtml(PDO $pdo, string $reportType): string {
$html .= '';
// Technician summary
- $stmt = $pdo->query("SELECT is_active, COUNT(*) as count FROM technicians GROUP BY is_active");
+ $stmt = $pdo->query("SELECT is_active, COUNT(*) as count FROM `" . t('technicians') . "` GROUP BY is_active");
$techStats = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
$html .= '
' . __('keys.report_tech_summary') . '
';
$html .= '| ' . __('keys.status') . ' | ' . __('common.count') . ' |
';
@@ -46,7 +46,7 @@ function buildReportHtml(PDO $pdo, string $reportType): string {
SELECT DATE(attempted_date) as date, COUNT(*) as count,
SUM(CASE WHEN attempt_result = 'success' THEN 1 ELSE 0 END) as successes,
SUM(CASE WHEN attempt_result != 'success' THEN 1 ELSE 0 END) as failures
- FROM activation_attempts
+ FROM `" . t('activation_attempts') . "`
WHERE attempted_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
GROUP BY DATE(attempted_date)
ORDER BY date DESC
@@ -66,8 +66,8 @@ function buildReportHtml(PDO $pdo, string $reportType): string {
$stmt = $pdo->query("
SELECT aa.attempted_date, aa.technician_id, aa.order_number,
k.product_key, aa.notes
- FROM activation_attempts aa
- LEFT JOIN oem_keys k ON aa.key_id = k.id
+ FROM `" . t('activation_attempts') . "` aa
+ LEFT JOIN `" . t('oem_keys') . "` k ON aa.key_id = k.id
WHERE aa.attempt_result != 'success'
ORDER BY aa.attempted_date DESC
LIMIT 100
@@ -94,7 +94,7 @@ function buildReportHtml(PDO $pdo, string $reportType): string {
COUNT(*) as total,
SUM(CASE WHEN attempt_result = 'success' THEN 1 ELSE 0 END) as successes,
COUNT(DISTINCT technician_id) as unique_techs
- FROM activation_attempts
+ FROM `" . t('activation_attempts') . "`
GROUP BY DATE_FORMAT(attempted_date, '%Y-%m')
ORDER BY month DESC
LIMIT 12
@@ -120,7 +120,7 @@ function handle_get_stats(PDO $pdo, array $admin_session): void {
$stats = [];
// Key statistics
- $stmt = $pdo->query("SELECT key_status, COUNT(*) as count FROM oem_keys GROUP BY key_status");
+ $stmt = $pdo->query("SELECT key_status, COUNT(*) as count FROM `" . t('oem_keys') . "` GROUP BY key_status");
$key_stats = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
$stats['keys'] = [
'unused' => $key_stats['unused'] ?? 0,
@@ -132,7 +132,7 @@ function handle_get_stats(PDO $pdo, array $admin_session): void {
];
// Technician statistics
- $stmt = $pdo->query("SELECT is_active, COUNT(*) as count FROM technicians GROUP BY is_active");
+ $stmt = $pdo->query("SELECT is_active, COUNT(*) as count FROM `" . t('technicians') . "` GROUP BY is_active");
$tech_stats = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
$stats['technicians'] = [
'active' => $tech_stats[1] ?? 0,
@@ -141,13 +141,13 @@ function handle_get_stats(PDO $pdo, array $admin_session): void {
];
// Activation statistics
- $stmt = $pdo->query("SELECT COUNT(*) FROM activation_attempts WHERE DATE(attempted_date) = CURDATE()");
+ $stmt = $pdo->query("SELECT COUNT(*) FROM `" . t('activation_attempts') . "` WHERE DATE(attempted_date) = CURDATE()");
$stats['activations']['today'] = $stmt->fetchColumn();
- $stmt = $pdo->query("SELECT COUNT(*) FROM activation_attempts WHERE YEARWEEK(attempted_date, 1) = YEARWEEK(CURDATE(), 1)");
+ $stmt = $pdo->query("SELECT COUNT(*) FROM `" . t('activation_attempts') . "` WHERE YEARWEEK(attempted_date, 1) = YEARWEEK(CURDATE(), 1)");
$stats['activations']['week'] = $stmt->fetchColumn();
- $stmt = $pdo->query("SELECT COUNT(*) FROM activation_attempts WHERE YEAR(attempted_date) = YEAR(CURDATE()) AND MONTH(attempted_date) = MONTH(CURDATE())");
+ $stmt = $pdo->query("SELECT COUNT(*) FROM `" . t('activation_attempts') . "` WHERE YEAR(attempted_date) = YEAR(CURDATE()) AND MONTH(attempted_date) = MONTH(CURDATE())");
$stats['activations']['month'] = $stmt->fetchColumn();
// Daily activation trend — fetch all history, let frontend slice by range
@@ -156,7 +156,7 @@ function handle_get_stats(PDO $pdo, array $admin_session): void {
COUNT(*) as total,
SUM(CASE WHEN attempt_result = 'success' THEN 1 ELSE 0 END) as successes,
SUM(CASE WHEN attempt_result != 'success' THEN 1 ELSE 0 END) as failures
- FROM activation_attempts
+ FROM `" . t('activation_attempts') . "`
GROUP BY DATE(attempted_date)
ORDER BY date ASC
");
@@ -188,8 +188,8 @@ function handle_get_stats(PDO $pdo, array $admin_session): void {
// Recent activity
$stmt = $pdo->prepare("
SELECT aal.created_at, au.username, aal.action, aal.description
- FROM admin_activity_log aal
- LEFT JOIN admin_users au ON aal.admin_id = au.id
+ FROM `" . t('admin_activity_log') . "` aal
+ LEFT JOIN `" . t('admin_users') . "` au ON aal.admin_id = au.id
ORDER BY aal.created_at DESC
LIMIT 10
");
diff --git a/FINAL_PRODUCTION_SYSTEM/controllers/admin/HistoryController.php b/FINAL_PRODUCTION_SYSTEM/controllers/admin/HistoryController.php
index 50dc1e4..705e017 100644
--- a/FINAL_PRODUCTION_SYSTEM/controllers/admin/HistoryController.php
+++ b/FINAL_PRODUCTION_SYSTEM/controllers/admin/HistoryController.php
@@ -71,10 +71,10 @@ function handle_get_hardware(PDO $pdo, array $admin_session): void {
$stmt = $pdo->prepare("
SELECT h.*, aa.order_number, aa.attempted_at, aa.technician_id,
t.full_name as technician_name, k.product_key
- FROM hardware_info h
- INNER JOIN activation_attempts aa ON h.activation_id = aa.id
- LEFT JOIN technicians t ON aa.technician_id = t.technician_id
- LEFT JOIN oem_keys k ON aa.key_id = k.id
+ FROM `" . t('hardware_info') . "` h
+ INNER JOIN `" . t('activation_attempts') . "` aa ON h.activation_id = aa.id
+ LEFT JOIN `" . t('technicians') . "` t ON aa.technician_id = t.technician_id
+ LEFT JOIN `" . t('oem_keys') . "` k ON aa.key_id = k.id
WHERE h.activation_id = ?
");
$stmt->execute([$activationId]);
@@ -101,10 +101,10 @@ function handle_get_hardware_by_order(PDO $pdo, array $admin_session): void {
aa.attempt_result as activation_result,
aa.attempted_at as activation_time,
k.product_key
- FROM hardware_info h
- LEFT JOIN technicians t ON h.technician_id = t.technician_id
- LEFT JOIN activation_attempts aa ON h.activation_id = aa.id
- LEFT JOIN oem_keys k ON aa.key_id = k.id
+ FROM `" . t('hardware_info') . "` h
+ LEFT JOIN `" . t('technicians') . "` t ON h.technician_id = t.technician_id
+ LEFT JOIN `" . t('activation_attempts') . "` aa ON h.activation_id = aa.id
+ LEFT JOIN `" . t('oem_keys') . "` k ON aa.key_id = k.id
WHERE h.order_number = ?
ORDER BY h.collection_timestamp DESC
LIMIT 1
diff --git a/FINAL_PRODUCTION_SYSTEM/controllers/admin/IntegrationController.php b/FINAL_PRODUCTION_SYSTEM/controllers/admin/IntegrationController.php
index a093ec4..9d64e59 100644
--- a/FINAL_PRODUCTION_SYSTEM/controllers/admin/IntegrationController.php
+++ b/FINAL_PRODUCTION_SYSTEM/controllers/admin/IntegrationController.php
@@ -9,7 +9,7 @@
function handle_list_integrations(PDO $pdo, array $admin_session): void {
requirePermission('system_settings', $admin_session);
- $stmt = $pdo->query("SELECT * FROM integrations ORDER BY id ASC");
+ $stmt = $pdo->query("SELECT * FROM `" . t('integrations') . "` ORDER BY id ASC");
$rows = $stmt->fetchAll();
// Decode config JSON and mask sensitive fields
@@ -29,7 +29,7 @@ function handle_list_integrations(PDO $pdo, array $admin_session): void {
COUNT(*) as total,
SUM(status = 'failed') as failed,
SUM(status = 'pending') as pending
- FROM integration_events WHERE integration_id = ?
+ FROM `" . t('integration_events') . "` WHERE integration_id = ?
");
$countStmt->execute([$row['id']]);
$row['event_counts'] = $countStmt->fetch();
@@ -48,7 +48,7 @@ function handle_get_integration(PDO $pdo, array $admin_session): void {
return;
}
- $stmt = $pdo->prepare("SELECT * FROM integrations WHERE integration_key = ?");
+ $stmt = $pdo->prepare("SELECT * FROM `" . t('integrations') . "` WHERE integration_key = ?");
$stmt->execute([$key]);
$intg = $stmt->fetch();
if (!$intg) {
@@ -61,7 +61,7 @@ function handle_get_integration(PDO $pdo, array $admin_session): void {
// Recent events (last 20)
$evtStmt = $pdo->prepare("
SELECT id, event_type, status, response_code, error_message, created_at, processed_at
- FROM integration_events
+ FROM `" . t('integration_events') . "`
WHERE integration_id = ?
ORDER BY created_at DESC LIMIT 20
");
@@ -85,7 +85,7 @@ function handle_save_integration(PDO $pdo, array $admin_session, ?array $json_in
return;
}
- $stmt = $pdo->prepare("SELECT * FROM integrations WHERE integration_key = ?");
+ $stmt = $pdo->prepare("SELECT * FROM `" . t('integrations') . "` WHERE integration_key = ?");
$stmt->execute([$key]);
$intg = $stmt->fetch();
if (!$intg) {
@@ -111,7 +111,7 @@ function handle_save_integration(PDO $pdo, array $admin_session, ?array $json_in
}
$updateStmt = $pdo->prepare("
- UPDATE integrations
+ UPDATE `" . t('integrations') . "`
SET enabled = ?, config = ?, updated_at = NOW()
WHERE integration_key = ?
");
diff --git a/FINAL_PRODUCTION_SYSTEM/controllers/admin/KeysController.php b/FINAL_PRODUCTION_SYSTEM/controllers/admin/KeysController.php
index b2f6cbe..86115eb 100644
--- a/FINAL_PRODUCTION_SYSTEM/controllers/admin/KeysController.php
+++ b/FINAL_PRODUCTION_SYSTEM/controllers/admin/KeysController.php
@@ -105,7 +105,7 @@ function handle_recycle_key(PDO $pdo, array $admin_session): void {
$id = intval($_POST['id'] ?? 0);
$stmt = $pdo->prepare("
- UPDATE oem_keys
+ UPDATE `" . t('oem_keys') . "`
SET key_status = 'unused', last_use_date = NULL, last_use_time = NULL
WHERE id = ?
");
@@ -126,7 +126,7 @@ function handle_delete_key(PDO $pdo, array $admin_session): void {
$id = intval($_POST['id'] ?? 0);
- $stmt = $pdo->prepare("DELETE FROM oem_keys WHERE id = ?");
+ $stmt = $pdo->prepare("DELETE FROM `" . t('oem_keys') . "` WHERE id = ?");
$stmt->execute([$id]);
logAdminActivity(
@@ -265,9 +265,9 @@ function handle_add_keys(PDO $pdo, array $admin_session, ?array $json_input = nu
$pdo->beginTransaction();
try {
- $checkStmt = $pdo->prepare("SELECT id FROM oem_keys WHERE product_key = ?");
+ $checkStmt = $pdo->prepare("SELECT id FROM `" . t('oem_keys') . "` WHERE product_key = ?");
$insertStmt = $pdo->prepare("
- INSERT INTO oem_keys (product_key, oem_identifier, roll_serial, key_status, created_at)
+ INSERT INTO `" . t('oem_keys') . "` (product_key, oem_identifier, roll_serial, key_status, created_at)
VALUES (?, ?, ?, 'unused', NOW())
");
diff --git a/FINAL_PRODUCTION_SYSTEM/controllers/admin/LicenseController.php b/FINAL_PRODUCTION_SYSTEM/controllers/admin/LicenseController.php
index 165c59b..4020115 100644
--- a/FINAL_PRODUCTION_SYSTEM/controllers/admin/LicenseController.php
+++ b/FINAL_PRODUCTION_SYSTEM/controllers/admin/LicenseController.php
@@ -17,12 +17,12 @@ function handle_license_status(PDO $pdo, array $admin_session, $json_input): voi
$techCount = 0;
$keyCount = 0;
try {
- $stmt = $pdo->query("SELECT COUNT(*) FROM technicians WHERE status = 'active'");
+ $stmt = $pdo->query("SELECT COUNT(*) FROM `" . t('technicians') . "` WHERE status = 'active'");
$techCount = (int)$stmt->fetchColumn();
} catch (Exception $e) { /* table may not exist */ }
try {
- $stmt = $pdo->query("SELECT COUNT(*) FROM oem_keys");
+ $stmt = $pdo->query("SELECT COUNT(*) FROM `" . t('oem_keys') . "`");
$keyCount = (int)$stmt->fetchColumn();
} catch (Exception $e) { /* table may not exist */ }
@@ -76,7 +76,7 @@ function handle_license_register(PDO $pdo, array $admin_session, $json_input): v
function handle_license_deactivate(PDO $pdo, array $admin_session, $json_input): void {
requirePermission('system_settings', $admin_session);
- $pdo->exec("UPDATE license_info SET is_active = 0");
+ $pdo->exec("UPDATE `" . t('license_info') . "` SET is_active = 0");
saveConfigBatch($pdo, ['license_tier' => 'community']);
logAdminActivity(
diff --git a/FINAL_PRODUCTION_SYSTEM/controllers/admin/NotificationsController.php b/FINAL_PRODUCTION_SYSTEM/controllers/admin/NotificationsController.php
index 81233f1..9e65f2c 100644
--- a/FINAL_PRODUCTION_SYSTEM/controllers/admin/NotificationsController.php
+++ b/FINAL_PRODUCTION_SYSTEM/controllers/admin/NotificationsController.php
@@ -39,7 +39,7 @@ function handle_push_subscribe(PDO $pdo, array $admin_session, ?array $json_inpu
// Upsert: insert or re-activate existing subscription
$stmt = $pdo->prepare("
- INSERT INTO push_subscriptions (admin_id, endpoint, p256dh_key, auth_key, user_agent, is_active)
+ INSERT INTO `" . t('push_subscriptions') . "` (admin_id, endpoint, p256dh_key, auth_key, user_agent, is_active)
VALUES (?, ?, ?, ?, ?, 1)
ON DUPLICATE KEY UPDATE p256dh_key = VALUES(p256dh_key), auth_key = VALUES(auth_key),
user_agent = VALUES(user_agent), is_active = 1, last_used_at = NOW()
@@ -58,10 +58,10 @@ function handle_push_unsubscribe(PDO $pdo, array $admin_session, ?array $json_in
if (empty($endpoint)) {
// Deactivate all subscriptions for this admin
- $stmt = $pdo->prepare("UPDATE push_subscriptions SET is_active = 0 WHERE admin_id = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('push_subscriptions') . "` SET is_active = 0 WHERE admin_id = ?");
$stmt->execute([$adminId]);
} else {
- $stmt = $pdo->prepare("UPDATE push_subscriptions SET is_active = 0 WHERE admin_id = ? AND endpoint = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('push_subscriptions') . "` SET is_active = 0 WHERE admin_id = ? AND endpoint = ?");
$stmt->execute([$adminId, $endpoint]);
}
@@ -75,7 +75,7 @@ function handle_get_push_preferences(PDO $pdo, array $admin_session): void {
$adminId = (int)$admin_session['admin_id'];
// Get saved preferences
- $stmt = $pdo->prepare("SELECT category, enabled FROM push_preferences WHERE admin_id = ?");
+ $stmt = $pdo->prepare("SELECT category, enabled FROM `" . t('push_preferences') . "` WHERE admin_id = ?");
$stmt->execute([$adminId]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
@@ -90,7 +90,7 @@ function handle_get_push_preferences(PDO $pdo, array $admin_session): void {
}
// Check if admin has any active subscriptions
- $subStmt = $pdo->prepare("SELECT COUNT(*) FROM push_subscriptions WHERE admin_id = ? AND is_active = 1");
+ $subStmt = $pdo->prepare("SELECT COUNT(*) FROM `" . t('push_subscriptions') . "` WHERE admin_id = ? AND is_active = 1");
$subStmt->execute([$adminId]);
$hasSubscription = (int)$subStmt->fetchColumn() > 0;
@@ -117,7 +117,7 @@ function handle_save_push_preferences(PDO $pdo, array $admin_session, ?array $js
$validCategories = ['security', 'keys', 'technicians', 'system', 'devices', 'activation'];
$stmt = $pdo->prepare("
- INSERT INTO push_preferences (admin_id, category, enabled)
+ INSERT INTO `" . t('push_preferences') . "` (admin_id, category, enabled)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE enabled = VALUES(enabled)
");
@@ -141,7 +141,7 @@ function handle_get_notifications(PDO $pdo, array $admin_session): void {
// Get 50 most recent notifications
$stmt = $pdo->prepare("
SELECT id, category, title_key, body, action_url, is_read, created_at
- FROM notifications
+ FROM `" . t('notifications') . "`
WHERE admin_id = ?
ORDER BY created_at DESC
LIMIT 50
@@ -150,7 +150,7 @@ function handle_get_notifications(PDO $pdo, array $admin_session): void {
$notifications = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Get unread count
- $countStmt = $pdo->prepare("SELECT COUNT(*) FROM notifications WHERE admin_id = ? AND is_read = 0");
+ $countStmt = $pdo->prepare("SELECT COUNT(*) FROM `" . t('notifications') . "` WHERE admin_id = ? AND is_read = 0");
$countStmt->execute([$adminId]);
$unreadCount = (int)$countStmt->fetchColumn();
@@ -170,7 +170,7 @@ function handle_send_test_notification(PDO $pdo, array $admin_session, ?array $j
// Insert a bell notification for this admin
$stmt = $pdo->prepare("
- INSERT INTO notifications (admin_id, category, title_key, body, action_url)
+ INSERT INTO `" . t('notifications') . "` (admin_id, category, title_key, body, action_url)
VALUES (?, 'system', 'notif.title.system', ?, 'admin_v2.php#notifications')
");
$testBody = $type === 'sound'
@@ -182,8 +182,8 @@ function handle_send_test_notification(PDO $pdo, array $admin_session, ?array $j
if ($type === 'push') {
$subStmt = $pdo->prepare("
SELECT ps.endpoint, ps.p256dh_key, ps.auth_key, au.preferred_language
- FROM push_subscriptions ps
- JOIN admin_users au ON ps.admin_id = au.id
+ FROM `" . t('push_subscriptions') . "` ps
+ JOIN `" . t('admin_users') . "` au ON ps.admin_id = au.id
WHERE ps.admin_id = ? AND ps.is_active = 1
");
$subStmt->execute([$adminId]);
@@ -220,7 +220,7 @@ function handle_send_test_notification(PDO $pdo, array $admin_session, ?array $j
foreach ($webPush->flush() as $report) {
if ($report->isSubscriptionExpired()) {
$endpoint = $report->getRequest()->getUri()->__toString();
- $pdo->prepare("UPDATE push_subscriptions SET is_active = 0 WHERE endpoint = ?")
+ $pdo->prepare("UPDATE `" . t('push_subscriptions') . "` SET is_active = 0 WHERE endpoint = ?")
->execute([$endpoint]);
}
}
@@ -240,7 +240,7 @@ function handle_mark_notifications_read(PDO $pdo, array $admin_session, ?array $
if ($ids === null || (is_array($ids) && empty($ids))) {
// Mark all as read
- $stmt = $pdo->prepare("UPDATE notifications SET is_read = 1 WHERE admin_id = ? AND is_read = 0");
+ $stmt = $pdo->prepare("UPDATE `" . t('notifications') . "` SET is_read = 1 WHERE admin_id = ? AND is_read = 0");
$stmt->execute([$adminId]);
} elseif (is_array($ids)) {
$intIds = array_map('intval', $ids);
diff --git a/FINAL_PRODUCTION_SYSTEM/controllers/admin/ProductVariantsController.php b/FINAL_PRODUCTION_SYSTEM/controllers/admin/ProductVariantsController.php
index 100843f..fa406e6 100644
--- a/FINAL_PRODUCTION_SYSTEM/controllers/admin/ProductVariantsController.php
+++ b/FINAL_PRODUCTION_SYSTEM/controllers/admin/ProductVariantsController.php
@@ -14,8 +14,8 @@ function handle_get_product_lines(PDO $pdo, array $admin_session, ?array $json_i
$stmt = $pdo->query("
SELECT pl.*,
COUNT(DISTINCT pv.id) AS variant_count
- FROM product_lines pl
- LEFT JOIN product_variants pv ON pv.line_id = pl.id AND pv.is_active = 1
+ FROM `" . t('product_lines') . "` pl
+ LEFT JOIN `" . t('product_variants') . "` pv ON pv.line_id = pl.id AND pv.is_active = 1
GROUP BY pl.id
ORDER BY pl.name
");
@@ -32,7 +32,7 @@ function handle_get_product_line(PDO $pdo, array $admin_session, ?array $json_in
jsonResponse(['success' => false, 'error' => 'Invalid line ID'], 400);
}
- $stmt = $pdo->prepare("SELECT * FROM product_lines WHERE id = ?");
+ $stmt = $pdo->prepare("SELECT * FROM `" . t('product_lines') . "` WHERE id = ?");
$stmt->execute([$id]);
$line = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$line) {
@@ -42,7 +42,7 @@ function handle_get_product_line(PDO $pdo, array $admin_session, ?array $json_in
// Fetch variants
$stmt = $pdo->prepare("
SELECT pv.*
- FROM product_variants pv
+ FROM `" . t('product_variants') . "` pv
WHERE pv.line_id = ? AND pv.is_active = 1
ORDER BY pv.disk_size_min_mb
");
@@ -104,7 +104,7 @@ function handle_save_product_line(PDO $pdo, array $admin_session, ?array $json_i
if ($id > 0) {
// Update
$stmt = $pdo->prepare("
- UPDATE product_lines
+ UPDATE `" . t('product_lines') . "`
SET name = ?, order_pattern = ?, description = ?, enforcement_level = ?, is_active = ?,
secure_boot_enforcement = ?, bios_enforcement = ?, hackbgrt_enforcement = ?,
partition_enforcement = ?, missing_drivers_enforcement = ?
@@ -116,7 +116,7 @@ function handle_save_product_line(PDO $pdo, array $admin_session, ?array $json_i
} else {
// Insert
$stmt = $pdo->prepare("
- INSERT INTO product_lines (name, order_pattern, description, enforcement_level, is_active,
+ INSERT INTO `" . t('product_lines') . "` (name, order_pattern, description, enforcement_level, is_active,
secure_boot_enforcement, bios_enforcement, hackbgrt_enforcement,
partition_enforcement, missing_drivers_enforcement)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
@@ -146,7 +146,7 @@ function handle_delete_product_line(PDO $pdo, array $admin_session, ?array $json
jsonResponse(['success' => false, 'error' => 'Invalid line ID'], 400);
}
- $stmt = $pdo->prepare("UPDATE product_lines SET is_active = 0 WHERE id = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('product_lines') . "` SET is_active = 0 WHERE id = ?");
$stmt->execute([$id]);
logAdminActivity($admin_session['admin_id'], $admin_session['id'], 'PRODUCT_LINE_DELETE', "Deactivated product line ID: $id");
@@ -177,14 +177,14 @@ function handle_save_product_variant(PDO $pdo, array $admin_session, ?array $jso
try {
if ($id > 0) {
$stmt = $pdo->prepare("
- UPDATE product_variants
+ UPDATE `" . t('product_variants') . "`
SET line_id = ?, name = ?, disk_size_min_mb = ?, disk_size_max_mb = ?, is_active = ?
WHERE id = ?
");
$stmt->execute([$lineId, $name, $diskSizeMin, $diskSizeMax, $isActive, $id]);
} else {
$stmt = $pdo->prepare("
- INSERT INTO product_variants (line_id, name, disk_size_min_mb, disk_size_max_mb, is_active)
+ INSERT INTO `" . t('product_variants') . "` (line_id, name, disk_size_min_mb, disk_size_max_mb, is_active)
VALUES (?, ?, ?, ?, ?)
");
$stmt->execute([$lineId, $name, $diskSizeMin, $diskSizeMax, $isActive]);
@@ -192,12 +192,12 @@ function handle_save_product_variant(PDO $pdo, array $admin_session, ?array $jso
}
// Replace partitions: delete existing, insert new
- $stmt = $pdo->prepare("DELETE FROM product_variant_partitions WHERE variant_id = ?");
+ $stmt = $pdo->prepare("DELETE FROM `" . t('product_variant_partitions') . "` WHERE variant_id = ?");
$stmt->execute([$id]);
if (!empty($partitions)) {
$stmt = $pdo->prepare("
- INSERT INTO product_variant_partitions
+ INSERT INTO `" . t('product_variant_partitions') . "`
(variant_id, partition_order, partition_name, partition_type, expected_size_mb, tolerance_percent, is_flexible)
VALUES (?, ?, ?, ?, ?, ?, ?)
");
@@ -257,7 +257,7 @@ function handle_delete_product_variant(PDO $pdo, array $admin_session, ?array $j
jsonResponse(['success' => false, 'error' => 'Invalid variant ID'], 400);
}
- $stmt = $pdo->prepare("UPDATE product_variants SET is_active = 0 WHERE id = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('product_variants') . "` SET is_active = 0 WHERE id = ?");
$stmt->execute([$id]);
logAdminActivity($admin_session['admin_id'], $admin_session['id'], 'PRODUCT_VARIANT_DELETE', "Deactivated variant ID: $id");
diff --git a/FINAL_PRODUCTION_SYSTEM/controllers/admin/ProductionController.php b/FINAL_PRODUCTION_SYSTEM/controllers/admin/ProductionController.php
index ab4452b..ebf473c 100644
--- a/FINAL_PRODUCTION_SYSTEM/controllers/admin/ProductionController.php
+++ b/FINAL_PRODUCTION_SYSTEM/controllers/admin/ProductionController.php
@@ -74,10 +74,10 @@ function handle_get_build_report(PDO $pdo, array $admin_session, $json_input): v
$uuid = $json_input['uuid'] ?? $_GET['uuid'] ?? '';
if ($id > 0) {
- $stmt = $pdo->prepare("SELECT * FROM computer_build_reports WHERE id = ?");
+ $stmt = $pdo->prepare("SELECT * FROM `" . t('computer_build_reports') . "` WHERE id = ?");
$stmt->execute([$id]);
} elseif ($uuid) {
- $stmt = $pdo->prepare("SELECT * FROM computer_build_reports WHERE report_uuid = ?");
+ $stmt = $pdo->prepare("SELECT * FROM `" . t('computer_build_reports') . "` WHERE report_uuid = ?");
$stmt->execute([$uuid]);
} else {
jsonResponse(['success' => false, 'error' => 'Report ID or UUID required']);
@@ -99,7 +99,7 @@ function handle_export_build_report(PDO $pdo, array $admin_session, $json_input)
$id = (int)($json_input['id'] ?? $_GET['id'] ?? 0);
$format = $json_input['format'] ?? $_GET['format'] ?? 'json';
- $stmt = $pdo->prepare("SELECT * FROM computer_build_reports WHERE id = ?");
+ $stmt = $pdo->prepare("SELECT * FROM `" . t('computer_build_reports') . "` WHERE id = ?");
$stmt->execute([$id]);
$report = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -204,7 +204,7 @@ function handle_update_build_report_shipping(PDO $pdo, array $admin_session, $js
}
$params[] = $id;
- $stmt = $pdo->prepare("UPDATE computer_build_reports SET " . implode(', ', $sets) . " WHERE id = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('computer_build_reports') . "` SET " . implode(', ', $sets) . " WHERE id = ?");
$stmt->execute($params);
logAdminActivity($admin_session['admin_id'], $admin_session['id'] ?? 0, 'CBR_SHIPPING_UPDATED', "Updated CBR #{$id} shipping: {$shippingStatus}");
@@ -228,13 +228,13 @@ function handle_get_key_pool_status(PDO $pdo, array $admin_session, $json_input)
SUM(CASE WHEN key_status = 'allocated' THEN 1 ELSE 0 END) AS allocated_keys,
SUM(CASE WHEN key_status = 'good' THEN 1 ELSE 0 END) AS used_keys,
SUM(CASE WHEN key_status = 'bad' THEN 1 ELSE 0 END) AS bad_keys
- FROM oem_keys
+ FROM `" . t('oem_keys') . "`
GROUP BY oem_identifier
");
$pools = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Get pool config
- $configStmt = $pdo->query("SELECT * FROM key_pool_config ORDER BY product_edition");
+ $configStmt = $pdo->query("SELECT * FROM `" . t('key_pool_config') . "` ORDER BY product_edition");
$configs = [];
foreach ($configStmt->fetchAll(PDO::FETCH_ASSOC) as $c) {
$configs[$c['product_edition']] = $c;
@@ -287,7 +287,7 @@ function handle_save_key_pool_config(PDO $pdo, array $admin_session, $json_input
}
$stmt = $pdo->prepare("
- INSERT INTO key_pool_config (product_edition, low_threshold, critical_threshold, auto_notify, notify_email)
+ INSERT INTO `" . t('key_pool_config') . "` (product_edition, low_threshold, critical_threshold, auto_notify, notify_email)
VALUES (?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
low_threshold = VALUES(low_threshold),
@@ -326,15 +326,15 @@ function handle_check_hardware_binding(PDO $pdo, array $admin_session, $json_inp
// Return recent bindings
$stmt = $pdo->query("
SELECT hkb.*, ok.product_key, ok.oem_identifier AS product_type
- FROM hardware_key_bindings hkb
- LEFT JOIN oem_keys ok ON ok.id = hkb.product_key_id
+ FROM `" . t('hardware_key_bindings') . "` hkb
+ LEFT JOIN `" . t('oem_keys') . "` ok ON ok.id = hkb.product_key_id
ORDER BY hkb.bound_at DESC LIMIT 50
");
} else {
$stmt = $pdo->prepare("
SELECT hkb.*, ok.product_key, ok.oem_identifier AS product_type
- FROM hardware_key_bindings hkb
- LEFT JOIN oem_keys ok ON ok.id = hkb.product_key_id
+ FROM `" . t('hardware_key_bindings') . "` hkb
+ LEFT JOIN `" . t('oem_keys') . "` ok ON ok.id = hkb.product_key_id
WHERE " . implode(' AND ', $where) . "
ORDER BY hkb.bound_at DESC LIMIT 50
");
@@ -348,7 +348,7 @@ function handle_check_hardware_binding(PDO $pdo, array $admin_session, $json_inp
if ($keyId > 0) {
$conflictStmt = $pdo->prepare("
SELECT device_fingerprint, motherboard_serial, bound_at
- FROM hardware_key_bindings
+ FROM `" . t('hardware_key_bindings') . "`
WHERE product_key_id = ? AND status = 'active'
");
$conflictStmt->execute([$keyId]);
@@ -371,7 +371,7 @@ function handle_release_hardware_binding(PDO $pdo, array $admin_session, $json_i
}
$stmt = $pdo->prepare("
- UPDATE hardware_key_bindings
+ UPDATE `" . t('hardware_key_bindings') . "`
SET status = 'released', released_at = NOW(), released_by_admin_id = ?
WHERE id = ? AND status = 'active'
");
@@ -411,7 +411,7 @@ function handle_import_dpk_batch(PDO $pdo, array $admin_session): void {
// Create batch record
$batchStmt = $pdo->prepare("
- INSERT INTO dpk_import_batches
+ INSERT INTO `" . t('dpk_import_batches') . "`
(batch_name, import_source, product_edition, source_filename, source_checksum,
imported_by_admin_id, imported_by_username, import_status)
VALUES (?, ?, ?, ?, ?, ?, ?, 'processing')
@@ -446,9 +446,9 @@ function handle_import_dpk_batch(PDO $pdo, array $admin_session): void {
$duplicates = 0;
$failed = 0;
- $checkExisting = $pdo->prepare("SELECT COUNT(*) FROM oem_keys WHERE product_key = ?");
+ $checkExisting = $pdo->prepare("SELECT COUNT(*) FROM `" . t('oem_keys') . "` WHERE product_key = ?");
$insertKey = $pdo->prepare("
- INSERT INTO oem_keys (product_key, oem_identifier, key_status)
+ INSERT INTO `" . t('oem_keys') . "` (product_key, oem_identifier, key_status)
VALUES (?, ?, 'unused')
");
@@ -469,7 +469,7 @@ function handle_import_dpk_batch(PDO $pdo, array $admin_session): void {
// Update batch record
$pdo->prepare("
- UPDATE dpk_import_batches
+ UPDATE `" . t('dpk_import_batches') . "`
SET total_keys = ?, imported_keys = ?, duplicate_keys = ?, failed_keys = ?,
import_status = 'completed', completed_at = NOW()
WHERE id = ?
@@ -483,7 +483,7 @@ function handle_import_dpk_batch(PDO $pdo, array $admin_session): void {
// Update key pool replenishment timestamp
if ($productEdition && $imported > 0) {
$pdo->prepare("
- UPDATE key_pool_config SET last_replenished_at = NOW() WHERE product_edition = ?
+ UPDATE `" . t('key_pool_config') . "` SET last_replenished_at = NOW() WHERE product_edition = ?
")->execute([$productEdition]);
}
@@ -526,7 +526,7 @@ function parseDPKXml(string $content): array {
function handle_list_dpk_batches(PDO $pdo, array $admin_session, $json_input): void {
requirePermission('view_keys', $admin_session);
- $stmt = $pdo->query("SELECT * FROM dpk_import_batches ORDER BY created_at DESC LIMIT 50");
+ $stmt = $pdo->query("SELECT * FROM `" . t('dpk_import_batches') . "` ORDER BY created_at DESC LIMIT 50");
jsonResponse(['success' => true, 'batches' => $stmt->fetchAll(PDO::FETCH_ASSOC)]);
}
@@ -621,13 +621,13 @@ function handle_save_work_order(PDO $pdo, array $admin_session, $json_input): vo
}
$params[] = $id;
- $stmt = $pdo->prepare("UPDATE work_orders SET " . implode(', ', $sets) . " WHERE id = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('work_orders') . "` SET " . implode(', ', $sets) . " WHERE id = ?");
$stmt->execute($params);
} else {
$data['created_by_admin_id'] = (int)$admin_session['admin_id'];
$cols = array_keys($data);
$placeholders = array_fill(0, count($cols), '?');
- $stmt = $pdo->prepare("INSERT INTO work_orders (" . implode(',', $cols) . ") VALUES (" . implode(',', $placeholders) . ")");
+ $stmt = $pdo->prepare("INSERT INTO `" . t('work_orders') . "` (" . implode(',', $cols) . ") VALUES (" . implode(',', $placeholders) . ")");
$stmt->execute(array_values($data));
$id = (int)$pdo->lastInsertId();
}
@@ -646,7 +646,7 @@ function handle_get_work_order(PDO $pdo, array $admin_session, $json_input): voi
return;
}
- $stmt = $pdo->prepare("SELECT * FROM work_orders WHERE id = ?");
+ $stmt = $pdo->prepare("SELECT * FROM `" . t('work_orders') . "` WHERE id = ?");
$stmt->execute([$id]);
$order = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -659,7 +659,7 @@ function handle_get_work_order(PDO $pdo, array $admin_session, $json_input): voi
$cbrStmt = $pdo->prepare("
SELECT id, report_uuid, order_number, activation_status, shipping_status,
motherboard_model, cpu_model, created_at
- FROM computer_build_reports
+ FROM `" . t('computer_build_reports') . "`
WHERE work_order_id = ?
ORDER BY created_at ASC
");
@@ -679,7 +679,7 @@ function handle_delete_work_order(PDO $pdo, array $admin_session, $json_input):
}
// Only allow deleting draft/cancelled orders
- $check = $pdo->prepare("SELECT status, work_order_number FROM work_orders WHERE id = ?");
+ $check = $pdo->prepare("SELECT status, work_order_number FROM `" . t('work_orders') . "` WHERE id = ?");
$check->execute([$id]);
$row = $check->fetch();
@@ -692,7 +692,7 @@ function handle_delete_work_order(PDO $pdo, array $admin_session, $json_input):
return;
}
- $pdo->prepare("DELETE FROM work_orders WHERE id = ?")->execute([$id]);
+ $pdo->prepare("DELETE FROM `" . t('work_orders') . "` WHERE id = ?")->execute([$id]);
logAdminActivity($admin_session['admin_id'], $admin_session['id'] ?? 0, 'WORK_ORDER_DELETED', "Deleted work order: {$row['work_order_number']}");
diff --git a/FINAL_PRODUCTION_SYSTEM/controllers/admin/SecurityController.php b/FINAL_PRODUCTION_SYSTEM/controllers/admin/SecurityController.php
index dd3913d..718eaac 100644
--- a/FINAL_PRODUCTION_SYSTEM/controllers/admin/SecurityController.php
+++ b/FINAL_PRODUCTION_SYSTEM/controllers/admin/SecurityController.php
@@ -9,7 +9,7 @@ function handle_get_2fa_status(PDO $pdo, array $admin_session): void {
try {
$stmt = $pdo->prepare("
SELECT totp_enabled, verified_at, backup_codes
- FROM admin_totp_secrets
+ FROM `" . t('admin_totp_secrets') . "`
WHERE admin_id = ?
");
$stmt->execute([$admin_session['admin_id']]);
@@ -48,8 +48,8 @@ function handle_list_trusted_networks(PDO $pdo, array $admin_session): void {
$stmt = $pdo->query("
SELECT tn.*, au.username as created_by_username
- FROM trusted_networks tn
- LEFT JOIN admin_users au ON tn.created_by_admin_id = au.id
+ FROM `" . t('trusted_networks') . "` tn
+ LEFT JOIN `" . t('admin_users') . "` au ON tn.created_by_admin_id = au.id
ORDER BY tn.created_at DESC
");
$networks = $stmt->fetchAll(PDO::FETCH_ASSOC);
@@ -78,7 +78,7 @@ function handle_add_trusted_network(PDO $pdo, array $admin_session, ?array $json
}
$stmt = $pdo->prepare("
- INSERT INTO trusted_networks (
+ INSERT INTO `" . t('trusted_networks') . "` (
network_name, ip_range, bypass_2fa, allow_usb_auth, description, created_by_admin_id
) VALUES (?, ?, ?, ?, ?, ?)
");
@@ -99,7 +99,7 @@ function handle_delete_trusted_network(PDO $pdo, array $admin_session, ?array $j
$networkId = intval($json_input['network_id'] ?? 0);
- $stmt = $pdo->prepare("SELECT network_name FROM trusted_networks WHERE id = ?");
+ $stmt = $pdo->prepare("SELECT network_name FROM `" . t('trusted_networks') . "` WHERE id = ?");
$stmt->execute([$networkId]);
$network = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -108,7 +108,7 @@ function handle_delete_trusted_network(PDO $pdo, array $admin_session, ?array $j
return;
}
- $stmt = $pdo->prepare("DELETE FROM trusted_networks WHERE id = ?");
+ $stmt = $pdo->prepare("DELETE FROM `" . t('trusted_networks') . "` WHERE id = ?");
$stmt->execute([$networkId]);
logAdminActivity(
diff --git a/FINAL_PRODUCTION_SYSTEM/controllers/admin/TaskPipelineController.php b/FINAL_PRODUCTION_SYSTEM/controllers/admin/TaskPipelineController.php
index 6914b76..bc00b25 100644
--- a/FINAL_PRODUCTION_SYSTEM/controllers/admin/TaskPipelineController.php
+++ b/FINAL_PRODUCTION_SYSTEM/controllers/admin/TaskPipelineController.php
@@ -15,7 +15,7 @@ function handle_list_task_templates(PDO $pdo, array $admin_session, $json_input)
requirePermission('system_settings', $admin_session);
$stmt = $pdo->query("
- SELECT * FROM task_templates
+ SELECT * FROM `" . t('task_templates') . "`
ORDER BY is_system DESC, task_key ASC
");
@@ -54,13 +54,13 @@ function handle_save_task_template(PDO $pdo, array $admin_session, $json_input):
if ($id > 0) {
// Check not editing a system task's key/type
- $existing = $pdo->prepare("SELECT is_system FROM task_templates WHERE id = ?");
+ $existing = $pdo->prepare("SELECT is_system FROM `" . t('task_templates') . "` WHERE id = ?");
$existing->execute([$id]);
$row = $existing->fetch();
if ($row && $row['is_system']) {
// System tasks: only allow editing name, description, timeout, on_failure, icon
$stmt = $pdo->prepare("
- UPDATE task_templates
+ UPDATE `" . t('task_templates') . "`
SET task_name = ?, description = ?, default_timeout_seconds = ?,
default_on_failure = ?, icon = ?
WHERE id = ?
@@ -68,7 +68,7 @@ function handle_save_task_template(PDO $pdo, array $admin_session, $json_input):
$stmt->execute([$taskName, $description, $defaultTimeout, $defaultOnFailure, $icon, $id]);
} else {
$stmt = $pdo->prepare("
- UPDATE task_templates
+ UPDATE `" . t('task_templates') . "`
SET task_key = ?, task_name = ?, task_type = ?, description = ?,
default_code = ?, default_timeout_seconds = ?, default_on_failure = ?, icon = ?
WHERE id = ? AND is_system = 0
@@ -77,7 +77,7 @@ function handle_save_task_template(PDO $pdo, array $admin_session, $json_input):
}
} else {
$stmt = $pdo->prepare("
- INSERT INTO task_templates
+ INSERT INTO `" . t('task_templates') . "`
(task_key, task_name, task_type, description, default_code,
default_timeout_seconds, default_on_failure, is_system, icon)
VALUES (?, ?, ?, ?, ?, ?, ?, 0, ?)
@@ -101,7 +101,7 @@ function handle_delete_task_template(PDO $pdo, array $admin_session, $json_input
}
// Cannot delete system tasks
- $check = $pdo->prepare("SELECT is_system, task_key FROM task_templates WHERE id = ?");
+ $check = $pdo->prepare("SELECT is_system, task_key FROM `" . t('task_templates') . "` WHERE id = ?");
$check->execute([$id]);
$row = $check->fetch();
if (!$row) {
@@ -114,8 +114,8 @@ function handle_delete_task_template(PDO $pdo, array $admin_session, $json_input
}
// Remove from all product line assignments first
- $pdo->prepare("DELETE FROM product_line_tasks WHERE task_template_id = ?")->execute([$id]);
- $pdo->prepare("DELETE FROM task_templates WHERE id = ? AND is_system = 0")->execute([$id]);
+ $pdo->prepare("DELETE FROM `" . t('product_line_tasks') . "` WHERE task_template_id = ?")->execute([$id]);
+ $pdo->prepare("DELETE FROM `" . t('task_templates') . "` WHERE id = ? AND is_system = 0")->execute([$id]);
logAdminActivity($admin_session['admin_id'], $admin_session['id'] ?? 0, 'TASK_TEMPLATE_DELETED', "Deleted task template: {$row['task_key']} (#{$id})");
@@ -137,8 +137,8 @@ function handle_get_product_line_tasks(PDO $pdo, array $admin_session, $json_inp
SELECT plt.*, tt.task_key, tt.task_name AS template_name, tt.task_type,
tt.description AS template_description, tt.default_code,
tt.default_timeout_seconds, tt.default_on_failure, tt.is_system, tt.icon
- FROM product_line_tasks plt
- JOIN task_templates tt ON tt.id = plt.task_template_id
+ FROM `" . t('product_line_tasks') . "` plt
+ JOIN `" . t('task_templates') . "` tt ON tt.id = plt.task_template_id
WHERE plt.product_line_id = ?
ORDER BY plt.sort_order ASC
");
@@ -165,11 +165,11 @@ function handle_save_product_line_tasks(PDO $pdo, array $admin_session, $json_in
$pdo->beginTransaction();
try {
// Remove existing assignments
- $pdo->prepare("DELETE FROM product_line_tasks WHERE product_line_id = ?")->execute([$productLineId]);
+ $pdo->prepare("DELETE FROM `" . t('product_line_tasks') . "` WHERE product_line_id = ?")->execute([$productLineId]);
// Insert new assignments in order
$insertStmt = $pdo->prepare("
- INSERT INTO product_line_tasks
+ INSERT INTO `" . t('product_line_tasks') . "`
(product_line_id, task_template_id, sort_order, enabled,
custom_name, custom_code, custom_timeout_seconds, custom_on_failure)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
@@ -246,7 +246,7 @@ function handle_get_activation_pipeline(PDO $pdo, array $admin_session, $json_in
SELECT id AS task_template_id, task_key, task_name, task_type,
default_code AS code, default_timeout_seconds AS timeout_seconds,
default_on_failure AS on_failure, 1 AS enabled
- FROM task_templates
+ FROM `" . t('task_templates') . "`
WHERE is_system = 1
ORDER BY id ASC
");
@@ -263,8 +263,8 @@ function handle_get_activation_pipeline(PDO $pdo, array $admin_session, $json_in
COALESCE(plt.custom_timeout_seconds, tt.default_timeout_seconds) AS timeout_seconds,
COALESCE(plt.custom_on_failure, tt.default_on_failure) AS on_failure,
plt.enabled
- FROM product_line_tasks plt
- JOIN task_templates tt ON tt.id = plt.task_template_id
+ FROM `" . t('product_line_tasks') . "` plt
+ JOIN `" . t('task_templates') . "` tt ON tt.id = plt.task_template_id
WHERE plt.product_line_id = ? AND plt.enabled = 1
ORDER BY plt.sort_order ASC
");
@@ -277,7 +277,7 @@ function handle_get_activation_pipeline(PDO $pdo, array $admin_session, $json_in
SELECT id AS task_template_id, task_key, task_name, task_type,
default_code AS code, default_timeout_seconds AS timeout_seconds,
default_on_failure AS on_failure, 1 AS enabled
- FROM task_templates
+ FROM `" . t('task_templates') . "`
WHERE is_system = 1
ORDER BY id ASC
");
@@ -297,7 +297,7 @@ function handle_log_task_execution(PDO $pdo, array $admin_session, $json_input):
}
$stmt = $pdo->prepare("
- INSERT INTO task_execution_log
+ INSERT INTO `" . t('task_execution_log') . "`
(activation_attempt_id, product_line_id, task_template_id, task_key,
task_name, status, started_at, completed_at, duration_ms,
output, error_message, technician_id, order_number)
diff --git a/FINAL_PRODUCTION_SYSTEM/controllers/admin/TechniciansController.php b/FINAL_PRODUCTION_SYSTEM/controllers/admin/TechniciansController.php
index 9980625..8ab6659 100644
--- a/FINAL_PRODUCTION_SYSTEM/controllers/admin/TechniciansController.php
+++ b/FINAL_PRODUCTION_SYSTEM/controllers/admin/TechniciansController.php
@@ -54,7 +54,7 @@ function handle_list_technicians(PDO $pdo, array $admin_session): void {
$stmt = $pdo->query("
SELECT id, technician_id, full_name, email, is_active
- FROM technicians
+ FROM `" . t('technicians') . "`
ORDER BY full_name ASC
");
$technicians = $stmt->fetchAll(PDO::FETCH_ASSOC);
@@ -92,7 +92,7 @@ function handle_add_tech(PDO $pdo, array $admin_session): void {
$pdo->beginTransaction();
// Check + insert inside transaction to prevent TOCTOU race condition
- $stmt = $pdo->prepare("SELECT COUNT(*) FROM technicians WHERE technician_id = ?");
+ $stmt = $pdo->prepare("SELECT COUNT(*) FROM `" . t('technicians') . "` WHERE technician_id = ?");
$stmt->execute([$tech_id]);
if ($stmt->fetchColumn() > 0) {
$pdo->rollBack();
@@ -101,7 +101,7 @@ function handle_add_tech(PDO $pdo, array $admin_session): void {
}
$stmt = $pdo->prepare("
- INSERT INTO technicians (technician_id, password_hash, full_name, email, is_active, preferred_language)
+ INSERT INTO `" . t('technicians') . "` (technician_id, password_hash, full_name, email, is_active, preferred_language)
VALUES (?, ?, ?, ?, ?, ?)
");
$stmt->execute([$tech_id, $password_hash, $full_name, $email, $is_active, $preferred_language]);
@@ -136,7 +136,7 @@ function handle_edit_tech(PDO $pdo, array $admin_session): void {
$is_active = isset($_POST['is_active']) ? 1 : 0;
$stmt = $pdo->prepare("
- UPDATE technicians
+ UPDATE `" . t('technicians') . "`
SET full_name = ?, email = ?, is_active = ?
WHERE id = ?
");
@@ -161,7 +161,7 @@ function handle_get_tech(PDO $pdo, array $admin_session): void {
$stmt = $pdo->prepare("
SELECT id, technician_id, full_name, email, is_active, preferred_server, preferred_language
- FROM technicians
+ FROM `" . t('technicians') . "`
WHERE id = ?
");
$stmt->execute([$techId]);
@@ -200,7 +200,7 @@ function handle_update_tech(PDO $pdo, array $admin_session, ?array $json_input =
}
$stmt = $pdo->prepare("
- UPDATE technicians
+ UPDATE `" . t('technicians') . "`
SET full_name = ?, email = ?, preferred_language = ?, is_active = ?
WHERE id = ?
");
@@ -230,7 +230,7 @@ function handle_reset_password(PDO $pdo, array $admin_session): void {
$password_hash = password_hash($new_password, PASSWORD_BCRYPT, ['cost' => BCRYPT_COST]);
$stmt = $pdo->prepare("
- UPDATE technicians
+ UPDATE `" . t('technicians') . "`
SET password_hash = ?, must_change_password = 1
WHERE id = ?
");
@@ -252,7 +252,7 @@ function handle_toggle_tech(PDO $pdo, array $admin_session): void {
$id = intval($_POST['id'] ?? 0);
$stmt = $pdo->prepare("
- UPDATE technicians
+ UPDATE `" . t('technicians') . "`
SET is_active = NOT is_active
WHERE id = ?
");
@@ -273,7 +273,7 @@ function handle_delete_tech(PDO $pdo, array $admin_session): void {
$id = intval($_POST['id'] ?? 0);
- $stmt = $pdo->prepare("DELETE FROM technicians WHERE id = ?");
+ $stmt = $pdo->prepare("DELETE FROM `" . t('technicians') . "` WHERE id = ?");
$stmt->execute([$id]);
logAdminActivity(
diff --git a/FINAL_PRODUCTION_SYSTEM/controllers/admin/UpgradeController.php b/FINAL_PRODUCTION_SYSTEM/controllers/admin/UpgradeController.php
index 0129469..7325a9c 100644
--- a/FINAL_PRODUCTION_SYSTEM/controllers/admin/UpgradeController.php
+++ b/FINAL_PRODUCTION_SYSTEM/controllers/admin/UpgradeController.php
@@ -34,7 +34,7 @@ function getBackupDir(): string {
}
function loadUpgradeRow(PDO $pdo, int $upgradeId): ?array {
- $stmt = $pdo->prepare("SELECT * FROM upgrade_history WHERE id = ?");
+ $stmt = $pdo->prepare("SELECT * FROM `" . t('upgrade_history') . "` WHERE id = ?");
$stmt->execute([$upgradeId]);
return $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
}
@@ -47,7 +47,7 @@ function updateUpgradeStatus(PDO $pdo, int $id, string $status, array $extra = [
$params[] = $val;
}
$params[] = $id;
- $sql = "UPDATE upgrade_history SET " . implode(', ', $sets) . " WHERE id = ?";
+ $sql = "UPDATE `" . t('upgrade_history') . "` SET " . implode(', ', $sets) . " WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
}
@@ -275,7 +275,7 @@ function handle_upgrade_download_github(PDO $pdo, array $admin_session, $json_in
// Check no active upgrade
$stmt = $pdo->prepare("
- SELECT id, status FROM upgrade_history
+ SELECT id, status FROM `" . t('upgrade_history') . "`
WHERE status NOT IN ('completed', 'failed', 'rolled_back')
LIMIT 1
");
@@ -368,7 +368,7 @@ function handle_upgrade_download_github(PDO $pdo, array $admin_session, $json_in
// Create upgrade_history row
$stmt = $pdo->prepare("
- INSERT INTO upgrade_history
+ INSERT INTO `" . t('upgrade_history') . "`
(from_version, to_version, from_version_code, to_version_code,
status, manifest_json, package_filename, package_checksum,
admin_id, admin_username)
@@ -416,7 +416,7 @@ function handle_upgrade_get_status(PDO $pdo, array $admin_session, $json_input):
// Active (non-terminal) upgrade
$stmt = $pdo->query("
- SELECT * FROM upgrade_history
+ SELECT * FROM `" . t('upgrade_history') . "`
WHERE status NOT IN ('completed', 'failed', 'rolled_back')
ORDER BY created_at DESC LIMIT 1
");
@@ -427,7 +427,7 @@ function handle_upgrade_get_status(PDO $pdo, array $admin_session, $json_input):
SELECT id, from_version, to_version, status, package_filename,
error_message, started_at, completed_at, rolled_back_at,
admin_username, created_at
- FROM upgrade_history
+ FROM `" . t('upgrade_history') . "`
ORDER BY created_at DESC LIMIT 10
");
$recentUpgrades = $stmt2->fetchAll(PDO::FETCH_ASSOC);
@@ -511,7 +511,7 @@ function handle_upgrade_upload_package(PDO $pdo, array $admin_session): void {
// Check no active upgrade in progress
$stmt = $pdo->prepare("
- SELECT id, status FROM upgrade_history
+ SELECT id, status FROM `" . t('upgrade_history') . "`
WHERE status NOT IN ('completed', 'failed', 'rolled_back')
LIMIT 1
");
@@ -536,7 +536,7 @@ function handle_upgrade_upload_package(PDO $pdo, array $admin_session): void {
// Create upgrade_history row
$stmt = $pdo->prepare("
- INSERT INTO upgrade_history
+ INSERT INTO `" . t('upgrade_history') . "`
(from_version, to_version, from_version_code, to_version_code,
status, manifest_json, package_filename, package_checksum,
admin_id, admin_username)
@@ -859,7 +859,7 @@ function handle_upgrade_apply(PDO $pdo, array $admin_session, $json_input): void
// Lock the row to prevent concurrent execution
$pdo->beginTransaction();
- $lockStmt = $pdo->prepare("SELECT id FROM upgrade_history WHERE id = ? FOR UPDATE");
+ $lockStmt = $pdo->prepare("SELECT id FROM `" . t('upgrade_history') . "` WHERE id = ? FOR UPDATE");
$lockStmt->execute([$upgradeId]);
$lockStmt->closeCursor();
$pdo->commit();
@@ -899,7 +899,7 @@ function handle_upgrade_apply(PDO $pdo, array $admin_session, $json_input): void
$migVersion = (int)($mig['version'] ?? 0);
// Check if already applied
- $checkStmt = $pdo->prepare("SELECT COUNT(*) FROM schema_versions WHERE filename = ?");
+ $checkStmt = $pdo->prepare("SELECT COUNT(*) FROM `" . t('schema_versions') . "` WHERE filename = ?");
$checkStmt->execute([basename($migFile)]);
$alreadyApplied = (int)$checkStmt->fetchColumn() > 0;
$checkStmt->closeCursor();
@@ -945,7 +945,7 @@ function handle_upgrade_apply(PDO $pdo, array $admin_session, $json_input): void
// Record in schema_versions
$checksum = hash('sha256', $migContent);
- $svStmt = $pdo->prepare("INSERT INTO schema_versions (version, filename, checksum) VALUES (?, ?, ?)");
+ $svStmt = $pdo->prepare("INSERT INTO `" . t('schema_versions') . "` (version, filename, checksum) VALUES (?, ?, ?)");
$svStmt->execute([$migVersion, basename($migFile), $checksum]);
$svStmt->closeCursor();
@@ -1327,7 +1327,7 @@ function handle_upgrade_rollback(PDO $pdo, array $admin_session, $json_input): v
);
$freshPdo->prepare("
- INSERT INTO upgrade_history
+ INSERT INTO `" . t('upgrade_history') . "`
(from_version, to_version, status, error_message,
admin_id, admin_username, rolled_back_at)
VALUES (?, ?, 'rolled_back', ?, ?, ?, ?)
@@ -1363,7 +1363,7 @@ function handle_upgrade_history(PDO $pdo, array $admin_session, $json_input): vo
status, package_filename, error_message,
started_at, completed_at, rolled_back_at,
admin_id, admin_username, created_at
- FROM upgrade_history
+ FROM `" . t('upgrade_history') . "`
ORDER BY created_at DESC
LIMIT 50
");
diff --git a/FINAL_PRODUCTION_SYSTEM/controllers/admin/UsbDevicesController.php b/FINAL_PRODUCTION_SYSTEM/controllers/admin/UsbDevicesController.php
index 888e86e..ad824f1 100644
--- a/FINAL_PRODUCTION_SYSTEM/controllers/admin/UsbDevicesController.php
+++ b/FINAL_PRODUCTION_SYSTEM/controllers/admin/UsbDevicesController.php
@@ -43,7 +43,7 @@ function handle_list_usb_devices(PDO $pdo, array $admin_session): void {
// Get USB device statistics
$stmt = $pdo->query("
SELECT device_status, COUNT(*) as count
- FROM usb_devices
+ FROM `" . t('usb_devices') . "`
GROUP BY device_status
");
$statusCounts = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
@@ -79,7 +79,7 @@ function handle_register_usb_device(PDO $pdo, array $admin_session, ?array $json
}
// Check if technician exists and is active
- $stmt = $pdo->prepare("SELECT technician_id, is_active FROM technicians WHERE technician_id = ?");
+ $stmt = $pdo->prepare("SELECT technician_id, is_active FROM `" . t('technicians') . "` WHERE technician_id = ?");
$stmt->execute([$technicianId]);
$technician = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -94,7 +94,7 @@ function handle_register_usb_device(PDO $pdo, array $admin_session, ?array $json
}
// Check if serial number already exists
- $stmt = $pdo->prepare("SELECT device_id, device_name FROM usb_devices WHERE device_serial_number = ?");
+ $stmt = $pdo->prepare("SELECT device_id, device_name FROM `" . t('usb_devices') . "` WHERE device_serial_number = ?");
$stmt->execute([$deviceSerial]);
$existingDevice = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -109,7 +109,7 @@ function handle_register_usb_device(PDO $pdo, array $admin_session, ?array $json
// Check max devices per technician limit
$maxDevices = (int)getConfig('usb_auth_max_devices_per_tech');
if ($maxDevices > 0) {
- $stmt = $pdo->prepare("SELECT COUNT(*) FROM usb_devices WHERE technician_id = ? AND device_status = 'active'");
+ $stmt = $pdo->prepare("SELECT COUNT(*) FROM `" . t('usb_devices') . "` WHERE technician_id = ? AND device_status = 'active'");
$stmt->execute([$technicianId]);
$currentCount = $stmt->fetchColumn();
@@ -124,7 +124,7 @@ function handle_register_usb_device(PDO $pdo, array $admin_session, ?array $json
// Insert new USB device
$stmt = $pdo->prepare("
- INSERT INTO usb_devices (
+ INSERT INTO `" . t('usb_devices') . "` (
device_serial_number, device_name, technician_id,
device_manufacturer, device_model, device_capacity_gb,
device_description, registered_by_admin_id
@@ -166,7 +166,7 @@ function handle_update_usb_device_status(PDO $pdo, array $admin_session, ?array
}
// Get device info before update
- $stmt = $pdo->prepare("SELECT device_name, technician_id FROM usb_devices WHERE device_id = ?");
+ $stmt = $pdo->prepare("SELECT device_name, technician_id FROM `" . t('usb_devices') . "` WHERE device_id = ?");
$stmt->execute([$deviceId]);
$device = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -178,7 +178,7 @@ function handle_update_usb_device_status(PDO $pdo, array $admin_session, ?array
// Update device status
if ($newStatus === 'active') {
$stmt = $pdo->prepare("
- UPDATE usb_devices
+ UPDATE `" . t('usb_devices') . "`
SET device_status = 'active',
disabled_date = NULL,
disabled_by_admin_id = NULL,
@@ -190,7 +190,7 @@ function handle_update_usb_device_status(PDO $pdo, array $admin_session, ?array
$disableReason = $json_input['reason'] ?? null;
$stmt = $pdo->prepare("
- UPDATE usb_devices
+ UPDATE `" . t('usb_devices') . "`
SET device_status = ?,
disabled_date = NOW(),
disabled_by_admin_id = ?,
@@ -218,7 +218,7 @@ function handle_delete_usb_device(PDO $pdo, array $admin_session, ?array $json_i
$deviceId = intval($json_input['device_id'] ?? 0);
- $stmt = $pdo->prepare("SELECT device_name, technician_id FROM usb_devices WHERE device_id = ?");
+ $stmt = $pdo->prepare("SELECT device_name, technician_id FROM `" . t('usb_devices') . "` WHERE device_id = ?");
$stmt->execute([$deviceId]);
$device = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -227,7 +227,7 @@ function handle_delete_usb_device(PDO $pdo, array $admin_session, ?array $json_i
return;
}
- $stmt = $pdo->prepare("DELETE FROM usb_devices WHERE device_id = ?");
+ $stmt = $pdo->prepare("DELETE FROM `" . t('usb_devices') . "` WHERE device_id = ?");
$stmt->execute([$deviceId]);
logAdminActivity(
diff --git a/FINAL_PRODUCTION_SYSTEM/database/2fa_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/2fa_migration.sql
index 1f27a42..fc1fae9 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/2fa_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/2fa_migration.sql
@@ -6,7 +6,7 @@
-- Table: admin_totp_secrets
-- Stores TOTP secrets and backup codes for admin 2FA
-CREATE TABLE IF NOT EXISTS `admin_totp_secrets` (
+CREATE TABLE IF NOT EXISTS `#__admin_totp_secrets` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`admin_id` INT NOT NULL COMMENT 'Reference to admin_users.id',
`totp_secret` VARCHAR(255) NOT NULL COMMENT 'Base32 encoded TOTP secret',
@@ -18,12 +18,12 @@ CREATE TABLE IF NOT EXISTS `admin_totp_secrets` (
UNIQUE KEY `idx_admin_id` (`admin_id`),
INDEX `idx_enabled` (`totp_enabled`),
- FOREIGN KEY (`admin_id`) REFERENCES `admin_users`(`id`) ON DELETE CASCADE
+ FOREIGN KEY (`admin_id`) REFERENCES `#__admin_users`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='TOTP 2FA secrets for admin accounts';
-- Table: trusted_networks
-- Defines network subnets that are trusted for security bypasses
-CREATE TABLE IF NOT EXISTS `trusted_networks` (
+CREATE TABLE IF NOT EXISTS `#__trusted_networks` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`network_name` VARCHAR(100) NOT NULL COMMENT 'Friendly name (e.g., "Office LAN")',
`ip_range` VARCHAR(45) NOT NULL COMMENT 'CIDR notation (e.g., 192.168.1.0/24)',
@@ -38,12 +38,12 @@ CREATE TABLE IF NOT EXISTS `trusted_networks` (
INDEX `idx_active` (`is_active`),
INDEX `idx_bypass_2fa` (`bypass_2fa`, `is_active`),
INDEX `idx_usb_auth` (`allow_usb_auth`, `is_active`),
- FOREIGN KEY (`created_by_admin_id`) REFERENCES `admin_users`(`id`) ON DELETE SET NULL
+ FOREIGN KEY (`created_by_admin_id`) REFERENCES `#__admin_users`(`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Trusted network subnets for security features';
-- Modify: admin_activity_log
-- Add columns to track 2FA usage and trusted network bypasses
-ALTER TABLE `admin_activity_log`
+ALTER TABLE `#__admin_activity_log`
ADD COLUMN IF NOT EXISTS `totp_verified` TINYINT(1) NULL COMMENT '1=2FA used, 0=bypassed, NULL=not applicable' AFTER `user_agent`,
ADD COLUMN IF NOT EXISTS `trusted_network_id` INT NULL COMMENT 'If bypassed, which network' AFTER `totp_verified`,
ADD INDEX IF NOT EXISTS `idx_totp_verified` (`totp_verified`);
@@ -55,8 +55,8 @@ SET @fk_exists = (SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
AND CONSTRAINT_NAME = 'fk_admin_activity_log_trusted_network');
SET @sql = IF(@fk_exists = 0,
- 'ALTER TABLE `admin_activity_log` ADD CONSTRAINT `fk_admin_activity_log_trusted_network`
- FOREIGN KEY (`trusted_network_id`) REFERENCES `trusted_networks`(`id`) ON DELETE SET NULL',
+ 'ALTER TABLE `#__admin_activity_log` ADD CONSTRAINT `fk_admin_activity_log_trusted_network`
+ FOREIGN KEY (`trusted_network_id`) REFERENCES `#__trusted_networks`(`id`) ON DELETE SET NULL',
'SELECT "Foreign key already exists"');
PREPARE stmt FROM @sql;
@@ -64,7 +64,7 @@ EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- System configuration for 2FA features
-INSERT INTO `system_config` (`config_key`, `config_value`, `description`) VALUES
+INSERT INTO `#__system_config` (`config_key`, `config_value`, `description`) VALUES
('totp_2fa_available', '1', 'Enable TOTP 2FA feature (1=yes, 0=no)'),
('totp_issuer_name', 'OEM Activation System', 'TOTP issuer name shown in authenticator app'),
('totp_backup_codes_count', '10', 'Number of backup codes to generate per user'),
diff --git a/FINAL_PRODUCTION_SYSTEM/database/acl_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/acl_migration.sql
index 1390bf4..d5fd64f 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/acl_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/acl_migration.sql
@@ -10,7 +10,7 @@
-- ============================================================
-- Permission Categories (groups permissions for UI accordion)
-CREATE TABLE IF NOT EXISTS acl_permission_categories (
+CREATE TABLE IF NOT EXISTS `#__acl_permission_categories` (
id INT AUTO_INCREMENT PRIMARY KEY,
category_key VARCHAR(50) NOT NULL UNIQUE,
display_name VARCHAR(100) NOT NULL,
@@ -19,7 +19,7 @@ CREATE TABLE IF NOT EXISTS acl_permission_categories (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Granular Permissions
-CREATE TABLE IF NOT EXISTS acl_permissions (
+CREATE TABLE IF NOT EXISTS `#__acl_permissions` (
id INT AUTO_INCREMENT PRIMARY KEY,
permission_key VARCHAR(100) NOT NULL UNIQUE,
display_name VARCHAR(100) NOT NULL,
@@ -28,13 +28,13 @@ CREATE TABLE IF NOT EXISTS acl_permissions (
resource_type VARCHAR(50) NOT NULL,
action_type ENUM('view','create','edit','delete','manage','execute') NOT NULL,
is_dangerous TINYINT(1) DEFAULT 0 COMMENT 'Requires confirmation / shown with warning',
- FOREIGN KEY (category_id) REFERENCES acl_permission_categories(id),
+ FOREIGN KEY (category_id) REFERENCES `#__acl_permission_categories`(id),
INDEX idx_resource (resource_type),
INDEX idx_category (category_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Custom Roles
-CREATE TABLE IF NOT EXISTS acl_roles (
+CREATE TABLE IF NOT EXISTS `#__acl_roles` (
id INT AUTO_INCREMENT PRIMARY KEY,
role_name VARCHAR(50) NOT NULL UNIQUE,
display_name VARCHAR(100) NOT NULL,
@@ -51,19 +51,19 @@ CREATE TABLE IF NOT EXISTS acl_roles (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Role <-> Permission Junction
-CREATE TABLE IF NOT EXISTS acl_role_permissions (
+CREATE TABLE IF NOT EXISTS `#__acl_role_permissions` (
id INT AUTO_INCREMENT PRIMARY KEY,
role_id INT NOT NULL,
permission_id INT NOT NULL,
granted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
granted_by INT NULL,
UNIQUE KEY unique_role_perm (role_id, permission_id),
- FOREIGN KEY (role_id) REFERENCES acl_roles(id) ON DELETE CASCADE,
- FOREIGN KEY (permission_id) REFERENCES acl_permissions(id) ON DELETE CASCADE
+ FOREIGN KEY (role_id) REFERENCES `#__acl_roles`(id) ON DELETE CASCADE,
+ FOREIGN KEY (permission_id) REFERENCES `#__acl_permissions`(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Per-User Permission Overrides
-CREATE TABLE IF NOT EXISTS acl_user_overrides (
+CREATE TABLE IF NOT EXISTS `#__acl_user_overrides` (
id INT AUTO_INCREMENT PRIMARY KEY,
user_type ENUM('admin','technician') NOT NULL,
user_id INT NOT NULL,
@@ -74,13 +74,13 @@ CREATE TABLE IF NOT EXISTS acl_user_overrides (
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_by INT NULL,
UNIQUE KEY unique_user_perm (user_type, user_id, permission_id),
- FOREIGN KEY (permission_id) REFERENCES acl_permissions(id) ON DELETE CASCADE,
+ FOREIGN KEY (permission_id) REFERENCES `#__acl_permissions`(id) ON DELETE CASCADE,
INDEX idx_user (user_type, user_id),
INDEX idx_expires (expires_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ACL Change Audit Log
-CREATE TABLE IF NOT EXISTS acl_change_log (
+CREATE TABLE IF NOT EXISTS `#__acl_change_log` (
id INT AUTO_INCREMENT PRIMARY KEY,
actor_id INT NOT NULL,
actor_type ENUM('admin','system') DEFAULT 'admin',
@@ -102,15 +102,15 @@ CREATE TABLE IF NOT EXISTS acl_change_log (
-- ============================================================
-- Add custom_role_id to admin_users (links to acl_roles for new ACL)
-ALTER TABLE admin_users ADD COLUMN custom_role_id INT NULL AFTER role;
-ALTER TABLE admin_users ADD CONSTRAINT fk_admin_acl_role FOREIGN KEY (custom_role_id) REFERENCES acl_roles(id) ON DELETE SET NULL;
+ALTER TABLE `#__admin_users` ADD COLUMN custom_role_id INT NULL AFTER role;
+ALTER TABLE `#__admin_users` ADD CONSTRAINT fk_admin_acl_role FOREIGN KEY (custom_role_id) REFERENCES `#__acl_roles`(id) ON DELETE SET NULL;
-- Add role_id to technicians (links to acl_roles for technician roles)
-ALTER TABLE technicians ADD COLUMN role_id INT NULL AFTER is_active;
-ALTER TABLE technicians ADD CONSTRAINT fk_tech_acl_role FOREIGN KEY (role_id) REFERENCES acl_roles(id) ON DELETE SET NULL;
+ALTER TABLE `#__technicians` ADD COLUMN role_id INT NULL AFTER is_active;
+ALTER TABLE `#__technicians` ADD CONSTRAINT fk_tech_acl_role FOREIGN KEY (role_id) REFERENCES `#__acl_roles`(id) ON DELETE SET NULL;
-- Add acl_v2_enabled config flag (disabled by default for safety)
-INSERT INTO system_config (config_key, config_value, description)
+INSERT INTO `#__system_config` (config_key, config_value, description)
VALUES ('acl_v2_enabled', '0', 'Enable database-driven ACL system (0=legacy hardcoded, 1=new ACL)')
ON DUPLICATE KEY UPDATE config_key = config_key;
@@ -118,7 +118,7 @@ ON DUPLICATE KEY UPDATE config_key = config_key;
-- SEED: Permission Categories
-- ============================================================
-INSERT INTO acl_permission_categories (category_key, display_name, icon, sort_order) VALUES
+INSERT INTO `#__acl_permission_categories` (category_key, display_name, icon, sort_order) VALUES
('dashboard', 'Dashboard & Reports', NULL, 10),
('keys', 'OEM Key Management', NULL, 20),
('technicians', 'Technician Management', NULL, 30),
@@ -134,7 +134,7 @@ INSERT INTO acl_permission_categories (category_key, display_name, icon, sort_or
-- SEED: Granular Permissions (~38)
-- ============================================================
-INSERT INTO acl_permissions (permission_key, display_name, description, category_id, resource_type, action_type, is_dangerous) VALUES
+INSERT INTO `#__acl_permissions` (permission_key, display_name, description, category_id, resource_type, action_type, is_dangerous) VALUES
-- Dashboard (cat 1)
('view_dashboard', 'View Dashboard', 'Access the main dashboard with statistics', 1, 'dashboard', 'view', 0),
('view_reports', 'View Reports', 'Access activation and usage reports', 1, 'dashboard', 'view', 0),
@@ -199,7 +199,7 @@ INSERT INTO acl_permissions (permission_key, display_name, description, category
-- SEED: Roles (7 admin + 2 technician)
-- ============================================================
-INSERT INTO acl_roles (role_name, display_name, description, role_type, is_system_role, priority, color) VALUES
+INSERT INTO `#__acl_roles` (role_name, display_name, description, role_type, is_system_role, priority, color) VALUES
-- Admin roles
('super_admin', 'Super Administrator', 'Full system access including admin management, system settings, backups, and role management', 'admin', 1, 100, '#dc3545'),
('admin', 'Administrator', 'All data operations except delete, admin management, and system settings', 'admin', 1, 80, '#007bff'),
@@ -218,15 +218,15 @@ INSERT INTO acl_roles (role_name, display_name, description, role_type, is_syste
-- Helper: Get role and permission IDs for assignment
-- super_admin: ALL permissions
-INSERT INTO acl_role_permissions (role_id, permission_id)
+INSERT INTO `#__acl_role_permissions` (role_id, permission_id)
SELECT r.id, p.id
-FROM acl_roles r CROSS JOIN acl_permissions p
+FROM `#__acl_roles` r CROSS JOIN `#__acl_permissions` p
WHERE r.role_name = 'super_admin';
-- admin: All view + edit/create operations, NO delete, NO admin mgmt, NO system settings, NO role mgmt
-INSERT INTO acl_role_permissions (role_id, permission_id)
+INSERT INTO `#__acl_role_permissions` (role_id, permission_id)
SELECT r.id, p.id
-FROM acl_roles r, acl_permissions p
+FROM `#__acl_roles` r, acl_permissions p
WHERE r.role_name = 'admin' AND p.permission_key IN (
'view_dashboard', 'view_reports', 'export_data',
'view_keys', 'add_key', 'import_keys', 'edit_key', 'recycle_key',
@@ -239,9 +239,9 @@ WHERE r.role_name = 'admin' AND p.permission_key IN (
);
-- billing_manager: Dashboard, keys (view only), activations (view), reports, export, logs
-INSERT INTO acl_role_permissions (role_id, permission_id)
+INSERT INTO `#__acl_role_permissions` (role_id, permission_id)
SELECT r.id, p.id
-FROM acl_roles r, acl_permissions p
+FROM `#__acl_roles` r, acl_permissions p
WHERE r.role_name = 'billing_manager' AND p.permission_key IN (
'view_dashboard', 'view_reports', 'export_data',
'view_keys',
@@ -250,9 +250,9 @@ WHERE r.role_name = 'billing_manager' AND p.permission_key IN (
);
-- hr_manager: Dashboard, technician CRUD, password reset, role assignment
-INSERT INTO acl_role_permissions (role_id, permission_id)
+INSERT INTO `#__acl_role_permissions` (role_id, permission_id)
SELECT r.id, p.id
-FROM acl_roles r, acl_permissions p
+FROM `#__acl_roles` r, acl_permissions p
WHERE r.role_name = 'hr_manager' AND p.permission_key IN (
'view_dashboard',
'view_technicians', 'add_technician', 'edit_technician', 'reset_tech_password', 'assign_tech_role',
@@ -260,9 +260,9 @@ WHERE r.role_name = 'hr_manager' AND p.permission_key IN (
);
-- qc_inspector: View activations, hardware, add notes, export
-INSERT INTO acl_role_permissions (role_id, permission_id)
+INSERT INTO `#__acl_role_permissions` (role_id, permission_id)
SELECT r.id, p.id
-FROM acl_roles r, acl_permissions p
+FROM `#__acl_roles` r, acl_permissions p
WHERE r.role_name = 'qc_inspector' AND p.permission_key IN (
'view_dashboard', 'view_reports', 'export_data',
'view_activations', 'add_activation_note',
@@ -270,9 +270,9 @@ WHERE r.role_name = 'qc_inspector' AND p.permission_key IN (
);
-- dept_manager: View technicians, activations, hardware, dashboard, add notes
-INSERT INTO acl_role_permissions (role_id, permission_id)
+INSERT INTO `#__acl_role_permissions` (role_id, permission_id)
SELECT r.id, p.id
-FROM acl_roles r, acl_permissions p
+FROM `#__acl_roles` r, acl_permissions p
WHERE r.role_name = 'dept_manager' AND p.permission_key IN (
'view_dashboard', 'view_reports', 'export_data',
'view_technicians',
@@ -282,9 +282,9 @@ WHERE r.role_name = 'dept_manager' AND p.permission_key IN (
);
-- viewer: Read-only across the board
-INSERT INTO acl_role_permissions (role_id, permission_id)
+INSERT INTO `#__acl_role_permissions` (role_id, permission_id)
SELECT r.id, p.id
-FROM acl_roles r, acl_permissions p
+FROM `#__acl_roles` r, acl_permissions p
WHERE r.role_name = 'viewer' AND p.permission_key IN (
'view_dashboard', 'view_reports', 'export_data',
'view_keys',
@@ -297,17 +297,17 @@ WHERE r.role_name = 'viewer' AND p.permission_key IN (
);
-- technician_full: Can activate, submit hardware
-INSERT INTO acl_role_permissions (role_id, permission_id)
+INSERT INTO `#__acl_role_permissions` (role_id, permission_id)
SELECT r.id, p.id
-FROM acl_roles r, acl_permissions p
+FROM `#__acl_roles` r, acl_permissions p
WHERE r.role_name = 'technician_full' AND p.permission_key IN (
'view_keys', 'view_activations', 'view_hardware'
);
-- technician_limited: View only
-INSERT INTO acl_role_permissions (role_id, permission_id)
+INSERT INTO `#__acl_role_permissions` (role_id, permission_id)
SELECT r.id, p.id
-FROM acl_roles r, acl_permissions p
+FROM `#__acl_roles` r, acl_permissions p
WHERE r.role_name = 'technician_limited' AND p.permission_key IN (
'view_keys'
);
@@ -317,6 +317,6 @@ WHERE r.role_name = 'technician_limited' AND p.permission_key IN (
-- Map legacy role ENUM to new custom_role_id
-- ============================================================
-UPDATE admin_users au
-INNER JOIN acl_roles ar ON ar.role_name COLLATE utf8mb4_general_ci = au.role COLLATE utf8mb4_general_ci AND ar.role_type = 'admin'
+UPDATE `#__admin_users` au
+INNER JOIN `#__acl_roles` ar ON ar.role_name COLLATE utf8mb4_general_ci = au.role COLLATE utf8mb4_general_ci AND ar.role_type = 'admin'
SET au.custom_role_id = ar.id;
diff --git a/FINAL_PRODUCTION_SYSTEM/database/backup_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/backup_migration.sql
index 2efd0aa..183ec9a 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/backup_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/backup_migration.sql
@@ -5,7 +5,7 @@
-- Table: backup_history
-- Tracks all database backups (automated and manual)
-CREATE TABLE IF NOT EXISTS `backup_history` (
+CREATE TABLE IF NOT EXISTS `#__backup_history` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`backup_filename` VARCHAR(255) NOT NULL COMMENT 'Filename in backups directory',
`backup_size_mb` DECIMAL(10,2) NOT NULL COMMENT 'Backup file size in megabytes',
@@ -25,12 +25,12 @@ CREATE TABLE IF NOT EXISTS `backup_history` (
INDEX `idx_backup_type` (`backup_type`),
INDEX `idx_deleted_at` (`deleted_at`),
INDEX `idx_filename` (`backup_filename`),
- FOREIGN KEY (`created_by_admin_id`) REFERENCES `admin_users`(`id`) ON DELETE SET NULL
+ FOREIGN KEY (`created_by_admin_id`) REFERENCES `#__admin_users`(`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Database backup history and tracking';
-- Table: backup_restore_log
-- Tracks database restore operations for disaster recovery audit
-CREATE TABLE IF NOT EXISTS `backup_restore_log` (
+CREATE TABLE IF NOT EXISTS `#__backup_restore_log` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`backup_history_id` INT NULL COMMENT 'Which backup was restored',
`backup_filename` VARCHAR(255) NOT NULL COMMENT 'Backup file used for restore',
@@ -44,12 +44,12 @@ CREATE TABLE IF NOT EXISTS `backup_restore_log` (
INDEX `idx_restored_at` (`restored_at`),
INDEX `idx_restore_status` (`restore_status`),
- FOREIGN KEY (`backup_history_id`) REFERENCES `backup_history`(`id`) ON DELETE SET NULL,
- FOREIGN KEY (`restored_by_admin_id`) REFERENCES `admin_users`(`id`) ON DELETE SET NULL
+ FOREIGN KEY (`backup_history_id`) REFERENCES `#__backup_history`(`id`) ON DELETE SET NULL,
+ FOREIGN KEY (`restored_by_admin_id`) REFERENCES `#__admin_users`(`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Database restore operation audit log';
-- System configuration for automated backups
-INSERT INTO `system_config` (`config_key`, `config_value`, `description`) VALUES
+INSERT INTO `#__system_config` (`config_key`, `config_value`, `description`) VALUES
('backup_enabled', '1', 'Enable automated database backups (1=yes, 0=no)'),
('backup_retention_days', '30', 'Number of days to keep backups before deletion'),
('backup_schedule', '0 2 * * *', 'Backup cron schedule (default: daily at 2 AM UTC)'),
diff --git a/FINAL_PRODUCTION_SYSTEM/database/client_config_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/client_config_migration.sql
index 2cbda75..bd1b580 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/client_config_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/client_config_migration.sql
@@ -5,7 +5,7 @@
-- activation timing, and network diagnostics settings.
-- =============================================================
-INSERT INTO system_config (config_key, config_value, description) VALUES
+INSERT INTO `#__system_config` (config_key, config_value, description) VALUES
-- Pre-Activation Task Toggles
('client_task_wsus_cleanup', '1', 'Enable WSUS cleanup before activation'),
('client_task_security_hardening', '1', 'Enable SMB security hardening'),
diff --git a/FINAL_PRODUCTION_SYSTEM/database/client_resources_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/client_resources_migration.sql
index ca942ba..ad31235 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/client_resources_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/client_resources_migration.sql
@@ -2,7 +2,7 @@
-- Phase 9: PowerShell 7 Migration — Hosted MSI Installer
-- Run this migration to add the client_resources table and PS7 config entries
-CREATE TABLE IF NOT EXISTS client_resources (
+CREATE TABLE IF NOT EXISTS `#__client_resources` (
id INT AUTO_INCREMENT PRIMARY KEY,
resource_key VARCHAR(100) NOT NULL UNIQUE,
filename VARCHAR(255) NOT NULL,
@@ -14,5 +14,5 @@ CREATE TABLE IF NOT EXISTS client_resources (
uploaded_by INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
- FOREIGN KEY (uploaded_by) REFERENCES admin_users(id) ON DELETE SET NULL
+ FOREIGN KEY (uploaded_by) REFERENCES `#__admin_users`(id) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
diff --git a/FINAL_PRODUCTION_SYSTEM/database/create_admin.php b/FINAL_PRODUCTION_SYSTEM/database/create_admin.php
index 455f123..94379d9 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/create_admin.php
+++ b/FINAL_PRODUCTION_SYSTEM/database/create_admin.php
@@ -2,8 +2,8 @@
require __DIR__ . '/../config.php';
$hash = password_hash("Admin2024!", PASSWORD_BCRYPT, ["cost" => 10]);
// Get super_admin role ID from acl_roles
-$roleId = $pdo->query("SELECT id FROM acl_roles WHERE role_name = 'super_admin' LIMIT 1")->fetchColumn() ?: null;
+$roleId = $pdo->query("SELECT id FROM `" . t('acl_roles') . "` WHERE role_name = 'super_admin' LIMIT 1")->fetchColumn() ?: null;
-$stmt = $pdo->prepare("INSERT INTO admin_users (username, password_hash, full_name, email, role, custom_role_id) VALUES (?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE password_hash = VALUES(password_hash), custom_role_id = VALUES(custom_role_id), failed_login_attempts = 0, locked_until = NULL");
+$stmt = $pdo->prepare("INSERT INTO `" . t('admin_users') . "` (username, password_hash, full_name, email, role, custom_role_id) VALUES (?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE password_hash = VALUES(password_hash), custom_role_id = VALUES(custom_role_id), failed_login_attempts = 0, locked_until = NULL");
$stmt->execute(["admin", $hash, "Administrator", "admin@localhost", "super_admin", $roleId]);
echo "Admin user created/reset\n";
diff --git a/FINAL_PRODUCTION_SYSTEM/database/database_admin_security.sql b/FINAL_PRODUCTION_SYSTEM/database/database_admin_security.sql
index 0dad74c..e628b04 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/database_admin_security.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/database_admin_security.sql
@@ -3,8 +3,8 @@
USE oem_activation;
--- Admin users table (separate from technicians)
-CREATE TABLE admin_users (
+-- Admin users table (separate from `#__technicians`)
+CREATE TABLE `#__admin_users` (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
full_name VARCHAR(100) NOT NULL,
@@ -22,11 +22,11 @@ CREATE TABLE admin_users (
created_by INT,
INDEX idx_username (username),
INDEX idx_is_active (is_active),
- FOREIGN KEY (created_by) REFERENCES admin_users(id)
+ FOREIGN KEY (created_by) REFERENCES `#__admin_users`(id)
);
-- Admin sessions table
-CREATE TABLE admin_sessions (
+CREATE TABLE `#__admin_sessions` (
id INT AUTO_INCREMENT PRIMARY KEY,
admin_id INT NOT NULL,
session_token VARCHAR(64) NOT NULL UNIQUE,
@@ -36,14 +36,14 @@ CREATE TABLE admin_sessions (
last_activity TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
expires_at TIMESTAMP NOT NULL,
is_active BOOLEAN DEFAULT TRUE,
- FOREIGN KEY (admin_id) REFERENCES admin_users(id),
+ FOREIGN KEY (admin_id) REFERENCES `#__admin_users`(id),
INDEX idx_session_token (session_token),
INDEX idx_admin_id (admin_id),
INDEX idx_expires_at (expires_at)
);
-- Admin activity log
-CREATE TABLE admin_activity_log (
+CREATE TABLE `#__admin_activity_log` (
id INT AUTO_INCREMENT PRIMARY KEY,
admin_id INT,
session_id INT,
@@ -52,15 +52,15 @@ CREATE TABLE admin_activity_log (
ip_address VARCHAR(45),
user_agent TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (admin_id) REFERENCES admin_users(id),
- FOREIGN KEY (session_id) REFERENCES admin_sessions(id),
+ FOREIGN KEY (admin_id) REFERENCES `#__admin_users`(id),
+ FOREIGN KEY (session_id) REFERENCES `#__admin_sessions`(id),
INDEX idx_admin_id (admin_id),
INDEX idx_created_at (created_at),
INDEX idx_action (action)
);
-- IP whitelist table
-CREATE TABLE admin_ip_whitelist (
+CREATE TABLE `#__admin_ip_whitelist` (
id INT AUTO_INCREMENT PRIMARY KEY,
ip_address VARCHAR(45) NOT NULL,
ip_range VARCHAR(45),
@@ -68,13 +68,13 @@ CREATE TABLE admin_ip_whitelist (
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_by INT,
- FOREIGN KEY (created_by) REFERENCES admin_users(id),
+ FOREIGN KEY (created_by) REFERENCES `#__admin_users`(id),
INDEX idx_ip_address (ip_address),
INDEX idx_is_active (is_active)
);
-- Add security configuration
-INSERT INTO system_config (config_key, config_value, description) VALUES
+INSERT INTO `#__system_config` (config_key, config_value, description) VALUES
('admin_session_timeout_minutes', '30', 'Admin session timeout in minutes'),
('admin_max_failed_logins', '3', 'Maximum failed admin login attempts'),
('admin_lockout_duration_minutes', '30', 'Admin account lockout duration'),
@@ -87,12 +87,12 @@ ON DUPLICATE KEY UPDATE config_value = VALUES(config_value);
-- Create initial super admin (password: SuperSecure2024!)
-- Password hash for: SuperSecure2024!
-INSERT INTO admin_users (username, full_name, email, password_hash, role, must_change_password, created_by)
+INSERT INTO `#__admin_users` (username, full_name, email, password_hash, role, must_change_password, created_by)
VALUES ('superadmin', 'Super Administrator', 'admin@yourcompany.com',
'$2y$12$LQv3c1yqBwlVHpPd7u/Dw.G2K2wjDUl9jhJxfTULt3lOAOWuTDBKG',
'super_admin', TRUE, NULL);
-- Add some safe IP addresses (update these for your environment)
--- INSERT INTO admin_ip_whitelist (ip_address, description, created_by) VALUES
+-- INSERT INTO `#__admin_ip_whitelist` (ip_address, description, created_by) VALUES
-- ('192.168.1.0/24', 'Local network', 1),
-- ('10.0.0.0/8', 'Internal network', 1);
\ No newline at end of file
diff --git a/FINAL_PRODUCTION_SYSTEM/database/database_concurrency_indexes.sql b/FINAL_PRODUCTION_SYSTEM/database/database_concurrency_indexes.sql
index 247e840..23c4945 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/database_concurrency_indexes.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/database_concurrency_indexes.sql
@@ -3,35 +3,35 @@
-- Run this after the main database installation
-- Optimize key selection queries (CRITICAL for allocateKeyAtomically)
-ALTER TABLE oem_keys
+ALTER TABLE `#__oem_keys`
ADD INDEX idx_status_fail_date (key_status, fail_counter, last_use_date, id);
-- Optimize session lookups for concurrent access
-ALTER TABLE active_sessions
+ALTER TABLE `#__active_sessions`
ADD INDEX idx_tech_active_expires (technician_id, is_active, expires_at);
-- Optimize activation attempts queries
-ALTER TABLE activation_attempts
+ALTER TABLE `#__activation_attempts`
ADD INDEX idx_key_tech_date (key_id, technician_id, attempted_at);
-- Optimize admin session queries
-ALTER TABLE admin_sessions
+ALTER TABLE `#__admin_sessions`
ADD INDEX idx_admin_active_expires (admin_id, is_active, expires_at);
-- Composite index for common technician queries
-ALTER TABLE technicians
+ALTER TABLE `#__technicians`
ADD INDEX idx_active_locked (is_active, locked_until);
-- Index for cleanup operations (expired sessions)
-ALTER TABLE active_sessions
+ALTER TABLE `#__active_sessions`
ADD INDEX idx_expires_active (expires_at, is_active);
-- Index for audit trail queries
-ALTER TABLE admin_activity_log
+ALTER TABLE `#__admin_activity_log`
ADD INDEX idx_admin_action_time (admin_id, action, created_at);
-- Index for key usage statistics
-ALTER TABLE oem_keys
+ALTER TABLE `#__oem_keys`
ADD INDEX idx_first_usage (first_usage_date, key_status);
-- Update table statistics for better query planning
diff --git a/FINAL_PRODUCTION_SYSTEM/database/database_setup.sql b/FINAL_PRODUCTION_SYSTEM/database/database_setup.sql
index 5d9c5d2..56caca0 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/database_setup.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/database_setup.sql
@@ -5,7 +5,7 @@ CREATE DATABASE IF NOT EXISTS oem_activation;
USE oem_activation;
-- Table to store OEM keys
-CREATE TABLE oem_keys (
+CREATE TABLE `#__oem_keys` (
id INT AUTO_INCREMENT PRIMARY KEY,
product_key VARCHAR(29) NOT NULL UNIQUE,
oem_identifier VARCHAR(20) NOT NULL,
@@ -21,7 +21,7 @@ CREATE TABLE oem_keys (
);
-- Table to track activation attempts
-CREATE TABLE activation_attempts (
+CREATE TABLE `#__activation_attempts` (
id INT AUTO_INCREMENT PRIMARY KEY,
key_id INT NOT NULL,
order_number VARCHAR(10) NOT NULL,
@@ -31,15 +31,15 @@ CREATE TABLE activation_attempts (
attempted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
client_ip VARCHAR(45),
notes TEXT,
- FOREIGN KEY (key_id) REFERENCES oem_keys(id),
- FOREIGN KEY (technician_id) REFERENCES technicians(technician_id),
+ FOREIGN KEY (key_id) REFERENCES `#__oem_keys`(id),
+ FOREIGN KEY (technician_id) REFERENCES `#__technicians`(technician_id),
INDEX idx_order_number (order_number),
INDEX idx_technician_id (technician_id),
INDEX idx_attempted_at (attempted_at)
);
-- Table to store active sessions/tokens
-CREATE TABLE active_sessions (
+CREATE TABLE `#__active_sessions` (
id INT AUTO_INCREMENT PRIMARY KEY,
technician_id VARCHAR(20) NOT NULL,
session_token VARCHAR(64) NOT NULL UNIQUE,
@@ -48,14 +48,14 @@ CREATE TABLE active_sessions (
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP NOT NULL,
is_active BOOLEAN DEFAULT TRUE,
- FOREIGN KEY (key_id) REFERENCES oem_keys(id),
+ FOREIGN KEY (key_id) REFERENCES `#__oem_keys`(id),
INDEX idx_session_token (session_token),
INDEX idx_technician_id (technician_id),
INDEX idx_expires_at (expires_at)
);
-- Table for system configuration
-CREATE TABLE system_config (
+CREATE TABLE `#__system_config` (
config_key VARCHAR(50) PRIMARY KEY,
config_value TEXT NOT NULL,
description TEXT,
@@ -63,7 +63,7 @@ CREATE TABLE system_config (
);
-- Insert basic configuration
-INSERT INTO system_config (config_key, config_value, description) VALUES
+INSERT INTO `#__system_config` (config_key, config_value, description) VALUES
('smtp_server', 'smtp.zoho.com', 'SMTP server for notifications'),
('smtp_port', '587', 'SMTP port'),
('smtp_username', 'oem.activation@roo24.chesnotech.ru', 'SMTP username'),
diff --git a/FINAL_PRODUCTION_SYSTEM/database/database_setup_with_users.sql b/FINAL_PRODUCTION_SYSTEM/database/database_setup_with_users.sql
index aeb3e77..cee0f75 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/database_setup_with_users.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/database_setup_with_users.sql
@@ -5,7 +5,7 @@ CREATE DATABASE IF NOT EXISTS oem_activation;
USE oem_activation;
-- Table to store technician accounts
-CREATE TABLE technicians (
+CREATE TABLE `#__technicians` (
id INT AUTO_INCREMENT PRIMARY KEY,
technician_id VARCHAR(20) NOT NULL UNIQUE,
full_name VARCHAR(100) NOT NULL,
@@ -25,7 +25,7 @@ CREATE TABLE technicians (
);
-- Table to store OEM keys
-CREATE TABLE oem_keys (
+CREATE TABLE `#__oem_keys` (
id INT AUTO_INCREMENT PRIMARY KEY,
product_key VARCHAR(29) NOT NULL UNIQUE,
oem_identifier VARCHAR(20) NOT NULL,
@@ -41,7 +41,7 @@ CREATE TABLE oem_keys (
);
-- Table to track activation attempts
-CREATE TABLE activation_attempts (
+CREATE TABLE `#__activation_attempts` (
id INT AUTO_INCREMENT PRIMARY KEY,
key_id INT NOT NULL,
technician_id VARCHAR(20) NOT NULL,
@@ -51,15 +51,15 @@ CREATE TABLE activation_attempts (
attempted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
client_ip VARCHAR(45),
notes TEXT,
- FOREIGN KEY (key_id) REFERENCES oem_keys(id),
- FOREIGN KEY (technician_id) REFERENCES technicians(technician_id),
+ FOREIGN KEY (key_id) REFERENCES `#__oem_keys`(id),
+ FOREIGN KEY (technician_id) REFERENCES `#__technicians`(technician_id),
INDEX idx_order_number (order_number),
INDEX idx_technician_id (technician_id),
INDEX idx_attempted_at (attempted_at)
);
-- Table to store active sessions/tokens
-CREATE TABLE active_sessions (
+CREATE TABLE `#__active_sessions` (
id INT AUTO_INCREMENT PRIMARY KEY,
technician_id VARCHAR(20) NOT NULL,
session_token VARCHAR(64) NOT NULL UNIQUE,
@@ -68,15 +68,15 @@ CREATE TABLE active_sessions (
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP NOT NULL,
is_active BOOLEAN DEFAULT TRUE,
- FOREIGN KEY (key_id) REFERENCES oem_keys(id),
- FOREIGN KEY (technician_id) REFERENCES technicians(technician_id),
+ FOREIGN KEY (key_id) REFERENCES `#__oem_keys`(id),
+ FOREIGN KEY (technician_id) REFERENCES `#__technicians`(technician_id),
INDEX idx_session_token (session_token),
INDEX idx_technician_id (technician_id),
INDEX idx_expires_at (expires_at)
);
-- Table for system configuration
-CREATE TABLE system_config (
+CREATE TABLE `#__system_config` (
config_key VARCHAR(50) PRIMARY KEY,
config_value TEXT NOT NULL,
description TEXT,
@@ -84,20 +84,20 @@ CREATE TABLE system_config (
);
-- Table for password reset tokens
-CREATE TABLE password_reset_tokens (
+CREATE TABLE `#__password_reset_tokens` (
id INT AUTO_INCREMENT PRIMARY KEY,
technician_id VARCHAR(20) NOT NULL,
reset_token VARCHAR(64) NOT NULL UNIQUE,
expires_at TIMESTAMP NOT NULL,
used_at TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (technician_id) REFERENCES technicians(technician_id),
+ FOREIGN KEY (technician_id) REFERENCES `#__technicians`(technician_id),
INDEX idx_reset_token (reset_token),
INDEX idx_expires_at (expires_at)
);
-- Insert basic configuration
-INSERT INTO system_config (config_key, config_value, description) VALUES
+INSERT INTO `#__system_config` (config_key, config_value, description) VALUES
('smtp_server', 'smtp.zoho.com', 'SMTP server for notifications'),
('smtp_port', '587', 'SMTP port'),
('smtp_username', 'oem.activation@roo24.chesnotech.ru', 'SMTP username'),
@@ -115,13 +115,13 @@ INSERT INTO system_config (config_key, config_value, description) VALUES
('show_full_keys_in_admin', '0', 'Show full product keys in admin panel (1=yes, 0=no - admin only)');
-- Create default admin account (password: admin123 - CHANGE THIS!)
-INSERT INTO technicians (technician_id, full_name, email, password_hash, must_change_password, created_by, notes)
+INSERT INTO `#__technicians` (technician_id, full_name, email, password_hash, must_change_password, created_by, notes)
VALUES ('admin', 'System Administrator', 'admin@yourcompany.com',
'$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',
TRUE, 'system', 'Default admin account - change password immediately');
-- Create sample technician account (password: temp123)
-INSERT INTO technicians (technician_id, full_name, email, password_hash, temp_password, must_change_password, created_by, notes)
+INSERT INTO `#__technicians` (technician_id, full_name, email, password_hash, temp_password, must_change_password, created_by, notes)
VALUES ('tech001', 'John Technician', 'tech001@yourcompany.com',
'$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',
'temp123', TRUE, 'admin', 'Sample technician account');
\ No newline at end of file
diff --git a/FINAL_PRODUCTION_SYSTEM/database/docker-init/00-init.sh b/FINAL_PRODUCTION_SYSTEM/database/docker-init/00-init.sh
index bac8e58..fb6bcc1 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/docker-init/00-init.sh
+++ b/FINAL_PRODUCTION_SYSTEM/database/docker-init/00-init.sh
@@ -15,16 +15,45 @@ DB="${MARIADB_DATABASE:-oem_activation}"
SQL_DIR="/docker-entrypoint-initdb.d/sql"
MYSQL_CMD="mysql -u root -p${MARIADB_ROOT_PASSWORD} ${DB}"
+# ── Table prefix support ─────────────────────────────────────
+# SQL files use the Joomla-style sentinel `#__` for table names.
+# At init time we substitute it with $KEYGATE_DB_PREFIX (default: empty
+# string → identical schema to pre-prefix releases).
+PREFIX="${KEYGATE_DB_PREFIX:-}"
+SV_TABLE="${PREFIX}schema_versions"
+
+# Validate prefix: must match ^[a-z][a-z0-9_]{0,9}$ or be empty.
+if [ -n "$PREFIX" ]; then
+ if ! echo "$PREFIX" | grep -qE '^[a-z][a-z0-9_]{0,9}$'; then
+ echo "[ERROR] Invalid KEYGATE_DB_PREFIX='$PREFIX'. Must match ^[a-z][a-z0-9_]{0,9}\$ or be empty."
+ exit 1
+ fi
+fi
+
echo "=== KeyGate: Database Initialization ==="
echo "Database: $DB"
echo "SQL directory: $SQL_DIR"
+echo "Table prefix: ${PREFIX:-}"
+
+# ── Substitute #__ → $PREFIX for every .sql file in $SQL_DIR ──
+# We copy to /tmp/keygate-sql/ so the original mounted volume stays
+# untouched (read-only on some setups).
+STAGING="/tmp/keygate-sql"
+mkdir -p "$STAGING"
+for f in "$SQL_DIR"/*.sql; do
+ [ -f "$f" ] || continue
+ base="$(basename "$f")"
+ # sed -i won't work on read-only mounts; pipe through to a fresh file.
+ sed "s/#__/${PREFIX}/g" "$f" > "$STAGING/$base"
+done
+SQL_DIR="$STAGING"
# ── Step 0: Ensure schema_versions table exists ──────────────
# This must run unconditionally so the tracking table is always present.
$MYSQL_CMD < "$SQL_DIR/schema_versions_migration.sql" 2>/dev/null || true
# ── Idempotent migration runner ──────────────────────────────
-# Checks schema_versions before running; records after success.
+# Checks ${PREFIX}schema_versions before running; records after success.
run_sql() {
local file="$SQL_DIR/$1"
local version="$2"
@@ -36,7 +65,7 @@ run_sql() {
# Check if already applied
local applied
- applied=$($MYSQL_CMD -N -e "SELECT COUNT(*) FROM schema_versions WHERE filename = '$1'" 2>/dev/null || echo "0")
+ applied=$($MYSQL_CMD -N -e "SELECT COUNT(*) FROM \`${SV_TABLE}\` WHERE filename = '$1'" 2>/dev/null || echo "0")
if [ "$applied" -gt 0 ]; then
echo "[SKIP] Already applied: $1"
@@ -48,11 +77,18 @@ run_sql() {
echo "[WARN] Non-fatal errors in $1 (continuing)"
fi
- # Compute checksum and record
+ # Compute checksum from the original (un-substituted) file so the
+ # checksum is stable regardless of prefix choice. Falls back to staged
+ # copy if the original isn't accessible.
+ local original="/docker-entrypoint-initdb.d/sql/$1"
local checksum
- checksum=$(sha256sum "$file" | cut -d' ' -f1)
+ if [ -f "$original" ]; then
+ checksum=$(sha256sum "$original" | cut -d' ' -f1)
+ else
+ checksum=$(sha256sum "$file" | cut -d' ' -f1)
+ fi
- $MYSQL_CMD -e "INSERT INTO schema_versions (version, filename, checksum) VALUES ($version, '$1', '$checksum')"
+ $MYSQL_CMD -e "INSERT INTO \`${SV_TABLE}\` (version, filename, checksum) VALUES ($version, '$1', '$checksum')"
echo "[DONE] Applied: $1"
}
diff --git a/FINAL_PRODUCTION_SYSTEM/database/downloads_acl_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/downloads_acl_migration.sql
index d5da7bd..e66a039 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/downloads_acl_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/downloads_acl_migration.sql
@@ -5,33 +5,33 @@
-- ============================================================
-- Add "Downloads" permission category
-INSERT INTO acl_permission_categories (category_key, display_name, icon, sort_order)
+INSERT INTO `#__acl_permission_categories` (category_key, display_name, icon, sort_order)
VALUES ('downloads', 'Client Downloads', NULL, 55)
ON DUPLICATE KEY UPDATE display_name = VALUES(display_name);
-- Add download permissions
-INSERT INTO acl_permissions (permission_key, display_name, description, category_id, resource_type, action_type, is_dangerous)
+INSERT INTO `#__acl_permissions` (permission_key, display_name, description, category_id, resource_type, action_type, is_dangerous)
SELECT 'view_downloads', 'View Downloads', 'View and download client tools (launcher, PS7 installer, extensions)',
c.id, 'downloads', 'view', 0
-FROM acl_permission_categories c WHERE c.category_key = 'downloads'
+FROM `#__acl_permission_categories` c WHERE c.category_key = 'downloads'
ON DUPLICATE KEY UPDATE display_name = VALUES(display_name);
-INSERT INTO acl_permissions (permission_key, display_name, description, category_id, resource_type, action_type, is_dangerous)
+INSERT INTO `#__acl_permissions` (permission_key, display_name, description, category_id, resource_type, action_type, is_dangerous)
SELECT 'manage_downloads', 'Manage Downloads', 'Upload, replace, and delete client resources',
c.id, 'downloads', 'manage', 1
-FROM acl_permission_categories c WHERE c.category_key = 'downloads'
+FROM `#__acl_permission_categories` c WHERE c.category_key = 'downloads'
ON DUPLICATE KEY UPDATE display_name = VALUES(display_name);
-- Grant both permissions to super_admin role
INSERT IGNORE INTO acl_role_permissions (role_id, permission_id)
SELECT r.id, p.id
-FROM acl_roles r CROSS JOIN acl_permissions p
+FROM `#__acl_roles` r CROSS JOIN `#__acl_permissions` p
WHERE r.role_name = 'super_admin'
AND p.permission_key IN ('view_downloads', 'manage_downloads');
-- Grant view_downloads to admin role
INSERT IGNORE INTO acl_role_permissions (role_id, permission_id)
SELECT r.id, p.id
-FROM acl_roles r, acl_permissions p
+FROM `#__acl_roles` r, acl_permissions p
WHERE r.role_name = 'admin'
AND p.permission_key = 'view_downloads';
diff --git a/FINAL_PRODUCTION_SYSTEM/database/hardware_info_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/hardware_info_migration.sql
index cee3e96..8dde0c3 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/hardware_info_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/hardware_info_migration.sql
@@ -3,12 +3,12 @@
-- Purpose: Make OEM ID and Roll Serial optional, add hardware tracking
-- Step 1: Make OEM ID and Roll Serial optional in oem_keys table
-ALTER TABLE oem_keys
+ALTER TABLE `#__oem_keys`
MODIFY COLUMN oem_identifier VARCHAR(20) NULL DEFAULT NULL,
MODIFY COLUMN roll_serial VARCHAR(20) NULL DEFAULT NULL;
-- Step 2: Create hardware_info table for tracking PC hardware details
-CREATE TABLE IF NOT EXISTS hardware_info (
+CREATE TABLE IF NOT EXISTS `#__hardware_info` (
id INT AUTO_INCREMENT PRIMARY KEY,
activation_id INT NOT NULL COMMENT 'Links to activation_attempts.id',
order_number VARCHAR(10) NOT NULL COMMENT 'Order number for easy reference',
@@ -60,11 +60,11 @@ CREATE TABLE IF NOT EXISTS hardware_info (
INDEX idx_order_number (order_number),
INDEX idx_collected_at (collected_at),
- FOREIGN KEY (activation_id) REFERENCES activation_attempts(id) ON DELETE CASCADE
+ FOREIGN KEY (activation_id) REFERENCES `#__activation_attempts`(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Hardware information collected during activation';
-- Step 3: Add hardware_collected flag to activation_attempts
-ALTER TABLE activation_attempts
+ALTER TABLE `#__activation_attempts`
ADD COLUMN hardware_collected TINYINT(1) DEFAULT 0 COMMENT 'Whether hardware info was collected for this activation';
-- Step 4: Create view for easy hardware lookup by order number
@@ -86,12 +86,12 @@ SELECT
h.ram_total_capacity_gb,
h.secure_boot_enabled,
h.collected_at AS hardware_collected_at
-FROM activation_attempts a
-LEFT JOIN technicians t ON a.technician_id = t.technician_id
-LEFT JOIN oem_keys k ON a.key_id = k.id
-LEFT JOIN hardware_info h ON h.activation_id = a.id
+FROM `#__activation_attempts` a
+LEFT JOIN `#__technicians` t ON a.technician_id = t.technician_id
+LEFT JOIN `#__oem_keys` k ON a.key_id = k.id
+LEFT JOIN `#__hardware_info` h ON h.activation_id = a.id
ORDER BY a.attempted_at DESC;
-- Step 5: (Optional) Add secure_boot_enabled column if table already exists without it
-- Run this only if you applied the migration before this column was added:
--- ALTER TABLE hardware_info ADD COLUMN secure_boot_enabled TINYINT(1) NULL COMMENT 'Whether Secure Boot is enabled (1=yes, 0=no, NULL=unknown)' AFTER os_architecture;
+-- ALTER TABLE `#__hardware_info` ADD COLUMN secure_boot_enabled TINYINT(1) NULL COMMENT 'Whether Secure Boot is enabled (1=yes, 0=no, NULL=unknown)' AFTER os_architecture;
diff --git a/FINAL_PRODUCTION_SYSTEM/database/hardware_info_v2_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/hardware_info_v2_migration.sql
index ae57497..aa65dbc 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/hardware_info_v2_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/hardware_info_v2_migration.sql
@@ -5,48 +5,48 @@
-- Add new columns to hardware_info table
-- Chassis / Enclosure Information
-ALTER TABLE hardware_info ADD COLUMN chassis_manufacturer VARCHAR(100) NULL AFTER computer_name;
-ALTER TABLE hardware_info ADD COLUMN chassis_serial VARCHAR(100) NULL AFTER chassis_manufacturer;
-ALTER TABLE hardware_info ADD COLUMN chassis_type VARCHAR(50) NULL AFTER chassis_serial;
+ALTER TABLE `#__hardware_info` ADD COLUMN chassis_manufacturer VARCHAR(100) NULL AFTER computer_name;
+ALTER TABLE `#__hardware_info` ADD COLUMN chassis_serial VARCHAR(100) NULL AFTER chassis_manufacturer;
+ALTER TABLE `#__hardware_info` ADD COLUMN chassis_type VARCHAR(50) NULL AFTER chassis_serial;
-- System Product Information (OEM)
-ALTER TABLE hardware_info ADD COLUMN system_manufacturer VARCHAR(100) NULL AFTER chassis_type;
-ALTER TABLE hardware_info ADD COLUMN system_product_name VARCHAR(200) NULL AFTER system_manufacturer;
-ALTER TABLE hardware_info ADD COLUMN system_serial VARCHAR(100) NULL AFTER system_product_name;
-ALTER TABLE hardware_info ADD COLUMN system_uuid VARCHAR(50) NULL AFTER system_serial;
+ALTER TABLE `#__hardware_info` ADD COLUMN system_manufacturer VARCHAR(100) NULL AFTER chassis_type;
+ALTER TABLE `#__hardware_info` ADD COLUMN system_product_name VARCHAR(200) NULL AFTER system_manufacturer;
+ALTER TABLE `#__hardware_info` ADD COLUMN system_serial VARCHAR(100) NULL AFTER system_product_name;
+ALTER TABLE `#__hardware_info` ADD COLUMN system_uuid VARCHAR(50) NULL AFTER system_serial;
-- TPM Information
-ALTER TABLE hardware_info ADD COLUMN tpm_present TINYINT(1) NULL AFTER system_uuid;
-ALTER TABLE hardware_info ADD COLUMN tpm_version VARCHAR(50) NULL AFTER tpm_present;
-ALTER TABLE hardware_info ADD COLUMN tpm_manufacturer VARCHAR(100) NULL AFTER tpm_version;
+ALTER TABLE `#__hardware_info` ADD COLUMN tpm_present TINYINT(1) NULL AFTER system_uuid;
+ALTER TABLE `#__hardware_info` ADD COLUMN tpm_version VARCHAR(50) NULL AFTER tpm_present;
+ALTER TABLE `#__hardware_info` ADD COLUMN tpm_manufacturer VARCHAR(100) NULL AFTER tpm_version;
-- CPU Serial (Processor ID)
-ALTER TABLE hardware_info ADD COLUMN cpu_serial VARCHAR(50) NULL AFTER cpu_max_clock_speed;
+ALTER TABLE `#__hardware_info` ADD COLUMN cpu_serial VARCHAR(50) NULL AFTER cpu_max_clock_speed;
-- Network Information
-ALTER TABLE hardware_info ADD COLUMN primary_mac_address VARCHAR(20) NULL AFTER computer_name;
-ALTER TABLE hardware_info ADD COLUMN local_ip VARCHAR(45) NULL AFTER primary_mac_address;
-ALTER TABLE hardware_info ADD COLUMN public_ip VARCHAR(45) NULL AFTER local_ip;
-ALTER TABLE hardware_info ADD COLUMN network_adapters JSON NULL COMMENT 'Array of network adapter details with MAC, IP, etc.' AFTER public_ip;
+ALTER TABLE `#__hardware_info` ADD COLUMN primary_mac_address VARCHAR(20) NULL AFTER computer_name;
+ALTER TABLE `#__hardware_info` ADD COLUMN local_ip VARCHAR(45) NULL AFTER primary_mac_address;
+ALTER TABLE `#__hardware_info` ADD COLUMN public_ip VARCHAR(45) NULL AFTER local_ip;
+ALTER TABLE `#__hardware_info` ADD COLUMN network_adapters JSON NULL COMMENT 'Array of network adapter details with MAC, IP, etc.' AFTER public_ip;
-- Audio Devices
-ALTER TABLE hardware_info ADD COLUMN audio_devices JSON NULL COMMENT 'Array of sound device details' AFTER network_adapters;
+ALTER TABLE `#__hardware_info` ADD COLUMN audio_devices JSON NULL COMMENT 'Array of sound device details' AFTER network_adapters;
-- Monitor Information
-ALTER TABLE hardware_info ADD COLUMN monitors JSON NULL COMMENT 'Array of connected monitor details with serials' AFTER audio_devices;
+ALTER TABLE `#__hardware_info` ADD COLUMN monitors JSON NULL COMMENT 'Array of connected monitor details with serials' AFTER audio_devices;
-- OS Extended Info
-ALTER TABLE hardware_info ADD COLUMN os_build_number VARCHAR(20) NULL AFTER os_architecture;
-ALTER TABLE hardware_info ADD COLUMN os_install_date VARCHAR(50) NULL AFTER os_build_number;
-ALTER TABLE hardware_info ADD COLUMN os_serial_number VARCHAR(100) NULL AFTER os_install_date;
+ALTER TABLE `#__hardware_info` ADD COLUMN os_build_number VARCHAR(20) NULL AFTER os_architecture;
+ALTER TABLE `#__hardware_info` ADD COLUMN os_install_date VARCHAR(50) NULL AFTER os_build_number;
+ALTER TABLE `#__hardware_info` ADD COLUMN os_serial_number VARCHAR(100) NULL AFTER os_install_date;
-- Device Fingerprint (composite unique identifier)
-ALTER TABLE hardware_info ADD COLUMN device_fingerprint VARCHAR(500) NULL COMMENT 'Composite hardware fingerprint for duplicate detection' AFTER collection_method;
+ALTER TABLE `#__hardware_info` ADD COLUMN device_fingerprint VARCHAR(500) NULL COMMENT 'Composite hardware fingerprint for duplicate detection' AFTER collection_method;
-- Index for device fingerprint lookups
-ALTER TABLE hardware_info ADD INDEX idx_device_fingerprint (device_fingerprint(255));
-ALTER TABLE hardware_info ADD INDEX idx_public_ip (public_ip);
-ALTER TABLE hardware_info ADD INDEX idx_primary_mac (primary_mac_address);
+ALTER TABLE `#__hardware_info` ADD INDEX idx_device_fingerprint (device_fingerprint(255));
+ALTER TABLE `#__hardware_info` ADD INDEX idx_public_ip (public_ip);
+ALTER TABLE `#__hardware_info` ADD INDEX idx_primary_mac (primary_mac_address);
-- Update the view to include new network fields
CREATE OR REPLACE VIEW v_activation_hardware AS
@@ -73,8 +73,8 @@ SELECT
h.system_uuid,
h.device_fingerprint,
h.collected_at AS hardware_collected_at
-FROM activation_attempts a
-LEFT JOIN technicians t ON a.technician_id = t.technician_id
-LEFT JOIN oem_keys k ON a.key_id = k.id
-LEFT JOIN hardware_info h ON h.activation_id = a.id
+FROM `#__activation_attempts` a
+LEFT JOIN `#__technicians` t ON a.technician_id = t.technician_id
+LEFT JOIN `#__oem_keys` k ON a.key_id = k.id
+LEFT JOIN `#__hardware_info` h ON h.activation_id = a.id
ORDER BY a.attempted_at DESC;
diff --git a/FINAL_PRODUCTION_SYSTEM/database/hash_temp_passwords.php b/FINAL_PRODUCTION_SYSTEM/database/hash_temp_passwords.php
index fb7e21d..322e7f5 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/hash_temp_passwords.php
+++ b/FINAL_PRODUCTION_SYSTEM/database/hash_temp_passwords.php
@@ -8,7 +8,7 @@
echo "Hashing plaintext temp_passwords...\n";
-$stmt = $pdo->query("SELECT id, temp_password FROM technicians WHERE temp_password IS NOT NULL AND temp_password != ''");
+$stmt = $pdo->query("SELECT id, temp_password FROM `" . t('technicians') . "` WHERE temp_password IS NOT NULL AND temp_password != ''");
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
$updated = 0;
@@ -20,7 +20,7 @@
}
$hashed = password_hash($row['temp_password'], PASSWORD_BCRYPT, ['cost' => BCRYPT_COST]);
- $update = $pdo->prepare("UPDATE technicians SET temp_password = ? WHERE id = ?");
+ $update = $pdo->prepare("UPDATE `" . t('technicians') . "` SET temp_password = ? WHERE id = ?");
$update->execute([$hashed, $row['id']]);
$updated++;
echo " Hashed temp_password for ID {$row['id']}\n";
diff --git a/FINAL_PRODUCTION_SYSTEM/database/i18n_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/i18n_migration.sql
index 1d3f112..a92be36 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/i18n_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/i18n_migration.sql
@@ -2,12 +2,12 @@
-- Run this migration to enable per-user language selection
-- Add preferred_language column to admin_users
-ALTER TABLE admin_users ADD COLUMN preferred_language VARCHAR(5) DEFAULT 'en' AFTER role;
+ALTER TABLE `#__admin_users` ADD COLUMN preferred_language VARCHAR(5) DEFAULT 'en' AFTER role;
-- Add preferred_language column to technicians
-ALTER TABLE technicians ADD COLUMN preferred_language VARCHAR(5) DEFAULT 'en' AFTER notes;
+ALTER TABLE `#__technicians` ADD COLUMN preferred_language VARCHAR(5) DEFAULT 'en' AFTER notes;
-- Add system default language setting
-INSERT INTO system_config (config_key, config_value, description)
+INSERT INTO `#__system_config` (config_key, config_value, description)
VALUES ('default_language', 'en', 'Default system language (en = English, ru = Russian)')
ON DUPLICATE KEY UPDATE config_value = config_value;
diff --git a/FINAL_PRODUCTION_SYSTEM/database/install.sql b/FINAL_PRODUCTION_SYSTEM/database/install.sql
index 0441b3a..88db432 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/install.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/install.sql
@@ -8,7 +8,7 @@ START TRANSACTION;
SET time_zone = "+00:00";
-- Create technicians table
-CREATE TABLE `technicians` (
+CREATE TABLE `#__technicians` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`technician_id` varchar(20) NOT NULL,
`full_name` varchar(100) NOT NULL,
@@ -31,7 +31,7 @@ CREATE TABLE `technicians` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Create oem_keys table
-CREATE TABLE `oem_keys` (
+CREATE TABLE `#__oem_keys` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`product_key` varchar(29) NOT NULL,
`oem_identifier` varchar(20) NOT NULL,
@@ -56,7 +56,7 @@ CREATE TABLE `oem_keys` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Create activation_attempts table
-CREATE TABLE `activation_attempts` (
+CREATE TABLE `#__activation_attempts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`key_id` int(11) NOT NULL,
`technician_id` varchar(20) NOT NULL,
@@ -76,12 +76,12 @@ CREATE TABLE `activation_attempts` (
KEY `idx_attempted_at` (`attempted_at`),
KEY `idx_attempted_date` (`attempted_date`),
KEY `idx_key_tech_date` (`key_id`, `technician_id`, `attempted_at`),
- CONSTRAINT `activation_attempts_ibfk_1` FOREIGN KEY (`key_id`) REFERENCES `oem_keys` (`id`),
- CONSTRAINT `activation_attempts_ibfk_2` FOREIGN KEY (`technician_id`) REFERENCES `technicians` (`technician_id`)
+ CONSTRAINT `activation_attempts_ibfk_1` FOREIGN KEY (`key_id`) REFERENCES `#__oem_keys` (`id`),
+ CONSTRAINT `activation_attempts_ibfk_2` FOREIGN KEY (`technician_id`) REFERENCES `#__technicians` (`technician_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Create active_sessions table
-CREATE TABLE `active_sessions` (
+CREATE TABLE `#__active_sessions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`technician_id` varchar(20) NOT NULL,
`session_token` varchar(64) NOT NULL,
@@ -99,12 +99,12 @@ CREATE TABLE `active_sessions` (
KEY `idx_expires_at` (`expires_at`),
KEY `idx_tech_active_expires` (`technician_id`, `is_active`, `expires_at`),
KEY `idx_expires_active` (`expires_at`, `is_active`),
- CONSTRAINT `active_sessions_ibfk_1` FOREIGN KEY (`key_id`) REFERENCES `oem_keys` (`id`),
- CONSTRAINT `active_sessions_ibfk_2` FOREIGN KEY (`technician_id`) REFERENCES `technicians` (`technician_id`)
+ CONSTRAINT `active_sessions_ibfk_1` FOREIGN KEY (`key_id`) REFERENCES `#__oem_keys` (`id`),
+ CONSTRAINT `active_sessions_ibfk_2` FOREIGN KEY (`technician_id`) REFERENCES `#__technicians` (`technician_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Create admin_users table
-CREATE TABLE `admin_users` (
+CREATE TABLE `#__admin_users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`full_name` varchar(100) NOT NULL,
@@ -125,11 +125,11 @@ CREATE TABLE `admin_users` (
KEY `created_by` (`created_by`),
KEY `idx_username` (`username`),
KEY `idx_is_active` (`is_active`),
- CONSTRAINT `admin_users_ibfk_1` FOREIGN KEY (`created_by`) REFERENCES `admin_users` (`id`)
+ CONSTRAINT `admin_users_ibfk_1` FOREIGN KEY (`created_by`) REFERENCES `#__admin_users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Create admin_sessions table
-CREATE TABLE `admin_sessions` (
+CREATE TABLE `#__admin_sessions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`admin_id` int(11) NOT NULL,
`session_token` varchar(64) NOT NULL,
@@ -145,11 +145,11 @@ CREATE TABLE `admin_sessions` (
KEY `idx_session_token` (`session_token`),
KEY `idx_admin_id` (`admin_id`),
KEY `idx_expires_at` (`expires_at`),
- CONSTRAINT `admin_sessions_ibfk_1` FOREIGN KEY (`admin_id`) REFERENCES `admin_users` (`id`)
+ CONSTRAINT `admin_sessions_ibfk_1` FOREIGN KEY (`admin_id`) REFERENCES `#__admin_users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Create admin_activity_log table
-CREATE TABLE `admin_activity_log` (
+CREATE TABLE `#__admin_activity_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`admin_id` int(11) DEFAULT NULL,
`session_id` int(11) DEFAULT NULL,
@@ -164,12 +164,12 @@ CREATE TABLE `admin_activity_log` (
KEY `idx_admin_id` (`admin_id`),
KEY `idx_created_at` (`created_at`),
KEY `idx_action` (`action`),
- CONSTRAINT `admin_activity_log_ibfk_1` FOREIGN KEY (`admin_id`) REFERENCES `admin_users` (`id`),
- CONSTRAINT `admin_activity_log_ibfk_2` FOREIGN KEY (`session_id`) REFERENCES `admin_sessions` (`id`)
+ CONSTRAINT `admin_activity_log_ibfk_1` FOREIGN KEY (`admin_id`) REFERENCES `#__admin_users` (`id`),
+ CONSTRAINT `admin_activity_log_ibfk_2` FOREIGN KEY (`session_id`) REFERENCES `#__admin_sessions` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Create admin_ip_whitelist table
-CREATE TABLE `admin_ip_whitelist` (
+CREATE TABLE `#__admin_ip_whitelist` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ip_address` varchar(45) NOT NULL,
`ip_range` varchar(45) DEFAULT NULL,
@@ -181,11 +181,11 @@ CREATE TABLE `admin_ip_whitelist` (
KEY `created_by` (`created_by`),
KEY `idx_ip_address` (`ip_address`),
KEY `idx_is_active` (`is_active`),
- CONSTRAINT `admin_ip_whitelist_ibfk_1` FOREIGN KEY (`created_by`) REFERENCES `admin_users` (`id`)
+ CONSTRAINT `admin_ip_whitelist_ibfk_1` FOREIGN KEY (`created_by`) REFERENCES `#__admin_users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Create system_config table
-CREATE TABLE `system_config` (
+CREATE TABLE `#__system_config` (
`config_key` varchar(50) NOT NULL,
`config_value` text NOT NULL,
`description` text DEFAULT NULL,
@@ -194,7 +194,7 @@ CREATE TABLE `system_config` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Create password_reset_tokens table
-CREATE TABLE `password_reset_tokens` (
+CREATE TABLE `#__password_reset_tokens` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`technician_id` varchar(20) NOT NULL,
`reset_token` varchar(64) NOT NULL,
@@ -206,11 +206,11 @@ CREATE TABLE `password_reset_tokens` (
KEY `technician_id` (`technician_id`),
KEY `idx_reset_token` (`reset_token`),
KEY `idx_expires_at` (`expires_at`),
- CONSTRAINT `password_reset_tokens_ibfk_1` FOREIGN KEY (`technician_id`) REFERENCES `technicians` (`technician_id`)
+ CONSTRAINT `password_reset_tokens_ibfk_1` FOREIGN KEY (`technician_id`) REFERENCES `#__technicians` (`technician_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Insert default system configuration
-INSERT INTO `system_config` (`config_key`, `config_value`, `description`) VALUES
+INSERT INTO `#__system_config` (`config_key`, `config_value`, `description`) VALUES
('smtp_server', 'smtp.zoho.com', 'SMTP server for notifications'),
('smtp_port', '587', 'SMTP port'),
('smtp_username', '', 'SMTP username'),
@@ -236,7 +236,7 @@ INSERT INTO `system_config` (`config_key`, `config_value`, `description`) VALUES
('admin_log_retention_days', '365', 'Keep admin activity logs for N days');
-- Create sample technician account (for testing)
-INSERT INTO `technicians` (`technician_id`, `full_name`, `email`, `password_hash`, `temp_password`, `must_change_password`, `created_by`, `notes`) VALUES
+INSERT INTO `#__technicians` (`technician_id`, `full_name`, `email`, `password_hash`, `temp_password`, `must_change_password`, `created_by`, `notes`) VALUES
('demo', 'Demo Technician', 'demo@example.com', '$2y$12$LQv3c1yqBwlVHpPd7u/Dw.G2K2wjDUl9jhJxfTULt3lOAOWuTDBKG', 'demo123', 1, 'system', 'Demo account for testing - Password: demo123');
COMMIT;
\ No newline at end of file
diff --git a/FINAL_PRODUCTION_SYSTEM/database/integrations_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/integrations_migration.sql
index 4fa2bf3..f60e111 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/integrations_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/integrations_migration.sql
@@ -3,7 +3,7 @@
-- Supports osTicket, 1C ERP, and future integrations
-- =============================================================
-CREATE TABLE IF NOT EXISTS `integrations` (
+CREATE TABLE IF NOT EXISTS `#__integrations` (
`id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`integration_key` VARCHAR(50) NOT NULL UNIQUE,
`display_name` VARCHAR(100) NOT NULL,
@@ -18,7 +18,7 @@ CREATE TABLE IF NOT EXISTS `integrations` (
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-CREATE TABLE IF NOT EXISTS `integration_events` (
+CREATE TABLE IF NOT EXISTS `#__integration_events` (
`id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`integration_id` INT UNSIGNED NOT NULL,
`event_type` VARCHAR(50) NOT NULL,
@@ -29,14 +29,14 @@ CREATE TABLE IF NOT EXISTS `integration_events` (
`error_message` TEXT,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`processed_at` TIMESTAMP NULL DEFAULT NULL,
- FOREIGN KEY (`integration_id`) REFERENCES `integrations`(`id`) ON DELETE CASCADE,
+ FOREIGN KEY (`integration_id`) REFERENCES `#__integrations`(`id`) ON DELETE CASCADE,
INDEX `idx_ie_status` (`status`),
INDEX `idx_ie_event_type` (`event_type`),
INDEX `idx_ie_created` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Seed default integrations
-INSERT INTO `integrations` (`integration_key`, `display_name`, `description`, `integration_type`, `enabled`, `config`) VALUES
+INSERT INTO `#__integrations` (`integration_key`, `display_name`, `description`, `integration_type`, `enabled`, `config`) VALUES
('osticket', 'osTicket', 'Track PC build orders as support tickets in osTicket', 'api_sync', 0,
JSON_OBJECT(
'base_url', '',
diff --git a/FINAL_PRODUCTION_SYSTEM/database/license_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/license_migration.sql
index 49e8cb4..8dbc5dd 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/license_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/license_migration.sql
@@ -4,7 +4,7 @@
-- Tracks instance license, tier limits, and validation history.
-- =============================================================
-CREATE TABLE IF NOT EXISTS license_info (
+CREATE TABLE IF NOT EXISTS `#__license_info` (
id INT AUTO_INCREMENT PRIMARY KEY,
license_key VARCHAR(2048) NOT NULL COMMENT 'JWT license token',
instance_id VARCHAR(128) NOT NULL COMMENT 'SHA256 fingerprint of this installation',
@@ -26,10 +26,10 @@ CREATE TABLE IF NOT EXISTS license_info (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Default community license limits stored in system_config
-INSERT INTO system_config (config_key, config_value, description) VALUES
+INSERT INTO `#__system_config` (config_key, config_value, description) VALUES
('license_tier', 'community', 'Current license tier')
ON DUPLICATE KEY UPDATE config_key = config_key;
-INSERT INTO system_config (config_key, config_value, description) VALUES
+INSERT INTO `#__system_config` (config_key, config_value, description) VALUES
('license_instance_id', '', 'Unique instance fingerprint (auto-generated)')
ON DUPLICATE KEY UPDATE config_key = config_key;
diff --git a/FINAL_PRODUCTION_SYSTEM/database/missing_drivers_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/missing_drivers_migration.sql
index 0cdd5a0..61a4e83 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/missing_drivers_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/missing_drivers_migration.sql
@@ -2,21 +2,21 @@
-- Adds driver status tracking and per-check enforcement to product lines
-- 1. Add driver columns to hardware_info
-ALTER TABLE hardware_info
+ALTER TABLE `#__hardware_info`
ADD COLUMN IF NOT EXISTS missing_drivers JSON NULL COMMENT 'Array of devices with missing/problematic drivers',
ADD COLUMN IF NOT EXISTS missing_drivers_count INT NULL DEFAULT NULL COMMENT 'Number of missing/error drivers detected';
CREATE INDEX IF NOT EXISTS idx_hw_missing_drivers_count ON hardware_info (missing_drivers_count);
-- 2. Add enforcement columns to QC tables
-ALTER TABLE qc_motherboard_registry
+ALTER TABLE `#__qc_motherboard_registry`
ADD COLUMN IF NOT EXISTS missing_drivers_enforcement TINYINT(1) NULL COMMENT 'Override: 0=disabled, 1=info, 2=warning, 3=blocking';
-ALTER TABLE qc_manufacturer_defaults
+ALTER TABLE `#__qc_manufacturer_defaults`
ADD COLUMN IF NOT EXISTS missing_drivers_enforcement TINYINT(1) DEFAULT NULL COMMENT 'Override: 0=disabled, 1=info, 2=warning, 3=blocking';
-- 3. Add per-check enforcement columns to product_lines
-ALTER TABLE product_lines
+ALTER TABLE `#__product_lines`
ADD COLUMN IF NOT EXISTS secure_boot_enforcement TINYINT(1) DEFAULT NULL,
ADD COLUMN IF NOT EXISTS bios_enforcement TINYINT(1) DEFAULT NULL,
ADD COLUMN IF NOT EXISTS hackbgrt_enforcement TINYINT(1) DEFAULT NULL,
@@ -31,5 +31,5 @@ INSERT IGNORE INTO qc_global_settings (setting_key, setting_value, description)
VALUES ('default_partition_enforcement', '2', 'Default enforcement for partition layout check (0=disabled, 1=info, 2=warning, 3=blocking)');
-- 5. Widen check_type from ENUM to VARCHAR for extensibility
-ALTER TABLE qc_compliance_results
+ALTER TABLE `#__qc_compliance_results`
MODIFY COLUMN check_type VARCHAR(50) NOT NULL COMMENT 'Check type identifier';
diff --git a/FINAL_PRODUCTION_SYSTEM/database/order_field_config_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/order_field_config_migration.sql
index 4d7a821..1d218e1 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/order_field_config_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/order_field_config_migration.sql
@@ -5,19 +5,19 @@
-- 1. Widen order_number columns from VARCHAR(10) to VARCHAR(50)
-- Preserve original NULL/NOT NULL constraints per table
-ALTER TABLE activation_attempts MODIFY order_number VARCHAR(50) NOT NULL;
-ALTER TABLE active_sessions MODIFY order_number VARCHAR(50) NULL;
-ALTER TABLE hardware_info MODIFY order_number VARCHAR(50) NOT NULL;
-ALTER TABLE qc_compliance_results MODIFY order_number VARCHAR(50) NOT NULL;
+ALTER TABLE `#__activation_attempts` MODIFY order_number VARCHAR(50) NOT NULL;
+ALTER TABLE `#__active_sessions` MODIFY order_number VARCHAR(50) NULL;
+ALTER TABLE `#__hardware_info` MODIFY order_number VARCHAR(50) NOT NULL;
+ALTER TABLE `#__qc_compliance_results` MODIFY order_number VARCHAR(50) NOT NULL;
-- hardware_collection_log: only alter if table exists (not present in all installations)
SET @tbl_exists = (SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'hardware_collection_log');
-SET @sql = IF(@tbl_exists > 0, 'ALTER TABLE hardware_collection_log MODIFY order_number VARCHAR(50) NOT NULL', 'SELECT 1');
+SET @sql = IF(@tbl_exists > 0, 'ALTER TABLE `#__hardware_collection_log` MODIFY order_number VARCHAR(50) NOT NULL', 'SELECT 1');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 2. Seed system_config with order field configuration defaults
-INSERT INTO system_config (config_key, config_value, description, updated_at)
+INSERT INTO `#__system_config` (config_key, config_value, description, updated_at)
VALUES
('order_field_label_en', 'Order Number', 'Display label for the order field (English)', NOW()),
('order_field_label_ru', 'Номер заказа', 'Display label for the order field (Russian)', NOW()),
diff --git a/FINAL_PRODUCTION_SYSTEM/database/product_variants_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/product_variants_migration.sql
index da6ec04..42f324b 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/product_variants_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/product_variants_migration.sql
@@ -2,7 +2,7 @@
-- Adds partition layout QC checking via product lines → variants → partition templates
-- ── Product Lines (linked to order number patterns) ──────────────
-CREATE TABLE IF NOT EXISTS product_lines (
+CREATE TABLE IF NOT EXISTS `#__product_lines` (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
order_pattern VARCHAR(50) NOT NULL COMMENT 'Order number prefix to match, e.g. ЭЛ00-',
@@ -16,7 +16,7 @@ CREATE TABLE IF NOT EXISTS product_lines (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ── Product Variants (disk size ranges within a product line) ────
-CREATE TABLE IF NOT EXISTS product_variants (
+CREATE TABLE IF NOT EXISTS `#__product_variants` (
id INT AUTO_INCREMENT PRIMARY KEY,
line_id INT NOT NULL,
name VARCHAR(100) NOT NULL COMMENT 'e.g. RTX 1TB, RTX 512GB',
@@ -25,12 +25,12 @@ CREATE TABLE IF NOT EXISTS product_variants (
is_active TINYINT(1) NOT NULL DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
- FOREIGN KEY (line_id) REFERENCES product_lines(id) ON DELETE CASCADE,
+ FOREIGN KEY (line_id) REFERENCES `#__product_lines`(id) ON DELETE CASCADE,
UNIQUE KEY uk_line_name (line_id, name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ── Partition Templates (expected layout per variant) ────────────
-CREATE TABLE IF NOT EXISTS product_variant_partitions (
+CREATE TABLE IF NOT EXISTS `#__product_variant_partitions` (
id INT AUTO_INCREMENT PRIMARY KEY,
variant_id INT NOT NULL,
partition_order INT NOT NULL COMMENT 'Expected position on disk: 1, 2, 3...',
@@ -39,16 +39,16 @@ CREATE TABLE IF NOT EXISTS product_variant_partitions (
expected_size_mb INT NOT NULL,
tolerance_percent DECIMAL(5,2) NOT NULL DEFAULT 1.00 COMMENT 'Allowed deviation % per partition',
is_flexible TINYINT(1) NOT NULL DEFAULT 0 COMMENT '1 = absorbs remaining space (e.g. Data partition)',
- FOREIGN KEY (variant_id) REFERENCES product_variants(id) ON DELETE CASCADE,
+ FOREIGN KEY (variant_id) REFERENCES `#__product_variants`(id) ON DELETE CASCADE,
UNIQUE KEY uk_variant_order (variant_id, partition_order)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ── Extend QC compliance results to include partition_layout ─────
-ALTER TABLE qc_compliance_results
+ALTER TABLE `#__qc_compliance_results`
MODIFY COLUMN check_type ENUM('bios_version','secure_boot','hackbgrt_boot_priority','partition_layout') NOT NULL;
-- ── Add detected variant tracking to hardware_info ───────────────
-ALTER TABLE hardware_info
+ALTER TABLE `#__hardware_info`
ADD COLUMN IF NOT EXISTS detected_variant_id INT DEFAULT NULL,
ADD COLUMN IF NOT EXISTS detected_variant_name VARCHAR(100) DEFAULT NULL,
ADD COLUMN IF NOT EXISTS detected_line_name VARCHAR(100) DEFAULT NULL;
diff --git a/FINAL_PRODUCTION_SYSTEM/database/production_tracking_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/production_tracking_migration.sql
index 8f247aa..8d4da60 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/production_tracking_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/production_tracking_migration.sql
@@ -7,7 +7,7 @@
-- ── 1. Computer Build Reports (CBR) ────────────────────────
-- Structured per-machine reports for auditing and compliance.
-CREATE TABLE IF NOT EXISTS computer_build_reports (
+CREATE TABLE IF NOT EXISTS `#__computer_build_reports` (
id INT AUTO_INCREMENT PRIMARY KEY,
report_uuid VARCHAR(36) NOT NULL UNIQUE COMMENT 'UUID v4 for external reference',
activation_attempt_id INT DEFAULT NULL,
@@ -80,7 +80,7 @@ CREATE TABLE IF NOT EXISTS computer_build_reports (
-- ── 2. Key Pool Management ─────────────────────────────────
-- Alert thresholds and replenishment tracking per product edition.
-CREATE TABLE IF NOT EXISTS key_pool_config (
+CREATE TABLE IF NOT EXISTS `#__key_pool_config` (
id INT AUTO_INCREMENT PRIMARY KEY,
product_edition VARCHAR(100) NOT NULL UNIQUE COMMENT 'e.g. Windows 11 Pro, Windows 11 Home',
low_threshold INT NOT NULL DEFAULT 10 COMMENT 'Alert when unused keys drop below this',
@@ -96,7 +96,7 @@ CREATE TABLE IF NOT EXISTS key_pool_config (
-- ── 3. Hardware Binding Registry ───────────────────────────
-- Tracks which keys have been used on which hardware.
-CREATE TABLE IF NOT EXISTS hardware_key_bindings (
+CREATE TABLE IF NOT EXISTS `#__hardware_key_bindings` (
id INT AUTO_INCREMENT PRIMARY KEY,
product_key_id INT NOT NULL COMMENT 'FK to oem_keys',
device_fingerprint VARCHAR(500) NOT NULL,
@@ -118,7 +118,7 @@ CREATE TABLE IF NOT EXISTS hardware_key_bindings (
-- ── 4. DPK Import Batches ──────────────────────────────────
-- Tracks bulk key imports from Microsoft OEM deliveries.
-CREATE TABLE IF NOT EXISTS dpk_import_batches (
+CREATE TABLE IF NOT EXISTS `#__dpk_import_batches` (
id INT AUTO_INCREMENT PRIMARY KEY,
batch_name VARCHAR(255) NOT NULL COMMENT 'e.g. "Microsoft Order #12345"',
import_source VARCHAR(100) NOT NULL DEFAULT 'manual' COMMENT 'manual, microsoft_csv, microsoft_xml',
@@ -142,7 +142,7 @@ CREATE TABLE IF NOT EXISTS dpk_import_batches (
-- ── 5. Work Orders (Production Line Tracking) ──────────────
-- Links builds to customer orders, batch production runs.
-CREATE TABLE IF NOT EXISTS work_orders (
+CREATE TABLE IF NOT EXISTS `#__work_orders` (
id INT AUTO_INCREMENT PRIMARY KEY,
work_order_number VARCHAR(50) NOT NULL UNIQUE COMMENT 'Auto-generated or manual',
batch_number VARCHAR(100) DEFAULT NULL COMMENT 'Production batch grouping',
diff --git a/FINAL_PRODUCTION_SYSTEM/database/push_notifications_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/push_notifications_migration.sql
index 5fee47b..061e04e 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/push_notifications_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/push_notifications_migration.sql
@@ -5,7 +5,7 @@
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
-- Push subscriptions: stores browser push endpoints per admin
-CREATE TABLE IF NOT EXISTS `push_subscriptions` (
+CREATE TABLE IF NOT EXISTS `#__push_subscriptions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`admin_id` int(11) NOT NULL,
`endpoint` text NOT NULL,
@@ -18,11 +18,11 @@ CREATE TABLE IF NOT EXISTS `push_subscriptions` (
PRIMARY KEY (`id`),
UNIQUE KEY `uq_admin_endpoint` (`admin_id`, `endpoint`(500)),
KEY `idx_admin_active` (`admin_id`, `is_active`),
- CONSTRAINT `fk_push_sub_admin` FOREIGN KEY (`admin_id`) REFERENCES `admin_users` (`id`) ON DELETE CASCADE
+ CONSTRAINT `fk_push_sub_admin` FOREIGN KEY (`admin_id`) REFERENCES `#__admin_users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Push preferences: per-admin category toggles
-CREATE TABLE IF NOT EXISTS `push_preferences` (
+CREATE TABLE IF NOT EXISTS `#__push_preferences` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`admin_id` int(11) NOT NULL,
`category` varchar(50) NOT NULL,
@@ -30,11 +30,11 @@ CREATE TABLE IF NOT EXISTS `push_preferences` (
PRIMARY KEY (`id`),
UNIQUE KEY `uq_admin_category` (`admin_id`, `category`),
KEY `idx_admin_id` (`admin_id`),
- CONSTRAINT `fk_push_pref_admin` FOREIGN KEY (`admin_id`) REFERENCES `admin_users` (`id`) ON DELETE CASCADE
+ CONSTRAINT `fk_push_pref_admin` FOREIGN KEY (`admin_id`) REFERENCES `#__admin_users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Notifications: bell dropdown history
-CREATE TABLE IF NOT EXISTS `notifications` (
+CREATE TABLE IF NOT EXISTS `#__notifications` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`admin_id` int(11) NOT NULL,
`category` varchar(50) NOT NULL,
@@ -47,11 +47,11 @@ CREATE TABLE IF NOT EXISTS `notifications` (
PRIMARY KEY (`id`),
KEY `idx_admin_read` (`admin_id`, `is_read`),
KEY `idx_admin_created` (`admin_id`, `created_at` DESC),
- CONSTRAINT `fk_notif_admin` FOREIGN KEY (`admin_id`) REFERENCES `admin_users` (`id`) ON DELETE CASCADE
+ CONSTRAINT `fk_notif_admin` FOREIGN KEY (`admin_id`) REFERENCES `#__admin_users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- VAPID keys and push settings in system_config
-INSERT INTO `system_config` (`config_key`, `config_value`, `description`)
+INSERT INTO `#__system_config` (`config_key`, `config_value`, `description`)
VALUES
('vapid_public_key', '', 'VAPID public key for Web Push (auto-generated)'),
('vapid_private_key', '', 'VAPID private key for Web Push (auto-generated)'),
diff --git a/FINAL_PRODUCTION_SYSTEM/database/qc_compliance_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/qc_compliance_migration.sql
index c289c28..2a0a27f 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/qc_compliance_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/qc_compliance_migration.sql
@@ -9,15 +9,15 @@
-- 1. New columns on hardware_info
-- ============================================================
-ALTER TABLE hardware_info ADD COLUMN boot_order JSON NULL COMMENT 'Ordered list of UEFI boot entries from bcdedit' AFTER device_fingerprint;
-ALTER TABLE hardware_info ADD COLUMN hackbgrt_installed TINYINT(1) NULL COMMENT '1=HackBGRT traces found on EFI partition' AFTER boot_order;
-ALTER TABLE hardware_info ADD COLUMN hackbgrt_first_boot TINYINT(1) NULL COMMENT '1=HackBGRT is first boot entry' AFTER hackbgrt_installed;
+ALTER TABLE `#__hardware_info` ADD COLUMN boot_order JSON NULL COMMENT 'Ordered list of UEFI boot entries from bcdedit' AFTER device_fingerprint;
+ALTER TABLE `#__hardware_info` ADD COLUMN hackbgrt_installed TINYINT(1) NULL COMMENT '1=HackBGRT traces found on EFI partition' AFTER boot_order;
+ALTER TABLE `#__hardware_info` ADD COLUMN hackbgrt_first_boot TINYINT(1) NULL COMMENT '1=HackBGRT is first boot entry' AFTER hackbgrt_installed;
-- ============================================================
-- 2. QC Global Settings (key-value)
-- ============================================================
-CREATE TABLE IF NOT EXISTS qc_global_settings (
+CREATE TABLE IF NOT EXISTS `#__qc_global_settings` (
id INT AUTO_INCREMENT PRIMARY KEY,
setting_key VARCHAR(100) NOT NULL UNIQUE,
setting_value TEXT NOT NULL,
@@ -26,7 +26,7 @@ CREATE TABLE IF NOT EXISTS qc_global_settings (
updated_by INT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-INSERT INTO qc_global_settings (setting_key, setting_value, description) VALUES
+INSERT INTO `#__qc_global_settings` (setting_key, setting_value, description) VALUES
('qc_enabled', '0', 'Enable hardware compliance checking during activation (0=off, 1=on)'),
('default_bios_enforcement', '1', 'Default BIOS version check enforcement (0=disabled, 1=info, 2=warning, 3=blocking)'),
('default_secure_boot_enforcement', '1', 'Default Secure Boot check enforcement (0=disabled, 1=info, 2=warning, 3=blocking)'),
@@ -37,7 +37,7 @@ INSERT INTO qc_global_settings (setting_key, setting_value, description) VALUES
-- 3. Manufacturer Defaults
-- ============================================================
-CREATE TABLE IF NOT EXISTS qc_manufacturer_defaults (
+CREATE TABLE IF NOT EXISTS `#__qc_manufacturer_defaults` (
id INT AUTO_INCREMENT PRIMARY KEY,
manufacturer VARCHAR(100) NOT NULL UNIQUE,
secure_boot_required TINYINT(1) DEFAULT 1 COMMENT '1=Secure Boot must be ON',
@@ -54,10 +54,10 @@ CREATE TABLE IF NOT EXISTS qc_manufacturer_defaults (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ============================================================
--- 4. Motherboard Registry (auto-populated from hardware_info)
+-- 4. Motherboard Registry (auto-populated from `#__hardware_info`)
-- ============================================================
-CREATE TABLE IF NOT EXISTS qc_motherboard_registry (
+CREATE TABLE IF NOT EXISTS `#__qc_motherboard_registry` (
id INT AUTO_INCREMENT PRIMARY KEY,
manufacturer VARCHAR(100) NOT NULL,
product VARCHAR(100) NOT NULL,
@@ -85,7 +85,7 @@ CREATE TABLE IF NOT EXISTS qc_motherboard_registry (
-- 5. Compliance Results (per check, per hardware submission)
-- ============================================================
-CREATE TABLE IF NOT EXISTS qc_compliance_results (
+CREATE TABLE IF NOT EXISTS `#__qc_compliance_results` (
id INT AUTO_INCREMENT PRIMARY KEY,
hardware_info_id INT NOT NULL,
order_number VARCHAR(10) NOT NULL,
@@ -99,7 +99,7 @@ CREATE TABLE IF NOT EXISTS qc_compliance_results (
motherboard_registry_id INT NULL,
is_retroactive TINYINT(1) DEFAULT 0 COMMENT '1=created by retroactive recheck',
checked_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (hardware_info_id) REFERENCES hardware_info(id) ON DELETE CASCADE,
+ FOREIGN KEY (hardware_info_id) REFERENCES `#__hardware_info`(id) ON DELETE CASCADE,
INDEX idx_hardware_id (hardware_info_id),
INDEX idx_order_number (order_number),
INDEX idx_check_result (check_result),
@@ -110,12 +110,12 @@ CREATE TABLE IF NOT EXISTS qc_compliance_results (
-- 6. ACL: Quality Control permission category + permissions
-- ============================================================
-INSERT INTO acl_permission_categories (category_key, display_name, icon, sort_order) VALUES
+INSERT INTO `#__acl_permission_categories` (category_key, display_name, icon, sort_order) VALUES
('quality_control', 'Quality Control', NULL, 46);
-SET @qc_cat_id = (SELECT id FROM acl_permission_categories WHERE category_key = 'quality_control');
+SET @qc_cat_id = (SELECT id FROM `#__acl_permission_categories` WHERE category_key = 'quality_control');
-INSERT INTO acl_permissions (permission_key, display_name, description, category_id, resource_type, action_type, is_dangerous) VALUES
+INSERT INTO `#__acl_permissions` (permission_key, display_name, description, category_id, resource_type, action_type, is_dangerous) VALUES
('view_compliance', 'View Compliance Results', 'View QC compliance check results and statistics', @qc_cat_id, 'compliance', 'view', 0),
('manage_compliance_rules', 'Manage Compliance Rules', 'Configure motherboard registry and compliance enforcement rules', @qc_cat_id, 'compliance', 'manage', 0),
('manage_compliance', 'Manage QC System', 'Toggle QC feature, trigger retroactive checks, modify global settings', @qc_cat_id, 'compliance', 'manage', 1);
@@ -123,23 +123,23 @@ INSERT INTO acl_permissions (permission_key, display_name, description, category
-- Grant to super_admin (already gets everything via CROSS JOIN, but explicit for clarity on new installs)
INSERT IGNORE INTO acl_role_permissions (role_id, permission_id)
SELECT r.id, p.id
-FROM acl_roles r CROSS JOIN acl_permissions p
+FROM `#__acl_roles` r CROSS JOIN `#__acl_permissions` p
WHERE r.role_name = 'super_admin' AND p.permission_key IN ('view_compliance', 'manage_compliance_rules', 'manage_compliance');
-- Grant to admin: view + manage rules
INSERT IGNORE INTO acl_role_permissions (role_id, permission_id)
SELECT r.id, p.id
-FROM acl_roles r, acl_permissions p
+FROM `#__acl_roles` r, acl_permissions p
WHERE r.role_name = 'admin' AND p.permission_key IN ('view_compliance', 'manage_compliance_rules');
-- Grant to qc_inspector: view only
INSERT IGNORE INTO acl_role_permissions (role_id, permission_id)
SELECT r.id, p.id
-FROM acl_roles r, acl_permissions p
+FROM `#__acl_roles` r, acl_permissions p
WHERE r.role_name = 'qc_inspector' AND p.permission_key IN ('view_compliance');
-- Grant to dept_manager: view only
INSERT IGNORE INTO acl_role_permissions (role_id, permission_id)
SELECT r.id, p.id
-FROM acl_roles r, acl_permissions p
+FROM `#__acl_roles` r, acl_permissions p
WHERE r.role_name = 'dept_manager' AND p.permission_key IN ('view_compliance');
diff --git a/FINAL_PRODUCTION_SYSTEM/database/rate_limiting_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/rate_limiting_migration.sql
index e037a26..bc4293f 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/rate_limiting_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/rate_limiting_migration.sql
@@ -6,7 +6,7 @@
-- Table: rate_limit_violations
-- Logs when API rate limits are exceeded for security monitoring
-CREATE TABLE IF NOT EXISTS `rate_limit_violations` (
+CREATE TABLE IF NOT EXISTS `#__rate_limit_violations` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`identifier` VARCHAR(100) NOT NULL COMMENT 'IP address or user ID',
`action` VARCHAR(50) NOT NULL COMMENT 'Endpoint action (login, get-key, etc.)',
@@ -26,7 +26,7 @@ CREATE TABLE IF NOT EXISTS `rate_limit_violations` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Rate limit violation log for security monitoring';
-- System configuration for rate limiting
-INSERT INTO `system_config` (`config_key`, `config_value`, `description`) VALUES
+INSERT INTO `#__system_config` (`config_key`, `config_value`, `description`) VALUES
('rate_limit_enabled', '1', 'Enable API rate limiting (1=yes, 0=no)'),
('rate_limit_global_per_minute', '100', 'Max requests per minute per IP (all endpoints)'),
('rate_limit_login_per_hour', '20', 'Max login attempts per hour per IP'),
diff --git a/FINAL_PRODUCTION_SYSTEM/database/rbac_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/rbac_migration.sql
index 0c50dc4..25f5888 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/rbac_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/rbac_migration.sql
@@ -13,7 +13,7 @@ SET @role_column_exists = (SELECT COUNT(*) FROM information_schema.COLUMNS
-- If role column doesn't exist, create it
SET @sql = IF(@role_column_exists = 0,
- 'ALTER TABLE `admin_users` ADD COLUMN `role` ENUM(''super_admin'', ''admin'', ''viewer'') DEFAULT ''admin'' COMMENT ''Admin role for RBAC''',
+ 'ALTER TABLE `#__admin_users` ADD COLUMN `role` ENUM(''super_admin'', ''admin'', ''viewer'') DEFAULT ''admin'' COMMENT ''Admin role for RBAC''',
'SELECT "Role column already exists"');
PREPARE stmt FROM @sql;
@@ -21,12 +21,12 @@ EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- Add role tracking to admin_activity_log
-ALTER TABLE `admin_activity_log`
+ALTER TABLE `#__admin_activity_log`
ADD COLUMN IF NOT EXISTS `admin_role` ENUM('super_admin', 'admin', 'viewer') NULL COMMENT 'Role of admin at time of action' AFTER `user_agent`,
ADD INDEX IF NOT EXISTS `idx_admin_role` (`admin_role`);
--- Create table for permission audit trail
-CREATE TABLE IF NOT EXISTS `rbac_permission_denials` (
+-- Create table `#__for` permission audit trail
+CREATE TABLE IF NOT EXISTS `#__rbac_permission_denials` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`admin_id` INT NOT NULL COMMENT 'Admin who was denied',
`session_id` VARCHAR(64) NULL COMMENT 'Session ID if available',
@@ -41,24 +41,24 @@ CREATE TABLE IF NOT EXISTS `rbac_permission_denials` (
INDEX `idx_admin_role` (`admin_role`),
INDEX `idx_requested_action` (`requested_action`),
INDEX `idx_denied_at` (`denied_at`),
- FOREIGN KEY (`admin_id`) REFERENCES `admin_users`(`id`) ON DELETE CASCADE
+ FOREIGN KEY (`admin_id`) REFERENCES `#__admin_users`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='RBAC permission denial audit log';
-- System configuration for RBAC
-INSERT INTO `system_config` (`config_key`, `config_value`, `description`) VALUES
+INSERT INTO `#__system_config` (`config_key`, `config_value`, `description`) VALUES
('rbac_enabled', '1', 'Enable role-based access control (1=yes, 0=no)'),
('rbac_log_denials', '1', 'Log permission denials to rbac_permission_denials table'),
('rbac_strict_mode', '1', 'Deny access to undefined permissions (1=yes, 0=allow)')
ON DUPLICATE KEY UPDATE `config_value` = VALUES(`config_value`);
-- Verify we have at least one super_admin account
-SET @super_admin_count = (SELECT COUNT(*) FROM `admin_users` WHERE `role` = 'super_admin');
+SET @super_admin_count = (SELECT COUNT(*) FROM `#__admin_users` WHERE `role` = 'super_admin');
-- If no super_admin exists, promote the first admin to super_admin
-UPDATE `admin_users` SET `role` = 'super_admin'
-WHERE `id` = (SELECT `id` FROM (SELECT `id` FROM `admin_users` ORDER BY `id` ASC LIMIT 1) AS temp)
+UPDATE `#__admin_users` SET `role` = 'super_admin'
+WHERE `id` = (SELECT `id` FROM (SELECT `id` FROM `#__admin_users` ORDER BY `id` ASC LIMIT 1) AS temp)
AND @super_admin_count = 0;
-- Migration complete
SELECT 'Migration: RBAC tables and permissions configured successfully' AS status;
-SELECT CONCAT('Super admins: ', COUNT(*)) AS super_admin_count FROM `admin_users` WHERE `role` = 'super_admin';
+SELECT CONCAT('Super admins: ', COUNT(*)) AS super_admin_count FROM `#__admin_users` WHERE `role` = 'super_admin';
diff --git a/FINAL_PRODUCTION_SYSTEM/database/schema_versions_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/schema_versions_migration.sql
index 7c8c3e3..18b66e3 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/schema_versions_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/schema_versions_migration.sql
@@ -1,7 +1,7 @@
-- Schema Version Tracking
-- Tracks which migration files have been applied to prevent re-running.
-CREATE TABLE IF NOT EXISTS schema_versions (
+CREATE TABLE IF NOT EXISTS `#__schema_versions` (
id INT AUTO_INCREMENT PRIMARY KEY,
version INT NOT NULL,
filename VARCHAR(255) NOT NULL,
diff --git a/FINAL_PRODUCTION_SYSTEM/database/seed_demo_compliance.sql b/FINAL_PRODUCTION_SYSTEM/database/seed_demo_compliance.sql
index fcc4699..42f6de5 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/seed_demo_compliance.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/seed_demo_compliance.sql
@@ -8,49 +8,49 @@
-- 256GB: OS 120000 MB = 117.1875 GB, Data 121736 MB = 118.8828125 GB
-- 1. Delete old compliance results to start fresh
-DELETE FROM qc_compliance_results;
+DELETE FROM `#__qc_compliance_results`;
-- 2. Update existing hardware_info order numbers to follow product line patterns
-- Also inject complete_disk_layout JSON for partition checking
-- PASS: Good 512 GB layout (ЭЛ00-100001)
-UPDATE hardware_info SET order_number = 'ЭЛ00-100001',
+UPDATE `#__hardware_info` SET order_number = 'ЭЛ00-100001',
complete_disk_layout = '[{"disk_number":0,"disk_model":"Samsung SSD 970 EVO 500GB","disk_size_gb":465.76,"partition_style":"GPT","partitions":[{"partition_number":0,"size_gb":0.25390625,"partition_purpose":"EFI","file_system":"FAT32"},{"partition_number":1,"size_gb":0.015625,"partition_purpose":"MSR","file_system":null},{"partition_number":2,"size_gb":195.3125,"partition_purpose":"OS","file_system":"NTFS","drive_letter":"C:"},{"partition_number":3,"size_gb":1.46484375,"partition_purpose":"Recovery","file_system":"NTFS"},{"partition_number":4,"size_gb":276.7578125,"partition_purpose":"Data","file_system":"NTFS","drive_letter":"D:"},{"partition_number":5,"size_gb":0.1953125,"partition_purpose":"Other","file_system":"FAT32","volume_name":"BIOS","drive_letter":"E:"}]}]'
-WHERE id = (SELECT id FROM (SELECT MIN(id) AS id FROM hardware_info) t);
+WHERE id = (SELECT id FROM (SELECT MIN(id) AS id FROM `#__hardware_info`) t);
-- PASS: Good 512 GB layout (ЭЛ00-100002)
-UPDATE hardware_info SET order_number = 'ЭЛ00-100002',
+UPDATE `#__hardware_info` SET order_number = 'ЭЛ00-100002',
complete_disk_layout = '[{"disk_number":0,"disk_model":"WD Blue SN570 500GB","disk_size_gb":465.76,"partition_style":"GPT","partitions":[{"partition_number":0,"size_gb":0.25390625,"partition_purpose":"EFI","file_system":"FAT32"},{"partition_number":1,"size_gb":0.015625,"partition_purpose":"MSR","file_system":null},{"partition_number":2,"size_gb":195.3125,"partition_purpose":"OS","file_system":"NTFS","drive_letter":"C:"},{"partition_number":3,"size_gb":1.46484375,"partition_purpose":"Recovery","file_system":"NTFS"},{"partition_number":4,"size_gb":276.7578125,"partition_purpose":"Data","file_system":"NTFS","drive_letter":"D:"},{"partition_number":5,"size_gb":0.1953125,"partition_purpose":"Other","file_system":"FAT32","volume_name":"BIOS","drive_letter":"E:"}]}]'
-WHERE id = (SELECT id FROM (SELECT id FROM hardware_info ORDER BY id LIMIT 1 OFFSET 1) t);
+WHERE id = (SELECT id FROM (SELECT id FROM `#__hardware_info` ORDER BY id LIMIT 1 OFFSET 1) t);
-- PASS: Good 1 TB layout (ЛЕ00-200001)
-UPDATE hardware_info SET order_number = 'ЛЕ00-200001',
+UPDATE `#__hardware_info` SET order_number = 'ЛЕ00-200001',
complete_disk_layout = '[{"disk_number":0,"disk_model":"Kingston A2000 1TB","disk_size_gb":931.51,"partition_style":"GPT","partitions":[{"partition_number":0,"size_gb":0.25390625,"partition_purpose":"EFI","file_system":"FAT32"},{"partition_number":1,"size_gb":0.015625,"partition_purpose":"MSR","file_system":null},{"partition_number":2,"size_gb":390.625,"partition_purpose":"OS","file_system":"NTFS","drive_letter":"C:"},{"partition_number":3,"size_gb":1.46484375,"partition_purpose":"Recovery","file_system":"NTFS"},{"partition_number":4,"size_gb":540.0,"partition_purpose":"Data","file_system":"NTFS","drive_letter":"D:"},{"partition_number":5,"size_gb":0.1953125,"partition_purpose":"Other","file_system":"FAT32","volume_name":"BIOS","drive_letter":"E:"}]}]'
-WHERE id = (SELECT id FROM (SELECT id FROM hardware_info ORDER BY id LIMIT 1 OFFSET 2) t);
+WHERE id = (SELECT id FROM (SELECT id FROM `#__hardware_info` ORDER BY id LIMIT 1 OFFSET 2) t);
-- WARNING: 256 GB layout with Data partition slightly too small (ЛЕ00-200002)
-- Data is 113.77 GB = 116500 MB but template requires 121736 MB minimum
-UPDATE hardware_info SET order_number = 'ЛЕ00-200002',
+UPDATE `#__hardware_info` SET order_number = 'ЛЕ00-200002',
complete_disk_layout = '[{"disk_number":0,"disk_model":"Samsung SSD 860 EVO 250GB","disk_size_gb":232.89,"partition_style":"GPT","partitions":[{"partition_number":0,"size_gb":0.25390625,"partition_purpose":"EFI","file_system":"FAT32"},{"partition_number":1,"size_gb":0.015625,"partition_purpose":"MSR","file_system":null},{"partition_number":2,"size_gb":117.1875,"partition_purpose":"OS","file_system":"NTFS","drive_letter":"C:"},{"partition_number":3,"size_gb":1.46484375,"partition_purpose":"Recovery","file_system":"NTFS"},{"partition_number":4,"size_gb":113.77,"partition_purpose":"Data","file_system":"NTFS","drive_letter":"D:"},{"partition_number":5,"size_gb":0.1953125,"partition_purpose":"Other","file_system":"FAT32","volume_name":"BIOS","drive_letter":"E:"}]}]'
-WHERE id = (SELECT id FROM (SELECT id FROM hardware_info ORDER BY id LIMIT 1 OFFSET 3) t);
+WHERE id = (SELECT id FROM (SELECT id FROM `#__hardware_info` ORDER BY id LIMIT 1 OFFSET 3) t);
-- PASS: Good 1 TB layout (ИП00-300001)
-UPDATE hardware_info SET order_number = 'ИП00-300001',
+UPDATE `#__hardware_info` SET order_number = 'ИП00-300001',
complete_disk_layout = '[{"disk_number":0,"disk_model":"Crucial P3 1TB","disk_size_gb":931.51,"partition_style":"GPT","partitions":[{"partition_number":0,"size_gb":0.25390625,"partition_purpose":"EFI","file_system":"FAT32"},{"partition_number":1,"size_gb":0.015625,"partition_purpose":"MSR","file_system":null},{"partition_number":2,"size_gb":390.625,"partition_purpose":"OS","file_system":"NTFS","drive_letter":"C:"},{"partition_number":3,"size_gb":1.46484375,"partition_purpose":"Recovery","file_system":"NTFS"},{"partition_number":4,"size_gb":540.0,"partition_purpose":"Data","file_system":"NTFS","drive_letter":"D:"},{"partition_number":5,"size_gb":0.1953125,"partition_purpose":"Other","file_system":"FAT32","volume_name":"BIOS","drive_letter":"E:"}]}]'
-WHERE id = (SELECT id FROM (SELECT id FROM hardware_info ORDER BY id LIMIT 1 OFFSET 4) t);
+WHERE id = (SELECT id FROM (SELECT id FROM `#__hardware_info` ORDER BY id LIMIT 1 OFFSET 4) t);
-- FAIL: Bad 512 GB layout — wrong OS size (150 GB instead of ~195 GB)
-UPDATE hardware_info SET order_number = 'ИП00-300002',
+UPDATE `#__hardware_info` SET order_number = 'ИП00-300002',
complete_disk_layout = '[{"disk_number":0,"disk_model":"WD Blue SN550 500GB","disk_size_gb":465.76,"partition_style":"GPT","partitions":[{"partition_number":0,"size_gb":0.25390625,"partition_purpose":"EFI","file_system":"FAT32"},{"partition_number":1,"size_gb":0.015625,"partition_purpose":"MSR","file_system":null},{"partition_number":2,"size_gb":146.484375,"partition_purpose":"OS","file_system":"NTFS","drive_letter":"C:"},{"partition_number":3,"size_gb":1.46484375,"partition_purpose":"Recovery","file_system":"NTFS"},{"partition_number":4,"size_gb":317.35,"partition_purpose":"Data","file_system":"NTFS","drive_letter":"D:"},{"partition_number":5,"size_gb":0.1953125,"partition_purpose":"Other","file_system":"FAT32","volume_name":"BIOS","drive_letter":"E:"}]}]'
-WHERE id = (SELECT id FROM (SELECT id FROM hardware_info ORDER BY id LIMIT 1 OFFSET 5) t);
+WHERE id = (SELECT id FROM (SELECT id FROM `#__hardware_info` ORDER BY id LIMIT 1 OFFSET 5) t);
-- No disk layout data (ЭЛ00-100003) — will show "no data" for partition check
-UPDATE hardware_info SET order_number = 'ЭЛ00-100003'
+UPDATE `#__hardware_info` SET order_number = 'ЭЛ00-100003'
WHERE order_number NOT LIKE 'ЭЛ00-%' AND order_number NOT LIKE 'ЛЕ00-%' AND order_number NOT LIKE 'ИП00-%'
- AND id = (SELECT id FROM (SELECT id FROM hardware_info WHERE order_number NOT LIKE 'ЭЛ00-%' AND order_number NOT LIKE 'ЛЕ00-%' AND order_number NOT LIKE 'ИП00-%' ORDER BY id LIMIT 1) t);
+ AND id = (SELECT id FROM (SELECT id FROM `#__hardware_info` WHERE order_number NOT LIKE 'ЭЛ00-%' AND order_number NOT LIKE 'ЛЕ00-%' AND order_number NOT LIKE 'ИП00-%' ORDER BY id LIMIT 1) t);
-UPDATE hardware_info SET order_number = 'ЛЕ00-200003'
+UPDATE `#__hardware_info` SET order_number = 'ЛЕ00-200003'
WHERE order_number NOT LIKE 'ЭЛ00-%' AND order_number NOT LIKE 'ЛЕ00-%' AND order_number NOT LIKE 'ИП00-%'
- AND id = (SELECT id FROM (SELECT id FROM hardware_info WHERE order_number NOT LIKE 'ЭЛ00-%' AND order_number NOT LIKE 'ЛЕ00-%' AND order_number NOT LIKE 'ИП00-%' ORDER BY id LIMIT 1) t);
+ AND id = (SELECT id FROM (SELECT id FROM `#__hardware_info` WHERE order_number NOT LIKE 'ЭЛ00-%' AND order_number NOT LIKE 'ЛЕ00-%' AND order_number NOT LIKE 'ИП00-%' ORDER BY id LIMIT 1) t);
-- Done. Now trigger "Recheck Historical" from the admin UI to regenerate all compliance results.
diff --git a/FINAL_PRODUCTION_SYSTEM/database/seed_variants.sql b/FINAL_PRODUCTION_SYSTEM/database/seed_variants.sql
index 3684d8d..7878914 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/seed_variants.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/seed_variants.sql
@@ -2,9 +2,9 @@
-- Disk sizes: 256 GB (~238 GB = 243712 MB), 512 GB (~474 GB = 485376 MB), 1 TB (~931 GB = 953344 MB), 2 TB (~1862 GB = 1907200 MB)
-- Get product line IDs
-SET @pl1 = (SELECT id FROM product_lines WHERE order_pattern = 'ЭЛ00-######');
-SET @pl2 = (SELECT id FROM product_lines WHERE order_pattern = 'ЛЕ00-######');
-SET @pl3 = (SELECT id FROM product_lines WHERE order_pattern = 'ИП00-######');
+SET @pl1 = (SELECT id FROM `#__product_lines` WHERE order_pattern = 'ЭЛ00-######');
+SET @pl2 = (SELECT id FROM `#__product_lines` WHERE order_pattern = 'ЛЕ00-######');
+SET @pl3 = (SELECT id FROM `#__product_lines` WHERE order_pattern = 'ИП00-######');
-- ── Variants for Marketplace 1 ──────────────────────────────────
INSERT IGNORE INTO product_variants (line_id, name, disk_size_min_mb, disk_size_max_mb) VALUES
@@ -39,9 +39,9 @@ INSERT IGNORE INTO product_variants (line_id, name, disk_size_min_mb, disk_size_
-- 2 TB ~ 1907200 MB total: EFI 260 + MSR 16 + OS 500000 + Recovery 1500 + Data 1405224 + BIOS 200
-- ── 256 GB variants (all 3 product lines) ────────────────────────
-INSERT INTO product_variant_partitions (variant_id, partition_order, partition_name, partition_type, expected_size_mb, tolerance_percent, is_flexible)
+INSERT INTO `#__product_variant_partitions` (variant_id, partition_order, partition_name, partition_type, expected_size_mb, tolerance_percent, is_flexible)
SELECT v.id, p.partition_order, p.partition_name, p.partition_type, p.expected_size_mb, p.tolerance_percent, p.is_flexible
-FROM product_variants v
+FROM `#__product_variants` v
CROSS JOIN (
SELECT 1 AS partition_order, 'EFI' AS partition_name, 'EFI System' AS partition_type, 260 AS expected_size_mb, 1.00 AS tolerance_percent, 0 AS is_flexible UNION ALL
SELECT 2, 'MSR', 'Microsoft Reserved', 16, 1.00, 0 UNION ALL
@@ -54,9 +54,9 @@ WHERE v.name = '256 GB'
ON DUPLICATE KEY UPDATE expected_size_mb = VALUES(expected_size_mb), partition_type = VALUES(partition_type), is_flexible = VALUES(is_flexible);
-- ── 512 GB variants (all 3 product lines) ────────────────────────
-INSERT INTO product_variant_partitions (variant_id, partition_order, partition_name, partition_type, expected_size_mb, tolerance_percent, is_flexible)
+INSERT INTO `#__product_variant_partitions` (variant_id, partition_order, partition_name, partition_type, expected_size_mb, tolerance_percent, is_flexible)
SELECT v.id, p.partition_order, p.partition_name, p.partition_type, p.expected_size_mb, p.tolerance_percent, p.is_flexible
-FROM product_variants v
+FROM `#__product_variants` v
CROSS JOIN (
SELECT 1 AS partition_order, 'EFI' AS partition_name, 'EFI System' AS partition_type, 260 AS expected_size_mb, 1.00 AS tolerance_percent, 0 AS is_flexible UNION ALL
SELECT 2, 'MSR', 'Microsoft Reserved', 16, 1.00, 0 UNION ALL
@@ -69,9 +69,9 @@ WHERE v.name = '512 GB'
ON DUPLICATE KEY UPDATE expected_size_mb = VALUES(expected_size_mb), partition_type = VALUES(partition_type), is_flexible = VALUES(is_flexible);
-- ── 1 TB variants (all 3 product lines) ──────────────────────────
-INSERT INTO product_variant_partitions (variant_id, partition_order, partition_name, partition_type, expected_size_mb, tolerance_percent, is_flexible)
+INSERT INTO `#__product_variant_partitions` (variant_id, partition_order, partition_name, partition_type, expected_size_mb, tolerance_percent, is_flexible)
SELECT v.id, p.partition_order, p.partition_name, p.partition_type, p.expected_size_mb, p.tolerance_percent, p.is_flexible
-FROM product_variants v
+FROM `#__product_variants` v
CROSS JOIN (
SELECT 1 AS partition_order, 'EFI' AS partition_name, 'EFI System' AS partition_type, 260 AS expected_size_mb, 1.00 AS tolerance_percent, 0 AS is_flexible UNION ALL
SELECT 2, 'MSR', 'Microsoft Reserved', 16, 1.00, 0 UNION ALL
@@ -84,9 +84,9 @@ WHERE v.name = '1 TB'
ON DUPLICATE KEY UPDATE expected_size_mb = VALUES(expected_size_mb), partition_type = VALUES(partition_type), is_flexible = VALUES(is_flexible);
-- ── 2 TB variants (all 3 product lines) ──────────────────────────
-INSERT INTO product_variant_partitions (variant_id, partition_order, partition_name, partition_type, expected_size_mb, tolerance_percent, is_flexible)
+INSERT INTO `#__product_variant_partitions` (variant_id, partition_order, partition_name, partition_type, expected_size_mb, tolerance_percent, is_flexible)
SELECT v.id, p.partition_order, p.partition_name, p.partition_type, p.expected_size_mb, p.tolerance_percent, p.is_flexible
-FROM product_variants v
+FROM `#__product_variants` v
CROSS JOIN (
SELECT 1 AS partition_order, 'EFI' AS partition_name, 'EFI System' AS partition_type, 260 AS expected_size_mb, 1.00 AS tolerance_percent, 0 AS is_flexible UNION ALL
SELECT 2, 'MSR', 'Microsoft Reserved', 16, 1.00, 0 UNION ALL
diff --git a/FINAL_PRODUCTION_SYSTEM/database/task_pipeline_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/task_pipeline_migration.sql
index 5ad75bf..3ec8067 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/task_pipeline_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/task_pipeline_migration.sql
@@ -7,7 +7,7 @@
-- =============================================================
-- Global task template library (reusable across product lines)
-CREATE TABLE IF NOT EXISTS task_templates (
+CREATE TABLE IF NOT EXISTS `#__task_templates` (
id INT AUTO_INCREMENT PRIMARY KEY,
task_key VARCHAR(50) NOT NULL UNIQUE COMMENT 'Internal identifier (e.g. hardware_collection)',
task_name VARCHAR(100) NOT NULL COMMENT 'Display name',
@@ -23,7 +23,7 @@ CREATE TABLE IF NOT EXISTS task_templates (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Per-product-line task assignments (which tasks run, in what order, with overrides)
-CREATE TABLE IF NOT EXISTS product_line_tasks (
+CREATE TABLE IF NOT EXISTS `#__product_line_tasks` (
id INT AUTO_INCREMENT PRIMARY KEY,
product_line_id INT NOT NULL COMMENT 'FK to product_lines table',
task_template_id INT NOT NULL COMMENT 'FK to task_templates',
@@ -40,7 +40,7 @@ CREATE TABLE IF NOT EXISTS product_line_tasks (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Task execution log (tracks what ran during each activation)
-CREATE TABLE IF NOT EXISTS task_execution_log (
+CREATE TABLE IF NOT EXISTS `#__task_execution_log` (
id INT AUTO_INCREMENT PRIMARY KEY,
activation_attempt_id INT DEFAULT NULL COMMENT 'FK to activation_attempts',
product_line_id INT DEFAULT NULL,
@@ -62,7 +62,7 @@ CREATE TABLE IF NOT EXISTS task_execution_log (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Seed built-in task templates
-INSERT INTO task_templates (task_key, task_name, task_type, description, default_timeout_seconds, default_on_failure, is_system, icon) VALUES
+INSERT INTO `#__task_templates` (task_key, task_name, task_type, description, default_timeout_seconds, default_on_failure, is_system, icon) VALUES
('hardware_collection', 'Hardware Collection', 'built_in', 'Collect full hardware inventory (MB, CPU, RAM, GPU, disks, network)', 60, 'stop', 1, 'Cpu'),
('qc_compliance', 'QC Compliance Check', 'built_in', 'Run quality control checks (Secure Boot, BIOS version, HackBGRT)', 30, 'stop', 1, 'ShieldCheck'),
('oem_activation', 'OEM Key Activation', 'built_in', 'Request OEM key from server, install and activate Windows', 180, 'stop', 1, 'Key'),
@@ -73,7 +73,7 @@ INSERT INTO task_templates (task_key, task_name, task_type, description, default
ON DUPLICATE KEY UPDATE task_name = VALUES(task_name);
-- Seed example custom tasks (disabled by default, admin can enable per product line)
-INSERT INTO task_templates (task_key, task_name, task_type, description, default_code, default_timeout_seconds, default_on_failure, is_system, icon) VALUES
+INSERT INTO `#__task_templates` (task_key, task_name, task_type, description, default_code, default_timeout_seconds, default_on_failure, is_system, icon) VALUES
('set_power_plan', 'Set Power Plan', 'custom', 'Configure Windows power plan (High Performance, Balanced, etc.)',
'powercfg /setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c # High Performance', 15, 'skip', 0, 'Zap'),
('disable_sleep', 'Disable Sleep Mode', 'custom', 'Prevent the PC from going to sleep',
diff --git a/FINAL_PRODUCTION_SYSTEM/database/temp_password_hash_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/temp_password_hash_migration.sql
index 7188269..e2b4cef 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/temp_password_hash_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/temp_password_hash_migration.sql
@@ -3,7 +3,7 @@
-- and must be followed by running the PHP migration script below.
-- Step 1: Widen column to hold bcrypt hashes (60 chars)
-ALTER TABLE technicians MODIFY COLUMN temp_password VARCHAR(255) DEFAULT NULL;
+ALTER TABLE `#__technicians` MODIFY COLUMN temp_password VARCHAR(255) DEFAULT NULL;
-- Step 2: The existing plaintext temp passwords must be hashed via PHP
-- because SQL cannot generate bcrypt hashes natively.
diff --git a/FINAL_PRODUCTION_SYSTEM/database/unallocated_space_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/unallocated_space_migration.sql
index 1827a70..606a568 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/unallocated_space_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/unallocated_space_migration.sql
@@ -2,7 +2,7 @@
-- Adds configurable max unallocated space limit for partition QC
-- 1. Add per-variant unallocated space limit
-ALTER TABLE product_variants
+ALTER TABLE `#__product_variants`
ADD COLUMN IF NOT EXISTS max_unallocated_mb INT DEFAULT NULL
COMMENT 'Max allowed unallocated disk space in MB (NULL = use global setting)';
diff --git a/FINAL_PRODUCTION_SYSTEM/database/upgrade_system_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/upgrade_system_migration.sql
index d1ee47a..7037a12 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/upgrade_system_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/upgrade_system_migration.sql
@@ -5,7 +5,7 @@
-- verify, rollback. Provides full audit trail.
-- =============================================================
-CREATE TABLE IF NOT EXISTS upgrade_history (
+CREATE TABLE IF NOT EXISTS `#__upgrade_history` (
id INT AUTO_INCREMENT PRIMARY KEY,
from_version VARCHAR(20) NOT NULL,
to_version VARCHAR(20) NOT NULL,
diff --git a/FINAL_PRODUCTION_SYSTEM/database/usb_devices_migration.sql b/FINAL_PRODUCTION_SYSTEM/database/usb_devices_migration.sql
index ca10291..335bdea 100644
--- a/FINAL_PRODUCTION_SYSTEM/database/usb_devices_migration.sql
+++ b/FINAL_PRODUCTION_SYSTEM/database/usb_devices_migration.sql
@@ -4,7 +4,7 @@
-- Tracks registered USB devices for passwordless technician auth.
-- =============================================================
-CREATE TABLE IF NOT EXISTS usb_devices (
+CREATE TABLE IF NOT EXISTS `#__usb_devices` (
device_id INT AUTO_INCREMENT PRIMARY KEY,
device_serial_number VARCHAR(255) NOT NULL UNIQUE,
device_name VARCHAR(255) NOT NULL,
diff --git a/FINAL_PRODUCTION_SYSTEM/functions/acl.php b/FINAL_PRODUCTION_SYSTEM/functions/acl.php
index 8b602f1..8411927 100644
--- a/FINAL_PRODUCTION_SYSTEM/functions/acl.php
+++ b/FINAL_PRODUCTION_SYSTEM/functions/acl.php
@@ -110,7 +110,7 @@ function aclLogDenial($userId, $userType, $permissionKey, $session) {
try {
$stmt = $pdo->prepare("
- INSERT INTO rbac_permission_denials (
+ INSERT INTO `" . t('rbac_permission_denials') . "` (
admin_id, session_id, admin_role, requested_action,
endpoint, ip_address, user_agent
) VALUES (?, ?, ?, ?, ?, ?, ?)
@@ -150,7 +150,7 @@ function aclGetEffectivePermissions($userType, $userId) {
// Check if super_admin
$isSuperAdmin = false;
if ($roleId) {
- $stmt = $pdo->prepare("SELECT role_name FROM acl_roles WHERE id = ?");
+ $stmt = $pdo->prepare("SELECT role_name FROM `" . t('acl_roles') . "` WHERE id = ?");
$stmt->execute([$roleId]);
$role = $stmt->fetch(PDO::FETCH_ASSOC);
if ($role && $role['role_name'] === 'super_admin') {
@@ -159,7 +159,7 @@ function aclGetEffectivePermissions($userType, $userId) {
}
// Get all permissions
- $stmt = $pdo->query("SELECT id, permission_key, display_name, category_id, is_dangerous FROM acl_permissions ORDER BY id");
+ $stmt = $pdo->query("SELECT id, permission_key, display_name, category_id, is_dangerous FROM `" . t('acl_permissions') . "` ORDER BY id");
$allPerms = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Get role permissions
@@ -167,8 +167,8 @@ function aclGetEffectivePermissions($userType, $userId) {
if ($roleId) {
$stmt = $pdo->prepare("
SELECT p.permission_key
- FROM acl_role_permissions rp
- INNER JOIN acl_permissions p ON rp.permission_id = p.id
+ FROM `" . t('acl_role_permissions') . "` rp
+ INNER JOIN `" . t('acl_permissions') . "` p ON rp.permission_id = p.id
WHERE rp.role_id = ?
");
$stmt->execute([$roleId]);
@@ -179,8 +179,8 @@ function aclGetEffectivePermissions($userType, $userId) {
$overrides = [];
$stmt = $pdo->prepare("
SELECT p.permission_key, uo.is_granted, uo.reason, uo.expires_at
- FROM acl_user_overrides uo
- INNER JOIN acl_permissions p ON uo.permission_id = p.id
+ FROM `" . t('acl_user_overrides') . "` uo
+ INNER JOIN `" . t('acl_permissions') . "` p ON uo.permission_id = p.id
WHERE uo.user_type = ? AND uo.user_id = ?
AND (uo.expires_at IS NULL OR uo.expires_at > NOW())
");
@@ -232,12 +232,12 @@ function aclGetEffectivePermissions($userType, $userId) {
function aclGetRoleById($roleId) {
global $pdo;
try {
- $stmt = $pdo->prepare("SELECT * FROM acl_roles WHERE id = ?");
+ $stmt = $pdo->prepare("SELECT * FROM `" . t('acl_roles') . "` WHERE id = ?");
$stmt->execute([$roleId]);
$role = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$role) return null;
- $stmt = $pdo->prepare("SELECT permission_id FROM acl_role_permissions WHERE role_id = ?");
+ $stmt = $pdo->prepare("SELECT permission_id FROM `" . t('acl_role_permissions') . "` WHERE role_id = ?");
$stmt->execute([$roleId]);
$role['permission_ids'] = $stmt->fetchAll(PDO::FETCH_COLUMN);
@@ -255,8 +255,8 @@ function aclListRoles($roleType = null) {
global $pdo;
try {
$sql = "SELECT r.*,
- (SELECT COUNT(*) FROM acl_role_permissions WHERE role_id = r.id) as permission_count
- FROM acl_roles r WHERE 1=1";
+ (SELECT COUNT(*) FROM `" . t('acl_role_permissions') . "` WHERE role_id = r.id) as permission_count
+ FROM `" . t('acl_roles') . "` r WHERE 1=1";
$params = [];
if ($roleType) {
$sql .= " AND r.role_type = ?";
@@ -291,7 +291,7 @@ function aclCreateRole($name, $displayName, $description, $roleType, $color, $pe
$pdo->beginTransaction();
$stmt = $pdo->prepare("
- INSERT INTO acl_roles (role_name, display_name, description, role_type, color, is_system_role, priority, created_by)
+ INSERT INTO `" . t('acl_roles') . "` (role_name, display_name, description, role_type, color, is_system_role, priority, created_by)
VALUES (?, ?, ?, ?, ?, 0, 0, ?)
");
$stmt->execute([$name, $displayName, $description, $roleType, $color, $actorId]);
@@ -299,7 +299,7 @@ function aclCreateRole($name, $displayName, $description, $roleType, $color, $pe
// Assign permissions
if (!empty($permissionIds)) {
- $stmt = $pdo->prepare("INSERT INTO acl_role_permissions (role_id, permission_id, granted_by) VALUES (?, ?, ?)");
+ $stmt = $pdo->prepare("INSERT INTO `" . t('acl_role_permissions') . "` (role_id, permission_id, granted_by) VALUES (?, ?, ?)");
foreach ($permissionIds as $permId) {
$stmt->execute([$roleId, $permId, $actorId]);
}
@@ -329,7 +329,7 @@ function aclUpdateRole($roleId, $data, $actorId) {
// Optimistic locking: reject if role was modified since the client loaded it
if (!empty($data['expected_updated_at'])) {
- $stmt = $pdo->prepare("SELECT updated_at FROM acl_roles WHERE id = ?");
+ $stmt = $pdo->prepare("SELECT updated_at FROM `" . t('acl_roles') . "` WHERE id = ?");
$stmt->execute([$roleId]);
$currentUpdatedAt = $stmt->fetchColumn();
if ($currentUpdatedAt && $currentUpdatedAt !== $data['expected_updated_at']) {
@@ -372,7 +372,7 @@ function aclUpdateRole($roleId, $data, $actorId) {
if (!empty($fields)) {
$params[] = $roleId;
- $stmt = $pdo->prepare("UPDATE acl_roles SET " . implode(', ', $fields) . " WHERE id = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('acl_roles') . "` SET " . implode(', ', $fields) . " WHERE id = ?");
$stmt->execute($params);
}
@@ -381,11 +381,11 @@ function aclUpdateRole($roleId, $data, $actorId) {
$oldPermIds = $role['permission_ids'];
// Clear existing
- $stmt = $pdo->prepare("DELETE FROM acl_role_permissions WHERE role_id = ?");
+ $stmt = $pdo->prepare("DELETE FROM `" . t('acl_role_permissions') . "` WHERE role_id = ?");
$stmt->execute([$roleId]);
// Insert new
- $stmt = $pdo->prepare("INSERT INTO acl_role_permissions (role_id, permission_id, granted_by) VALUES (?, ?, ?)");
+ $stmt = $pdo->prepare("INSERT INTO `" . t('acl_role_permissions') . "` (role_id, permission_id, granted_by) VALUES (?, ?, ?)");
foreach ($data['permission_ids'] as $permId) {
$stmt->execute([$roleId, $permId, $actorId]);
}
@@ -428,7 +428,7 @@ function aclDeleteRole($roleId, $actorId) {
$pdo->beginTransaction();
// role_permissions will cascade delete
- $stmt = $pdo->prepare("DELETE FROM acl_roles WHERE id = ? AND is_system_role = 0");
+ $stmt = $pdo->prepare("DELETE FROM `" . t('acl_roles') . "` WHERE id = ? AND is_system_role = 0");
$stmt->execute([$roleId]);
aclLogChange($actorId, 'delete_role', 'role', $roleId, $role['display_name'],
@@ -480,10 +480,10 @@ function aclAssignPermissions($roleId, $permissionIds, $actorId) {
$oldPermIds = $role['permission_ids'];
- $stmt = $pdo->prepare("DELETE FROM acl_role_permissions WHERE role_id = ?");
+ $stmt = $pdo->prepare("DELETE FROM `" . t('acl_role_permissions') . "` WHERE role_id = ?");
$stmt->execute([$roleId]);
- $stmt = $pdo->prepare("INSERT INTO acl_role_permissions (role_id, permission_id, granted_by) VALUES (?, ?, ?)");
+ $stmt = $pdo->prepare("INSERT INTO `" . t('acl_role_permissions') . "` (role_id, permission_id, granted_by) VALUES (?, ?, ?)");
foreach ($permissionIds as $permId) {
$stmt->execute([$roleId, $permId, $actorId]);
}
@@ -511,7 +511,7 @@ function aclSetUserOverride($userType, $userId, $permissionId, $isGranted, $reas
global $pdo;
try {
$stmt = $pdo->prepare("
- INSERT INTO acl_user_overrides (user_type, user_id, permission_id, is_granted, reason, expires_at, created_by)
+ INSERT INTO `" . t('acl_user_overrides') . "` (user_type, user_id, permission_id, is_granted, reason, expires_at, created_by)
VALUES (?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE is_granted = VALUES(is_granted), reason = VALUES(reason),
expires_at = VALUES(expires_at), created_by = VALUES(created_by),
@@ -520,7 +520,7 @@ function aclSetUserOverride($userType, $userId, $permissionId, $isGranted, $reas
$stmt->execute([$userType, $userId, $permissionId, $isGranted ? 1 : 0, $reason, $expiresAt, $actorId]);
// Get permission key for logging
- $stmt2 = $pdo->prepare("SELECT permission_key FROM acl_permissions WHERE id = ?");
+ $stmt2 = $pdo->prepare("SELECT permission_key FROM `" . t('acl_permissions') . "` WHERE id = ?");
$stmt2->execute([$permissionId]);
$permKey = $stmt2->fetchColumn();
@@ -544,14 +544,14 @@ function aclRemoveUserOverride($userType, $userId, $permissionId, $actorId) {
// Get current override for logging
$stmt = $pdo->prepare("
SELECT uo.*, p.permission_key
- FROM acl_user_overrides uo
- INNER JOIN acl_permissions p ON uo.permission_id = p.id
+ FROM `" . t('acl_user_overrides') . "` uo
+ INNER JOIN `" . t('acl_permissions') . "` p ON uo.permission_id = p.id
WHERE uo.user_type = ? AND uo.user_id = ? AND uo.permission_id = ?
");
$stmt->execute([$userType, $userId, $permissionId]);
$old = $stmt->fetch(PDO::FETCH_ASSOC);
- $stmt = $pdo->prepare("DELETE FROM acl_user_overrides WHERE user_type = ? AND user_id = ? AND permission_id = ?");
+ $stmt = $pdo->prepare("DELETE FROM `" . t('acl_user_overrides') . "` WHERE user_type = ? AND user_id = ? AND permission_id = ?");
$stmt->execute([$userType, $userId, $permissionId]);
if ($old) {
@@ -575,8 +575,8 @@ function aclGetUserOverrides($userType, $userId) {
try {
$stmt = $pdo->prepare("
SELECT uo.*, p.permission_key, p.display_name as permission_name, p.category_id
- FROM acl_user_overrides uo
- INNER JOIN acl_permissions p ON uo.permission_id = p.id
+ FROM `" . t('acl_user_overrides') . "` uo
+ INNER JOIN `" . t('acl_permissions') . "` p ON uo.permission_id = p.id
WHERE uo.user_type = ? AND uo.user_id = ?
ORDER BY p.id
");
@@ -599,11 +599,11 @@ function aclListPermissions($categoryId = null) {
global $pdo;
try {
// Get categories
- $stmt = $pdo->query("SELECT * FROM acl_permission_categories ORDER BY sort_order");
+ $stmt = $pdo->query("SELECT * FROM `" . t('acl_permission_categories') . "` ORDER BY sort_order");
$categories = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Get permissions
- $sql = "SELECT * FROM acl_permissions";
+ $sql = "SELECT * FROM `" . t('acl_permissions') . "`";
$params = [];
if ($categoryId) {
$sql .= " WHERE category_id = ?";
@@ -646,11 +646,11 @@ function aclGetUserRoleId($userType, $userId) {
global $pdo;
try {
if ($userType === 'admin') {
- $stmt = $pdo->prepare("SELECT custom_role_id FROM admin_users WHERE id = ?");
+ $stmt = $pdo->prepare("SELECT custom_role_id FROM `" . t('admin_users') . "` WHERE id = ?");
$stmt->execute([$userId]);
return $stmt->fetchColumn() ?: null;
} elseif ($userType === 'technician') {
- $stmt = $pdo->prepare("SELECT role_id FROM technicians WHERE id = ?");
+ $stmt = $pdo->prepare("SELECT role_id FROM `" . t('technicians') . "` WHERE id = ?");
$stmt->execute([$userId]);
return $stmt->fetchColumn() ?: null;
}
@@ -668,8 +668,8 @@ function aclGetRoleUserCount($roleId) {
try {
$stmt = $pdo->prepare("
SELECT
- (SELECT COUNT(*) FROM admin_users WHERE custom_role_id = ?) +
- (SELECT COUNT(*) FROM technicians WHERE role_id = ?) as total
+ (SELECT COUNT(*) FROM `" . t('admin_users') . "` WHERE custom_role_id = ?) +
+ (SELECT COUNT(*) FROM `" . t('technicians') . "` WHERE role_id = ?) as total
");
$stmt->execute([$roleId, $roleId]);
return (int)$stmt->fetchColumn();
@@ -686,7 +686,7 @@ function aclLogChange($actorId, $action, $targetType, $targetId, $targetName, $o
global $pdo;
try {
$stmt = $pdo->prepare("
- INSERT INTO acl_change_log (actor_id, action, target_type, target_id, target_name, old_value, new_value, ip_address)
+ INSERT INTO `" . t('acl_change_log') . "` (actor_id, action, target_type, target_id, target_name, old_value, new_value, ip_address)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
");
$stmt->execute([
diff --git a/FINAL_PRODUCTION_SYSTEM/functions/admin-helpers.php b/FINAL_PRODUCTION_SYSTEM/functions/admin-helpers.php
index 8e3855e..51bc3d0 100644
--- a/FINAL_PRODUCTION_SYSTEM/functions/admin-helpers.php
+++ b/FINAL_PRODUCTION_SYSTEM/functions/admin-helpers.php
@@ -27,8 +27,8 @@ function validateAdminSession() {
s.id, s.admin_id, s.expires_at, s.last_activity,
u.username, u.full_name, u.role, u.is_active, u.preferred_language,
u.password_changed_at, u.must_change_password
- FROM admin_sessions s
- JOIN admin_users u ON s.admin_id = u.id
+ FROM `" . t('admin_sessions') . "` s
+ JOIN `" . t('admin_users') . "` u ON s.admin_id = u.id
WHERE s.session_token = ? AND s.is_active = 1
");
$stmt->execute([$_SESSION['admin_token']]);
@@ -41,7 +41,7 @@ function validateAdminSession() {
// Check if session expired (hard expiry set at creation time)
if (strtotime($session['expires_at']) < time()) {
- $stmt = $pdo->prepare("UPDATE admin_sessions SET is_active = 0 WHERE id = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('admin_sessions') . "` SET is_active = 0 WHERE id = ?");
$stmt->execute([$session['id']]);
return false;
}
@@ -50,7 +50,7 @@ function validateAdminSession() {
$timeoutMinutes = (int) getConfigWithDefault('admin_session_timeout_minutes', DEFAULT_ADMIN_SESSION_TIMEOUT_MINUTES);
$timeoutSeconds = $timeoutMinutes * 60;
if (strtotime($session['last_activity']) < (time() - $timeoutSeconds)) {
- $stmt = $pdo->prepare("UPDATE admin_sessions SET is_active = 0 WHERE id = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('admin_sessions') . "` SET is_active = 0 WHERE id = ?");
$stmt->execute([$session['id']]);
return false;
}
@@ -71,7 +71,7 @@ function validateAdminSession() {
}
// Update last activity
- $stmt = $pdo->prepare("UPDATE admin_sessions SET last_activity = NOW() WHERE id = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('admin_sessions') . "` SET last_activity = NOW() WHERE id = ?");
$stmt->execute([$session['id']]);
return $session;
@@ -93,7 +93,7 @@ function logAdminActivity($admin_id, $session_id, $action, $description = '') {
global $pdo;
try {
$stmt = $pdo->prepare("
- INSERT INTO admin_activity_log (admin_id, session_id, action, description, ip_address, user_agent)
+ INSERT INTO `" . t('admin_activity_log') . "` (admin_id, session_id, action, description, ip_address, user_agent)
VALUES (?, ?, ?, ?, ?, ?)
");
$stmt->execute([
@@ -125,7 +125,7 @@ function authenticateAdmin($username, $password) {
$lockoutMinutes = (int) getConfigWithDefault('admin_lockout_duration_minutes', DEFAULT_ADMIN_LOCKOUT_MINUTES);
$sessionTimeout = (int) getConfigWithDefault('admin_session_timeout_minutes', DEFAULT_ADMIN_SESSION_TIMEOUT_MINUTES);
- $stmt = $pdo->prepare("SELECT * FROM admin_users WHERE username = ? AND is_active = 1");
+ $stmt = $pdo->prepare("SELECT * FROM `" . t('admin_users') . "` WHERE username = ? AND is_active = 1");
$stmt->execute([$username]);
$admin = $stmt->fetch();
@@ -153,7 +153,7 @@ function authenticateAdmin($username, $password) {
}
$stmt = $pdo->prepare("
- UPDATE admin_users
+ UPDATE `" . t('admin_users') . "`
SET failed_login_attempts = ?, locked_until = ?
WHERE id = ?
");
@@ -172,7 +172,7 @@ function authenticateAdmin($username, $password) {
$expires_at = date('Y-m-d H:i:s', time() + ($sessionTimeout * 60));
$stmt = $pdo->prepare("
- INSERT INTO admin_sessions (admin_id, session_token, ip_address, user_agent, expires_at)
+ INSERT INTO `" . t('admin_sessions') . "` (admin_id, session_token, ip_address, user_agent, expires_at)
VALUES (?, ?, ?, ?, ?)
");
$stmt->execute([
@@ -182,7 +182,7 @@ function authenticateAdmin($username, $password) {
// Reset failed attempts
$stmt = $pdo->prepare("
- UPDATE admin_users
+ UPDATE `" . t('admin_users') . "`
SET failed_login_attempts = 0, locked_until = NULL, last_login = NOW(), last_login_ip = ?
WHERE id = ?
");
@@ -217,7 +217,7 @@ function getUploadErrorMessage(int $errorCode): string {
*/
function saveConfigBatch(PDO $pdo, array $configs, array $descriptions = []): void {
$stmt = $pdo->prepare("
- INSERT INTO system_config (config_key, config_value, description, updated_at)
+ INSERT INTO `" . t('system_config') . "` (config_key, config_value, description, updated_at)
VALUES (?, ?, ?, NOW())
ON DUPLICATE KEY UPDATE config_value = ?, updated_at = NOW()
");
@@ -251,8 +251,8 @@ function isActorSuperAdmin($adminId) {
global $pdo;
try {
$stmt = $pdo->prepare("
- SELECT r.role_name FROM acl_roles r
- INNER JOIN admin_users u ON u.custom_role_id = r.id
+ SELECT r.role_name FROM `" . t('acl_roles') . "` r
+ INNER JOIN `" . t('admin_users') . "` u ON u.custom_role_id = r.id
WHERE u.id = ? AND r.role_name = 'super_admin'
");
$stmt->execute([$adminId]);
diff --git a/FINAL_PRODUCTION_SYSTEM/functions/csv-import.php b/FINAL_PRODUCTION_SYSTEM/functions/csv-import.php
index 11ee83b..91b7cb5 100644
--- a/FINAL_PRODUCTION_SYSTEM/functions/csv-import.php
+++ b/FINAL_PRODUCTION_SYSTEM/functions/csv-import.php
@@ -180,14 +180,14 @@ function importComprehensiveKeyRow($row, $format) {
try {
// Check if key already exists
- $stmt = $pdo->prepare("SELECT id, key_status FROM oem_keys WHERE product_key = ?");
+ $stmt = $pdo->prepare("SELECT id, key_status FROM `" . t('oem_keys') . "` WHERE product_key = ?");
$stmt->execute([$product_key]);
$existing = $stmt->fetch(PDO::FETCH_ASSOC);
if ($existing) {
// Update existing key
$stmt = $pdo->prepare("
- UPDATE oem_keys
+ UPDATE `" . t('oem_keys') . "`
SET key_status = ?, oem_identifier = ?, roll_serial = ?, fail_counter = ?,
last_use_date = ?, last_use_time = ?, first_usage_date = ?, first_usage_time = ?,
updated_at = NOW()
@@ -200,7 +200,7 @@ function importComprehensiveKeyRow($row, $format) {
} else {
// Insert new key
$stmt = $pdo->prepare("
- INSERT INTO oem_keys (product_key, oem_identifier, roll_serial, key_status, fail_counter,
+ INSERT INTO `" . t('oem_keys') . "` (product_key, oem_identifier, roll_serial, key_status, fail_counter,
last_use_date, last_use_time, first_usage_date, first_usage_time, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())
");
@@ -242,7 +242,7 @@ function importStandardKeyRow($row, $format) {
try {
// Check if key already exists
- $stmt = $pdo->prepare("SELECT id, key_status FROM oem_keys WHERE product_key = ?");
+ $stmt = $pdo->prepare("SELECT id, key_status FROM `" . t('oem_keys') . "` WHERE product_key = ?");
$stmt->execute([$product_key]);
$existing = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -250,7 +250,7 @@ function importStandardKeyRow($row, $format) {
// Update existing key if status changed
if ($existing['key_status'] !== $key_status) {
$stmt = $pdo->prepare("
- UPDATE oem_keys
+ UPDATE `" . t('oem_keys') . "`
SET key_status = ?, oem_identifier = ?, barcode = ?, updated_at = NOW()
WHERE product_key = ?
");
@@ -262,7 +262,7 @@ function importStandardKeyRow($row, $format) {
} else {
// Insert new key
$stmt = $pdo->prepare("
- INSERT INTO oem_keys (product_key, oem_identifier, barcode, key_status, roll_serial, created_at)
+ INSERT INTO `" . t('oem_keys') . "` (product_key, oem_identifier, barcode, key_status, roll_serial, created_at)
VALUES (?, ?, ?, ?, 'imported', NOW())
");
$stmt->execute([$product_key, $oem_identifier, $barcode, $key_status]);
@@ -321,7 +321,7 @@ function importActivationAttempts($key_id, $row, $format) {
if (!empty($attempt['attempted_date']) && !empty($attempt['technician_id'])) {
try {
$stmt = $pdo->prepare("
- INSERT INTO activation_attempts
+ INSERT INTO `" . t('activation_attempts') . "`
(key_id, technician_id, order_number, attempt_number, attempt_result,
attempted_date, attempted_time, attempted_at)
VALUES (?, ?, ?, ?, ?, ?, ?, NOW())
diff --git a/FINAL_PRODUCTION_SYSTEM/functions/db-helpers.php b/FINAL_PRODUCTION_SYSTEM/functions/db-helpers.php
new file mode 100644
index 0000000..30e6976
--- /dev/null
+++ b/FINAL_PRODUCTION_SYSTEM/functions/db-helpers.php
@@ -0,0 +1,37 @@
+prepare("SELECT * FROM integrations WHERE integration_key = ?");
+ $stmt = $pdo->prepare("SELECT * FROM `" . t('integrations') . "` WHERE integration_key = ?");
$stmt->execute([$key]);
$row = $stmt->fetch();
@@ -51,10 +51,10 @@ function updateIntegrationStatus(int $id, string $status, ?string $error = null)
try {
if ($error !== null) {
- $stmt = $pdo->prepare("UPDATE integrations SET status = ?, last_error = ?, updated_at = NOW() WHERE id = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('integrations') . "` SET status = ?, last_error = ?, updated_at = NOW() WHERE id = ?");
$stmt->execute([$status, $error, $id]);
} else {
- $stmt = $pdo->prepare("UPDATE integrations SET status = ?, updated_at = NOW() WHERE id = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('integrations') . "` SET status = ?, updated_at = NOW() WHERE id = ?");
$stmt->execute([$status, $id]);
}
@@ -81,7 +81,7 @@ function dispatchIntegrationEvent(string $integrationKey, string $eventType, arr
try {
$stmt = $pdo->prepare("
- INSERT INTO integration_events (integration_id, event_type, payload, status, created_at)
+ INSERT INTO `" . t('integration_events') . "` (integration_id, event_type, payload, status, created_at)
VALUES (?, ?, ?, 'pending', NOW())
");
$stmt->execute([
@@ -106,7 +106,7 @@ function dispatchEventToAll(string $eventType, array $payload): void {
global $pdo;
try {
- $stmt = $pdo->query("SELECT integration_key FROM integrations WHERE enabled = 1");
+ $stmt = $pdo->query("SELECT integration_key FROM `" . t('integrations') . "` WHERE enabled = 1");
$keys = $stmt->fetchAll(PDO::FETCH_COLUMN);
foreach ($keys as $key) {
@@ -124,7 +124,7 @@ function deliverIntegrationEvent(int $eventId, array $integration): void {
global $pdo;
try {
- $stmt = $pdo->prepare("SELECT * FROM integration_events WHERE id = ?");
+ $stmt = $pdo->prepare("SELECT * FROM `" . t('integration_events') . "` WHERE id = ?");
$stmt->execute([$eventId]);
$event = $stmt->fetch();
if (!$event) return;
@@ -137,7 +137,7 @@ function deliverIntegrationEvent(int $eventId, array $integration): void {
$handlerFile = dirname(__DIR__) . "/functions/integrations/{$key}-handler.php";
if (!file_exists($handlerFile)) {
// No handler yet — mark as skipped
- $stmt = $pdo->prepare("UPDATE integration_events SET status = 'skipped', processed_at = NOW(), error_message = 'No handler file' WHERE id = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('integration_events') . "` SET status = 'skipped', processed_at = NOW(), error_message = 'No handler file' WHERE id = ?");
$stmt->execute([$eventId]);
return;
}
@@ -146,7 +146,7 @@ function deliverIntegrationEvent(int $eventId, array $integration): void {
$handlerFunc = 'handle_' . str_replace('-', '_', $key) . '_event';
if (!function_exists($handlerFunc)) {
- $stmt = $pdo->prepare("UPDATE integration_events SET status = 'skipped', processed_at = NOW(), error_message = 'Handler function not found' WHERE id = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('integration_events') . "` SET status = 'skipped', processed_at = NOW(), error_message = 'Handler function not found' WHERE id = ?");
$stmt->execute([$eventId]);
return;
}
@@ -157,7 +157,7 @@ function deliverIntegrationEvent(int $eventId, array $integration): void {
// Update event with result
$status = ($result['success'] ?? false) ? 'sent' : 'failed';
$stmt = $pdo->prepare("
- UPDATE integration_events
+ UPDATE `" . t('integration_events') . "`
SET status = ?, response_code = ?, response_body = ?, error_message = ?, processed_at = NOW()
WHERE id = ?
");
@@ -172,7 +172,7 @@ function deliverIntegrationEvent(int $eventId, array $integration): void {
// Update integration status
if ($status === 'sent') {
updateIntegrationStatus($integration['id'], 'connected');
- $pdo->prepare("UPDATE integrations SET last_sync_at = NOW() WHERE id = ?")->execute([$integration['id']]);
+ $pdo->prepare("UPDATE `" . t('integrations') . "` SET last_sync_at = NOW() WHERE id = ?")->execute([$integration['id']]);
} else {
updateIntegrationStatus($integration['id'], 'error', $result['error'] ?? 'Delivery failed');
}
@@ -180,7 +180,7 @@ function deliverIntegrationEvent(int $eventId, array $integration): void {
} catch (Exception $e) {
error_log("deliverIntegrationEvent($eventId) failed: " . $e->getMessage());
try {
- $stmt = $pdo->prepare("UPDATE integration_events SET status = 'failed', processed_at = NOW(), error_message = ? WHERE id = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('integration_events') . "` SET status = 'failed', processed_at = NOW(), error_message = ? WHERE id = ?");
$stmt->execute([$e->getMessage(), $eventId]);
} catch (PDOException $ex) {
// Ignore
@@ -201,7 +201,7 @@ function retryFailedEvents(string $integrationKey, int $limit = 50): array {
try {
$stmt = $pdo->prepare("
- SELECT id FROM integration_events
+ SELECT id FROM `" . t('integration_events') . "`
WHERE integration_id = ? AND status IN ('failed', 'pending')
ORDER BY created_at ASC
LIMIT ?
@@ -216,7 +216,7 @@ function retryFailedEvents(string $integrationKey, int $limit = 50): array {
$retried++;
// Check if it succeeded
- $check = $pdo->prepare("SELECT status FROM integration_events WHERE id = ?");
+ $check = $pdo->prepare("SELECT status FROM `" . t('integration_events') . "` WHERE id = ?");
$check->execute([$eid]);
if ($check->fetchColumn() === 'sent') {
$succeeded++;
diff --git a/FINAL_PRODUCTION_SYSTEM/functions/key-helpers.php b/FINAL_PRODUCTION_SYSTEM/functions/key-helpers.php
index ba37328..63d385f 100644
--- a/FINAL_PRODUCTION_SYSTEM/functions/key-helpers.php
+++ b/FINAL_PRODUCTION_SYSTEM/functions/key-helpers.php
@@ -39,7 +39,7 @@ function allocateKeyAtomically($pdo, $technician_id, $order_number) {
}
$stmt = $pdo->prepare("
- SELECT * FROM oem_keys
+ SELECT * FROM `" . t('oem_keys') . "`
WHERE key_status IN ('unused', 'retry')
AND (fail_counter < " . MAX_KEY_FAIL_COUNTER . " OR key_status = 'unused')
ORDER BY
@@ -55,7 +55,7 @@ function allocateKeyAtomically($pdo, $technician_id, $order_number) {
if ($key) {
$stmt = $pdo->prepare("
- UPDATE oem_keys
+ UPDATE `" . t('oem_keys') . "`
SET key_status = 'allocated',
last_use_date = CURDATE(),
last_use_time = CURTIME(),
diff --git a/FINAL_PRODUCTION_SYSTEM/functions/license-helpers.php b/FINAL_PRODUCTION_SYSTEM/functions/license-helpers.php
index 44c904f..9aa8877 100644
--- a/FINAL_PRODUCTION_SYSTEM/functions/license-helpers.php
+++ b/FINAL_PRODUCTION_SYSTEM/functions/license-helpers.php
@@ -84,7 +84,7 @@ function generateInstanceId(PDO $pdo): string {
// Get database creation timestamp (stable across restarts)
try {
- $stmt = $pdo->query("SELECT MIN(created_at) AS first_record FROM admin_users");
+ $stmt = $pdo->query("SELECT MIN(created_at) AS first_record FROM `" . t('admin_users') . "`");
$row = $stmt->fetch();
$dbSeed = $row['first_record'] ?? date('Y-m-d');
} catch (Exception $e) {
@@ -171,7 +171,7 @@ function createLicenseJwt(array $payload, string $secret = 'keygate-community-ve
*/
function getCurrentLicense(PDO $pdo): ?array {
try {
- $stmt = $pdo->query("SELECT * FROM license_info WHERE is_active = 1 ORDER BY id DESC LIMIT 1");
+ $stmt = $pdo->query("SELECT * FROM `" . t('license_info') . "` WHERE is_active = 1 ORDER BY id DESC LIMIT 1");
return $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
} catch (Exception $e) {
// Table may not exist yet (pre-migration)
@@ -258,11 +258,11 @@ function registerLicense(PDO $pdo, string $licenseKey): array {
$tierDef = LICENSE_TIERS[$tier];
// Deactivate any existing license
- $pdo->exec("UPDATE license_info SET is_active = 0");
+ $pdo->exec("UPDATE `" . t('license_info') . "` SET is_active = 0");
// Insert new license
$stmt = $pdo->prepare("
- INSERT INTO license_info
+ INSERT INTO `" . t('license_info') . "`
(license_key, instance_id, tier, licensed_to_email, licensed_to_name,
max_technicians, max_keys, features,
issued_at, expires_at, last_validated_at, validation_status, is_active)
@@ -307,7 +307,7 @@ function isFeatureAvailable(PDO $pdo, string $feature): bool {
*/
function canAddTechnician(PDO $pdo): array {
$license = getEffectiveLicense($pdo);
- $stmt = $pdo->query("SELECT COUNT(*) FROM technicians WHERE status = 'active'");
+ $stmt = $pdo->query("SELECT COUNT(*) FROM `" . t('technicians') . "` WHERE status = 'active'");
$currentCount = (int)$stmt->fetchColumn();
if ($currentCount >= $license['max_technicians']) {
@@ -328,7 +328,7 @@ function canAddTechnician(PDO $pdo): array {
*/
function canAddKeys(PDO $pdo, int $count = 1): array {
$license = getEffectiveLicense($pdo);
- $stmt = $pdo->query("SELECT COUNT(*) FROM oem_keys");
+ $stmt = $pdo->query("SELECT COUNT(*) FROM `" . t('oem_keys') . "`");
$currentCount = (int)$stmt->fetchColumn();
if (($currentCount + $count) > $license['max_keys']) {
diff --git a/FINAL_PRODUCTION_SYSTEM/functions/network-utils.php b/FINAL_PRODUCTION_SYSTEM/functions/network-utils.php
index ec3e6bf..fe2e8f6 100644
--- a/FINAL_PRODUCTION_SYSTEM/functions/network-utils.php
+++ b/FINAL_PRODUCTION_SYSTEM/functions/network-utils.php
@@ -21,14 +21,14 @@ function checkTrustedNetwork($ip, $checkUSBAuth = false) {
// Check if network allows USB authentication
$stmt = $pdo->prepare("
SELECT id, network_name, ip_range, bypass_2fa, allow_usb_auth
- FROM trusted_networks
+ FROM `" . t('trusted_networks') . "`
WHERE is_active = 1 AND allow_usb_auth = 1
");
} else {
// Check if network allows 2FA bypass
$stmt = $pdo->prepare("
SELECT id, network_name, ip_range, bypass_2fa, allow_usb_auth
- FROM trusted_networks
+ FROM `" . t('trusted_networks') . "`
WHERE is_active = 1 AND bypass_2fa = 1
");
}
@@ -122,7 +122,7 @@ function logNetworkSecurityEvent($event_type, $ip_address, $network_id = null, $
try {
$stmt = $pdo->prepare("
- INSERT INTO admin_activity_log (
+ INSERT INTO `" . t('admin_activity_log') . "` (
admin_id, session_id, action, description,
ip_address, user_agent, trusted_network_id
) VALUES (
diff --git a/FINAL_PRODUCTION_SYSTEM/functions/push-helpers.php b/FINAL_PRODUCTION_SYSTEM/functions/push-helpers.php
index bcf23cd..2f2304f 100644
--- a/FINAL_PRODUCTION_SYSTEM/functions/push-helpers.php
+++ b/FINAL_PRODUCTION_SYSTEM/functions/push-helpers.php
@@ -87,7 +87,7 @@ function getVapidKeys(): ?array {
$keys = VAPID::createVapidKeys();
$stmt = $pdo->prepare("
- INSERT INTO system_config (config_key, config_value, description)
+ INSERT INTO `" . t('system_config') . "` (config_key, config_value, description)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE config_value = VALUES(config_value)
");
@@ -129,11 +129,11 @@ function dispatchNotification(string $action, string $description, int $actorAdm
// Get all admin IDs except the actor, who have this category enabled (or no preference row = default ON)
$stmt = $pdo->prepare("
SELECT DISTINCT au.id, au.preferred_language
- FROM admin_users au
+ FROM `" . t('admin_users') . "` au
WHERE au.id != ?
AND au.is_active = 1
AND NOT EXISTS (
- SELECT 1 FROM push_preferences pp
+ SELECT 1 FROM `" . t('push_preferences') . "` pp
WHERE pp.admin_id = au.id AND pp.category = ? AND pp.enabled = 0
)
");
@@ -148,7 +148,7 @@ function dispatchNotification(string $action, string $description, int $actorAdm
// Insert bell notifications for all recipients
$insertStmt = $pdo->prepare("
- INSERT INTO notifications (admin_id, category, title_key, body, action_url)
+ INSERT INTO `" . t('notifications') . "` (admin_id, category, title_key, body, action_url)
VALUES (?, ?, ?, ?, ?)
");
foreach ($recipientIds as $adminId) {
@@ -212,7 +212,7 @@ function dispatchNotification(string $action, string $description, int $actorAdm
if ($report->isSubscriptionExpired()) {
// Deactivate expired subscriptions
$expiredEndpoint = $report->getRequest()->getUri()->__toString();
- $deactivateStmt = $pdo->prepare("UPDATE push_subscriptions SET is_active = 0 WHERE endpoint = ?");
+ $deactivateStmt = $pdo->prepare("UPDATE `" . t('push_subscriptions') . "` SET is_active = 0 WHERE endpoint = ?");
$deactivateStmt->execute([$expiredEndpoint]);
}
}
diff --git a/FINAL_PRODUCTION_SYSTEM/functions/qc-compliance.php b/FINAL_PRODUCTION_SYSTEM/functions/qc-compliance.php
index 63f2d6a..eb339f5 100644
--- a/FINAL_PRODUCTION_SYSTEM/functions/qc-compliance.php
+++ b/FINAL_PRODUCTION_SYSTEM/functions/qc-compliance.php
@@ -8,7 +8,7 @@
* Check if QC compliance system is enabled
*/
function qcIsEnabled(PDO $pdo): bool {
- $stmt = $pdo->prepare("SELECT setting_value FROM qc_global_settings WHERE setting_key = 'qc_enabled' LIMIT 1");
+ $stmt = $pdo->prepare("SELECT setting_value FROM `" . t('qc_global_settings') . "` WHERE setting_key = 'qc_enabled' LIMIT 1");
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
return $row && $row['setting_value'] === '1';
@@ -18,7 +18,7 @@ function qcIsEnabled(PDO $pdo): bool {
* Return all global QC settings as key-value array
*/
function qcGetGlobalSettings(PDO $pdo): array {
- $stmt = $pdo->query("SELECT setting_key, setting_value FROM qc_global_settings");
+ $stmt = $pdo->query("SELECT setting_key, setting_value FROM `" . t('qc_global_settings') . "`");
$settings = [];
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
$settings[$row['setting_key']] = $row['setting_value'];
@@ -36,7 +36,7 @@ function qcAutoRegisterMotherboard(PDO $pdo, ?string $manufacturer, ?string $pro
}
// Check if already exists
- $stmt = $pdo->prepare("SELECT id, known_bios_versions FROM qc_motherboard_registry WHERE manufacturer = ? AND product = ? LIMIT 1");
+ $stmt = $pdo->prepare("SELECT id, known_bios_versions FROM `" . t('qc_motherboard_registry') . "` WHERE manufacturer = ? AND product = ? LIMIT 1");
$stmt->execute([$manufacturer, $product]);
$existing = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -48,7 +48,7 @@ function qcAutoRegisterMotherboard(PDO $pdo, ?string $manufacturer, ?string $pro
}
$stmt = $pdo->prepare("
- UPDATE qc_motherboard_registry
+ UPDATE `" . t('qc_motherboard_registry') . "`
SET times_seen = times_seen + 1,
last_seen_at = NOW(),
known_bios_versions = ?
@@ -61,7 +61,7 @@ function qcAutoRegisterMotherboard(PDO $pdo, ?string $manufacturer, ?string $pro
// Insert new motherboard
$knownVersions = !empty($biosVersion) ? json_encode([$biosVersion]) : '[]';
$stmt = $pdo->prepare("
- INSERT INTO qc_motherboard_registry (manufacturer, product, known_bios_versions, first_seen_at, last_seen_at, times_seen)
+ INSERT INTO `" . t('qc_motherboard_registry') . "` (manufacturer, product, known_bios_versions, first_seen_at, last_seen_at, times_seen)
VALUES (?, ?, ?, NOW(), NOW(), 1)
");
$stmt->execute([$manufacturer, $product, $knownVersions]);
@@ -89,7 +89,7 @@ function qcGetEffectiveRules(PDO $pdo, ?string $manufacturer, ?string $product,
// Overlay product line enforcement (matched by order number pattern)
if (!empty($orderNumber) && mb_strlen($orderNumber) <= 50) {
- $stmt = $pdo->query("SELECT id, name, order_pattern, secure_boot_enforcement, bios_enforcement, hackbgrt_enforcement, partition_enforcement, missing_drivers_enforcement FROM product_lines WHERE is_active = 1 ORDER BY LENGTH(order_pattern) DESC");
+ $stmt = $pdo->query("SELECT id, name, order_pattern, secure_boot_enforcement, bios_enforcement, hackbgrt_enforcement, partition_enforcement, missing_drivers_enforcement FROM `" . t('product_lines') . "` WHERE is_active = 1 ORDER BY LENGTH(order_pattern) DESC");
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $line) {
$pattern = $line['order_pattern'] ?? '';
if (!preg_match('/^[\p{L}\p{N}#*\-\s]+$/u', $pattern) || mb_strlen($pattern) > 50) continue;
@@ -114,7 +114,7 @@ function qcGetEffectiveRules(PDO $pdo, ?string $manufacturer, ?string $product,
// Overlay manufacturer defaults
if (!empty($manufacturer)) {
- $stmt = $pdo->prepare("SELECT * FROM qc_manufacturer_defaults WHERE manufacturer = ? LIMIT 1");
+ $stmt = $pdo->prepare("SELECT * FROM `" . t('qc_manufacturer_defaults') . "` WHERE manufacturer = ? LIMIT 1");
$stmt->execute([$manufacturer]);
$mfr = $stmt->fetch(PDO::FETCH_ASSOC);
if ($mfr) {
@@ -129,7 +129,7 @@ function qcGetEffectiveRules(PDO $pdo, ?string $manufacturer, ?string $product,
// Overlay model-specific overrides (non-NULL only)
if (!empty($manufacturer) && !empty($product)) {
- $stmt = $pdo->prepare("SELECT * FROM qc_motherboard_registry WHERE manufacturer = ? AND product = ? LIMIT 1");
+ $stmt = $pdo->prepare("SELECT * FROM `" . t('qc_motherboard_registry') . "` WHERE manufacturer = ? AND product = ? LIMIT 1");
$stmt->execute([$manufacturer, $product]);
$model = $stmt->fetch(PDO::FETCH_ASSOC);
if ($model) {
@@ -444,7 +444,7 @@ function qcCheckPartitionLayout(PDO $pdo, int $hardwareInfoId, string $orderNumb
if (mb_strlen($orderNumber) > 50) {
return null;
}
- $stmt = $pdo->query("SELECT id, name, order_pattern, enforcement_level FROM product_lines WHERE is_active = 1 ORDER BY LENGTH(order_pattern) DESC");
+ $stmt = $pdo->query("SELECT id, name, order_pattern, enforcement_level FROM `" . t('product_lines') . "` WHERE is_active = 1 ORDER BY LENGTH(order_pattern) DESC");
$matchedLine = null;
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $line) {
$pattern = $line['order_pattern'] ?? '';
@@ -537,7 +537,7 @@ function qcCheckPartitionLayout(PDO $pdo, int $hardwareInfoId, string $orderNumb
}
$stmt = $pdo->prepare("
SELECT id, name, disk_size_min_mb, disk_size_max_mb
- FROM product_variants
+ FROM `" . t('product_variants') . "`
WHERE line_id = ? AND is_active = 1
AND disk_size_min_mb <= ? AND disk_size_max_mb >= ?
ORDER BY disk_size_min_mb DESC
@@ -562,7 +562,7 @@ function qcCheckPartitionLayout(PDO $pdo, int $hardwareInfoId, string $orderNumb
// 6. Store detected variant in hardware_info
$stmt = $pdo->prepare("
- UPDATE hardware_info
+ UPDATE `" . t('hardware_info') . "`
SET detected_variant_id = ?, detected_variant_name = ?, detected_line_name = ?
WHERE id = ?
");
@@ -570,7 +570,7 @@ function qcCheckPartitionLayout(PDO $pdo, int $hardwareInfoId, string $orderNumb
// 7. Load expected partitions
$stmt = $pdo->prepare("
- SELECT * FROM product_variant_partitions
+ SELECT * FROM `" . t('product_variant_partitions') . "`
WHERE variant_id = ?
ORDER BY partition_order
");
@@ -659,7 +659,7 @@ function qcCheckPartitionLayout(PDO $pdo, int $hardwareInfoId, string $orderNumb
} else {
// Check global setting
try {
- $gStmt = $pdo->prepare("SELECT setting_value FROM qc_global_settings WHERE setting_key = 'max_unallocated_mb'");
+ $gStmt = $pdo->prepare("SELECT setting_value FROM `" . t('qc_global_settings') . "` WHERE setting_key = 'max_unallocated_mb'");
$gStmt->execute();
$gVal = $gStmt->fetchColumn();
if ($gVal !== false && $gVal !== null && $gVal !== '') {
@@ -714,7 +714,7 @@ function qcCheckPartitionLayout(PDO $pdo, int $hardwareInfoId, string $orderNumb
*/
function qcInsertResult(PDO $pdo, int $hardwareInfoId, string $orderNumber, array $check, ?int $registryId, bool $retroactive = false): void {
$stmt = $pdo->prepare("
- INSERT INTO qc_compliance_results (
+ INSERT INTO `" . t('qc_compliance_results') . "` (
hardware_info_id, order_number, check_type, check_result,
enforcement_level, expected_value, actual_value, message,
rule_source, motherboard_registry_id, is_retroactive, checked_at
@@ -741,7 +741,7 @@ function qcInsertResult(PDO $pdo, int $hardwareInfoId, string $orderNumber, arra
function qcHasBlockingIssues(PDO $pdo, int $hardwareInfoId): bool {
$stmt = $pdo->prepare("
SELECT COUNT(*) as cnt
- FROM qc_compliance_results
+ FROM `" . t('qc_compliance_results') . "`
WHERE hardware_info_id = ?
AND enforcement_level = 3
AND check_result = 'fail'
@@ -809,7 +809,7 @@ function qcRecheckHistorical(PDO $pdo, ?string $manufacturer = null, ?string $pr
$lastId = $hwId;
// Delete existing compliance results for this record
- $stmt2 = $pdo->prepare("DELETE FROM qc_compliance_results WHERE hardware_info_id = ?");
+ $stmt2 = $pdo->prepare("DELETE FROM `" . t('qc_compliance_results') . "` WHERE hardware_info_id = ?");
$stmt2->execute([$hwId]);
// Re-run checks
@@ -853,7 +853,7 @@ function qcRunChecksRetroactive(PDO $pdo, int $hardwareInfoId, array $hw): array
$orderNumber = $hw['order_number'] ?? '';
// Get registry ID (don't auto-register for retroactive)
- $stmt = $pdo->prepare("SELECT id FROM qc_motherboard_registry WHERE manufacturer = ? AND product = ? LIMIT 1");
+ $stmt = $pdo->prepare("SELECT id FROM `" . t('qc_motherboard_registry') . "` WHERE manufacturer = ? AND product = ? LIMIT 1");
$stmt->execute([$manufacturer, $product]);
$reg = $stmt->fetch(PDO::FETCH_ASSOC);
$registryId = $reg ? (int) $reg['id'] : null;
diff --git a/FINAL_PRODUCTION_SYSTEM/functions/session-helpers.php b/FINAL_PRODUCTION_SYSTEM/functions/session-helpers.php
index 8b382ed..9a1521f 100644
--- a/FINAL_PRODUCTION_SYSTEM/functions/session-helpers.php
+++ b/FINAL_PRODUCTION_SYSTEM/functions/session-helpers.php
@@ -32,9 +32,9 @@ function validateSession($token) {
try {
$stmt = $pdo->prepare("
SELECT s.*, k.product_key, k.key_status, t.is_active as tech_active
- FROM active_sessions s
- LEFT JOIN oem_keys k ON s.key_id = k.id
- LEFT JOIN technicians t ON s.technician_id = t.technician_id
+ FROM `" . t('active_sessions') . "` s
+ LEFT JOIN `" . t('oem_keys') . "` k ON s.key_id = k.id
+ LEFT JOIN `" . t('technicians') . "` t ON s.technician_id = t.technician_id
WHERE s.session_token = ?
AND s.is_active = 1
AND s.expires_at > NOW()
@@ -54,7 +54,7 @@ function validateSession($token) {
function cleanupExpiredSessions($pdo) {
try {
$stmt = $pdo->prepare("
- UPDATE active_sessions
+ UPDATE `" . t('active_sessions') . "`
SET is_active = 0
WHERE expires_at < NOW() AND is_active = 1
LIMIT " . SESSION_CLEANUP_BATCH . "
@@ -82,8 +82,8 @@ function getActiveSession($pdo, $technician_id) {
$stmt = $pdo->prepare("
SELECT s.*, k.product_key, k.oem_identifier, k.key_status, k.fail_counter
- FROM active_sessions s
- LEFT JOIN oem_keys k ON s.key_id = k.id
+ FROM `" . t('active_sessions') . "` s
+ LEFT JOIN `" . t('oem_keys') . "` k ON s.key_id = k.id
WHERE s.technician_id = ?
AND s.is_active = 1
AND s.expires_at > NOW()
diff --git a/FINAL_PRODUCTION_SYSTEM/functions/totp-helpers.php b/FINAL_PRODUCTION_SYSTEM/functions/totp-helpers.php
index 8a6cd21..32bf5b9 100644
--- a/FINAL_PRODUCTION_SYSTEM/functions/totp-helpers.php
+++ b/FINAL_PRODUCTION_SYSTEM/functions/totp-helpers.php
@@ -39,7 +39,7 @@ function validateAdminApiSession(): array {
function fetchTotpData(PDO $pdo, int $adminId): ?array {
$stmt = $pdo->prepare("
SELECT id, totp_secret, totp_enabled, backup_codes
- FROM admin_totp_secrets
+ FROM `" . t('admin_totp_secrets') . "`
WHERE admin_id = ?
");
$stmt->execute([$adminId]);
@@ -78,7 +78,7 @@ function verifyTotpCode(PDO $pdo, int $adminId, string $code, array $totpData, b
$backupCodes = array_values($backupCodes);
$stmt = $pdo->prepare("
- UPDATE admin_totp_secrets
+ UPDATE `" . t('admin_totp_secrets') . "`
SET backup_codes = ?, last_used_at = NOW()
WHERE admin_id = ?
");
@@ -92,7 +92,7 @@ function verifyTotpCode(PDO $pdo, int $adminId, string $code, array $totpData, b
} else {
$totp = TOTP::createFromSecret($totpData['totp_secret']);
- $stmt = $pdo->query("SELECT config_value FROM system_config WHERE config_key = 'totp_window'");
+ $stmt = $pdo->query("SELECT config_value FROM `" . t('system_config') . "` WHERE config_key = 'totp_window'");
$windowResult = $stmt->fetch(PDO::FETCH_ASSOC);
$window = $windowResult ? (int)$windowResult['config_value'] : 1;
@@ -100,7 +100,7 @@ function verifyTotpCode(PDO $pdo, int $adminId, string $code, array $totpData, b
if ($result['verified']) {
$stmt = $pdo->prepare("
- UPDATE admin_totp_secrets
+ UPDATE `" . t('admin_totp_secrets') . "`
SET last_used_at = NOW()
WHERE admin_id = ?
");
@@ -117,7 +117,7 @@ function verifyTotpCode(PDO $pdo, int $adminId, string $code, array $totpData, b
* @return array ['plain' => string[], 'hashed' => string[]]
*/
function generateBackupCodes(PDO $pdo): array {
- $stmt = $pdo->query("SELECT config_value FROM system_config WHERE config_key = 'totp_backup_codes_count'");
+ $stmt = $pdo->query("SELECT config_value FROM `" . t('system_config') . "` WHERE config_key = 'totp_backup_codes_count'");
$backupCountResult = $stmt->fetch(PDO::FETCH_ASSOC);
$backupCodeCount = $backupCountResult ? (int)$backupCountResult['config_value'] : 10;
diff --git a/FINAL_PRODUCTION_SYSTEM/install/ajax.php b/FINAL_PRODUCTION_SYSTEM/install/ajax.php
index fedc2a5..a9cbf4c 100644
--- a/FINAL_PRODUCTION_SYSTEM/install/ajax.php
+++ b/FINAL_PRODUCTION_SYSTEM/install/ajax.php
@@ -469,13 +469,13 @@ function handleInstallDbInit() {
}
// Bootstrap schema_versions first (the tracking table for all later migrations).
+ // Run through installerRunSqlFile so the `#__` prefix substitution kicks in.
$schemaFile = $sqlDir . '/schema_versions_migration.sql';
if (file_exists($schemaFile)) {
- try {
- $pdo->exec(file_get_contents($schemaFile));
- } catch (PDOException $e) { /* probably already exists */ }
+ installerRunSqlFile($pdo, file_get_contents($schemaFile)); // Best-effort; ignore errors.
}
+ $svTable = '`' . installerT('schema_versions') . '`';
$list = [];
foreach (installerMigrationList() as [$file, $version]) {
$filePath = $sqlDir . '/' . $file;
@@ -484,7 +484,7 @@ function handleInstallDbInit() {
if ($exists) {
try {
- $stmt = $pdo->prepare("SELECT COUNT(*) AS c FROM schema_versions WHERE filename = ?");
+ $stmt = $pdo->prepare("SELECT COUNT(*) AS c FROM {$svTable} WHERE filename = ?");
$stmt->execute([$file]);
$applied = ((int)$stmt->fetchColumn()) > 0;
} catch (PDOException $e) { /* table missing → not applied */ }
@@ -532,9 +532,11 @@ function handleInstallDbStep() {
return;
}
+ $svTable = '`' . installerT('schema_versions') . '`';
+
// Skip if already applied
try {
- $stmt = $pdo->prepare("SELECT COUNT(*) AS c FROM schema_versions WHERE filename = ?");
+ $stmt = $pdo->prepare("SELECT COUNT(*) AS c FROM {$svTable} WHERE filename = ?");
$stmt->execute([$file]);
if ((int)$stmt->fetchColumn() > 0) {
echo json_encode(['file' => $file, 'success' => true, 'status' => 'skipped', 'message' => 'Already applied']);
@@ -548,7 +550,7 @@ function handleInstallDbStep() {
if ($result['ok']) {
try {
$checksum = hash('sha256', $sql);
- $stmt = $pdo->prepare("INSERT IGNORE INTO schema_versions (version, filename, checksum) VALUES (?, ?, ?)");
+ $stmt = $pdo->prepare("INSERT IGNORE INTO {$svTable} (version, filename, checksum) VALUES (?, ?, ?)");
$stmt->execute([$version, $file, $checksum]);
} catch (PDOException $e) { /* ignore */ }
@@ -566,7 +568,7 @@ function handleInstallDbStep() {
if (preg_match('/Duplicate|already exists|1060|1061|1050|1062/i', $result['error'])) {
try {
$checksum = hash('sha256', $sql);
- $stmt = $pdo->prepare("INSERT IGNORE INTO schema_versions (version, filename, checksum) VALUES (?, ?, ?)");
+ $stmt = $pdo->prepare("INSERT IGNORE INTO {$svTable} (version, filename, checksum) VALUES (?, ?, ?)");
$stmt->execute([$version, $file, $checksum]);
} catch (PDOException $e2) { /* ignore */ }
@@ -602,12 +604,13 @@ function handleInstallDbAll() {
return;
}
- // Bootstrap schema_versions
+ // Bootstrap schema_versions (run through installerRunSqlFile so prefix substitution applies)
$schemaFile = $sqlDir . '/schema_versions_migration.sql';
if (file_exists($schemaFile)) {
- try { $pdo->exec(file_get_contents($schemaFile)); } catch (PDOException $e) { /* ok */ }
+ installerRunSqlFile($pdo, file_get_contents($schemaFile));
}
+ $svTable = '`' . installerT('schema_versions') . '`';
$results = [];
foreach (installerMigrationList() as $i => [$file, $version]) {
if ($i === 0) {
@@ -622,7 +625,7 @@ function handleInstallDbAll() {
}
try {
- $stmt = $pdo->prepare("SELECT COUNT(*) AS c FROM schema_versions WHERE filename = ?");
+ $stmt = $pdo->prepare("SELECT COUNT(*) AS c FROM {$svTable} WHERE filename = ?");
$stmt->execute([$file]);
if ((int)$stmt->fetchColumn() > 0) {
$results[] = ['file' => $file, 'status' => 'skipped', 'message' => 'Already applied'];
@@ -636,14 +639,14 @@ function handleInstallDbAll() {
if ($r['ok']) {
try {
$checksum = hash('sha256', $sql);
- $stmt = $pdo->prepare("INSERT IGNORE INTO schema_versions (version, filename, checksum) VALUES (?, ?, ?)");
+ $stmt = $pdo->prepare("INSERT IGNORE INTO {$svTable} (version, filename, checksum) VALUES (?, ?, ?)");
$stmt->execute([$version, $file, $checksum]);
} catch (PDOException $e) { /* ignore */ }
$results[] = ['file' => $file, 'status' => 'ok', 'message' => 'Applied (' . $r['stmts_run'] . ' statements)'];
} elseif (preg_match('/Duplicate|already exists|1060|1061|1050|1062/i', $r['error'])) {
try {
$checksum = hash('sha256', $sql);
- $stmt = $pdo->prepare("INSERT IGNORE INTO schema_versions (version, filename, checksum) VALUES (?, ?, ?)");
+ $stmt = $pdo->prepare("INSERT IGNORE INTO {$svTable} (version, filename, checksum) VALUES (?, ?, ?)");
$stmt->execute([$version, $file, $checksum]);
} catch (PDOException $e) { /* ignore */ }
$results[] = ['file' => $file, 'status' => 'ok', 'message' => 'Applied (some objects already existed)'];
@@ -675,6 +678,17 @@ function installerRunSqlFile(PDO $pdo, string $sql): array {
$sql = preg_replace('/^\s*(START\s+TRANSACTION|BEGIN)\s*;\s*$/im', '', $sql);
$sql = preg_replace('/^\s*COMMIT\s*;\s*$/im', '', $sql);
+ // Substitute table prefix sentinel `#__` with the configured prefix.
+ // Empty prefix → identical to pre-prefix schema.
+ $prefix = (string)($_SESSION['install_db']['prefix'] ?? '');
+ $sql = str_replace('#__', $prefix, $sql);
+
+ // Defense-in-depth: if substitution somehow missed and `#__` remains,
+ // abort loudly rather than send invalid SQL.
+ if (strpos($sql, '#__') !== false) {
+ return ['ok' => false, 'stmts_run' => 0, 'error' => 'Internal error: unsubstituted `#__` sentinel still present after prefix replacement.'];
+ }
+
$stmts = installerSplitSql($sql);
$count = 0;
foreach ($stmts as $stmt) {
@@ -690,6 +704,16 @@ function installerRunSqlFile(PDO $pdo, string $sql): array {
return ['ok' => true, 'stmts_run' => $count, 'error' => ''];
}
+/**
+ * Resolve the prefixed name for a logical table during installation.
+ * Mirrors functions/db-helpers.php t() but reads from $_SESSION since
+ * the installer runs before config.php exists.
+ */
+function installerT(string $name): string {
+ $prefix = (string)($_SESSION['install_db']['prefix'] ?? '');
+ return $prefix . $name;
+}
+
/**
* Split a multi-statement SQL string into individual statements.
* Respects backticks, single/double-quoted strings, line comments (-- ...),
@@ -815,30 +839,33 @@ function handleCreateAdmin() {
return;
}
+ $adminTable = '`' . installerT('admin_users') . '`';
+ $aclTable = '`' . installerT('acl_roles') . '`';
+
try {
// Check if admin already exists
- $stmt = $pdo->prepare("SELECT id FROM admin_users WHERE username = ?");
+ $stmt = $pdo->prepare("SELECT id FROM {$adminTable} WHERE username = ?");
$stmt->execute([$username]);
if ($stmt->fetch()) {
// Update existing
$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
- $stmt = $pdo->prepare("UPDATE admin_users SET password_hash = ?, full_name = ?, email = ?, role = 'super_admin', is_active = 1, must_change_password = 0, failed_login_attempts = 0, locked_until = NULL WHERE username = ?");
+ $stmt = $pdo->prepare("UPDATE {$adminTable} SET password_hash = ?, full_name = ?, email = ?, role = 'super_admin', is_active = 1, must_change_password = 0, failed_login_attempts = 0, locked_until = NULL WHERE username = ?");
$stmt->execute([$hash, $fullName, $email, $username]);
echo json_encode(['success' => true, 'message' => "Admin account '{$username}' updated."]);
} else {
// Create new
$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
- $stmt = $pdo->prepare("INSERT INTO admin_users (username, full_name, email, password_hash, role, is_active, must_change_password) VALUES (?, ?, ?, ?, 'super_admin', 1, 0)");
+ $stmt = $pdo->prepare("INSERT INTO {$adminTable} (username, full_name, email, password_hash, role, is_active, must_change_password) VALUES (?, ?, ?, ?, 'super_admin', 1, 0)");
$stmt->execute([$username, $fullName, $email, $hash]);
// Try to assign ACL role if table exists
try {
$adminId = $pdo->lastInsertId();
- $roleStmt = $pdo->prepare("SELECT id FROM acl_roles WHERE name = 'super_admin' LIMIT 1");
+ $roleStmt = $pdo->prepare("SELECT id FROM {$aclTable} WHERE name = 'super_admin' LIMIT 1");
$roleStmt->execute();
$role = $roleStmt->fetch(PDO::FETCH_ASSOC);
if ($role) {
- $pdo->prepare("UPDATE admin_users SET custom_role_id = ? WHERE id = ?")->execute([$role['id'], $adminId]);
+ $pdo->prepare("UPDATE {$adminTable} SET custom_role_id = ? WHERE id = ?")->execute([$role['id'], $adminId]);
}
} catch (PDOException $e) {
// ACL tables might not exist — that's fine
@@ -873,7 +900,9 @@ function handleFinalize() {
}
// ── Write config.php ──
- $configContent = generateConfig($host, $port, $user, $pass, $name, $timezone);
+ $prefix = (string)($_SESSION['install_db']['prefix'] ?? '');
+ $charset = (string)($_SESSION['install_db']['charset'] ?? 'utf8mb4');
+ $configContent = generateConfig($host, $port, $user, $pass, $name, $timezone, $prefix, $charset);
$configPath = realpath(__DIR__ . '/..') . '/config.php';
if (file_put_contents($configPath, $configContent) === false) {
@@ -888,6 +917,12 @@ function handleFinalize() {
try {
$pdo = getInstallerPdo();
if ($pdo) {
+ $tConfig = '`' . installerT('system_config') . '`';
+ $tTech = '`' . installerT('technicians') . '`';
+ $tAdmin = '`' . installerT('admin_users') . '`';
+ $tTrustedN = '`' . installerT('trusted_networks') . '`';
+ $tAdminIp = '`' . installerT('admin_ip_whitelist') . '`';
+
$settings = [
'system_name' => $systemName,
'server_url' => $serverUrl,
@@ -895,13 +930,13 @@ function handleFinalize() {
'timezone' => $timezone,
];
foreach ($settings as $key => $value) {
- $stmt = $pdo->prepare("INSERT INTO system_config (config_key, config_value, description) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE config_value = VALUES(config_value)");
+ $stmt = $pdo->prepare("INSERT INTO {$tConfig} (config_key, config_value, description) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE config_value = VALUES(config_value)");
$stmt->execute([$key, $value, "Set by installer"]);
}
// Delete demo technician if it exists
try {
- $pdo->exec("DELETE FROM technicians WHERE technician_id = 'demo' AND notes LIKE '%Demo account%'");
+ $pdo->exec("DELETE FROM {$tTech} WHERE technician_id = 'demo' AND notes LIKE '%Demo account%'");
} catch (PDOException $e) { /* ignore */ }
// ── Auto-detect installer's network and add as trusted ──
@@ -909,7 +944,7 @@ function handleFinalize() {
$clientIp = getClientIp();
if ($clientIp && $clientIp !== 'unknown') {
// Get admin ID for foreign key
- $adminStmt = $pdo->prepare("SELECT id FROM admin_users WHERE username = ? LIMIT 1");
+ $adminStmt = $pdo->prepare("SELECT id FROM {$tAdmin} WHERE username = ? LIMIT 1");
$adminStmt->execute([$adminUser]);
$adminRow = $adminStmt->fetch(PDO::FETCH_ASSOC);
$adminId = $adminRow ? $adminRow['id'] : null;
@@ -920,7 +955,7 @@ function handleFinalize() {
// Add to trusted_networks (for 2FA bypass + USB auth)
try {
$stmt = $pdo->prepare("
- INSERT INTO trusted_networks (network_name, ip_range, bypass_2fa, allow_usb_auth, description, created_by_admin_id)
+ INSERT INTO {$tTrustedN} (network_name, ip_range, bypass_2fa, allow_usb_auth, description, created_by_admin_id)
VALUES (?, ?, 1, 1, ?, ?)
");
$stmt->execute([
@@ -934,7 +969,7 @@ function handleFinalize() {
// Add to admin_ip_whitelist (for admin panel access)
try {
$stmt = $pdo->prepare("
- INSERT INTO admin_ip_whitelist (ip_address, ip_range, description, created_by)
+ INSERT INTO {$tAdminIp} (ip_address, ip_range, description, created_by)
VALUES (?, ?, ?, ?)
");
$stmt->execute([
@@ -1144,9 +1179,20 @@ function calculateSubnet(string $ip, int $prefix = 24): string {
/**
* Generate the production config.php content
*/
-function generateConfig(string $host, string $port, string $user, string $pass, string $name, string $timezone): string {
+function generateConfig(
+ string $host,
+ string $port,
+ string $user,
+ string $pass,
+ string $name,
+ string $timezone,
+ string $prefix = '',
+ string $charset = 'utf8mb4'
+): string {
// Escape single quotes in password for PHP string
- $passEscaped = addcslashes($pass, "'\\");
+ $passEscaped = addcslashes($pass, "'\\");
+ $prefixEscaped = addcslashes($prefix, "'\\");
+ $charsetEsc = preg_replace('/[^a-z0-9_]/', '', $charset) ?: 'utf8mb4';
return <<<'PHP_HEADER'
'{$host}',\n"
. " 'dbname' => '{$name}',\n"
. " 'username' => '{$user}',\n"
. " 'password' => '{$passEscaped}',\n"
- . " 'charset' => 'utf8mb4',\n"
+ . " 'charset' => '{$charsetEsc}',\n"
. " 'port' => {$port},\n"
. "];\n\n"
. <<<'PHP_BODY'
@@ -1355,6 +1402,13 @@ function installerCheckIncompleteState(): void {
$host = $hM[1]; $name = $nM[1]; $user = $uM[1]; $pass = $pM[1]; $port = (int)$portM[1];
if (strtolower($host) === 'localhost') $host = '127.0.0.1';
+ // Read DB_PREFIX from config (empty for legacy installs).
+ $prefix = '';
+ if (preg_match("/define\(\s*'DB_PREFIX'\s*,\s*'([^']*)'\s*\)/", $configSrc, $pxM)) {
+ $prefix = $pxM[1];
+ }
+ $adminTable = $prefix . 'admin_users';
+
try {
$dsn = "mysql:host={$host};port={$port};dbname={$name};charset=utf8mb4";
$pdo = new PDO($dsn, $user, $pass, [
@@ -1363,15 +1417,15 @@ function installerCheckIncompleteState(): void {
]);
// admin_users table missing → install was never completed.
- $stmt = $pdo->query("SHOW TABLES LIKE 'admin_users'");
+ $stmt = $pdo->query("SHOW TABLES LIKE " . $pdo->quote($adminTable));
if (!$stmt->fetch()) {
- installerLog("auto-unlock: admin_users table missing — clearing install.lock");
+ installerLog("auto-unlock: {$adminTable} missing — clearing install.lock");
@unlink($lockPath);
return;
}
// admin_users empty → install was never completed.
- $cnt = (int)$pdo->query("SELECT COUNT(*) FROM admin_users")->fetchColumn();
+ $cnt = (int)$pdo->query("SELECT COUNT(*) FROM `{$adminTable}`")->fetchColumn();
if ($cnt === 0) {
installerLog("auto-unlock: admin_users empty — clearing install.lock");
@unlink($lockPath);
@@ -1447,17 +1501,19 @@ function handleHealth(): void {
$expectTables = ['admin_users', 'oem_keys', 'technicians', 'system_config', 'schema_versions'];
foreach ($expectTables as $t) {
+ $physical = installerT($t);
try {
- $stmt = $pdo->query("SHOW TABLES LIKE '" . str_replace("'", '', $t) . "'");
+ $stmt = $pdo->query("SHOW TABLES LIKE " . $pdo->quote($physical));
$found = (bool)$stmt->fetch();
- $checks[] = ['label' => "Table {$t}", 'status' => $found ? 'pass' : 'fail'];
+ $checks[] = ['label' => "Table {$physical}", 'status' => $found ? 'pass' : 'fail'];
} catch (PDOException $e) {
- $checks[] = ['label' => "Table {$t}", 'status' => 'fail'];
+ $checks[] = ['label' => "Table {$physical}", 'status' => 'fail'];
}
}
try {
- $admins = (int)$pdo->query("SELECT COUNT(*) FROM admin_users")->fetchColumn();
+ $adminTable = '`' . installerT('admin_users') . '`';
+ $admins = (int)$pdo->query("SELECT COUNT(*) FROM {$adminTable}")->fetchColumn();
$checks[] = ['label' => 'Admin accounts', 'status' => $admins > 0 ? 'pass' : 'fail', 'value' => $admins];
} catch (PDOException $e) {
$checks[] = ['label' => 'Admin accounts', 'status' => 'fail'];
diff --git a/FINAL_PRODUCTION_SYSTEM/install/index.php b/FINAL_PRODUCTION_SYSTEM/install/index.php
index f55d2e1..d7b7169 100644
--- a/FINAL_PRODUCTION_SYSTEM/install/index.php
+++ b/FINAL_PRODUCTION_SYSTEM/install/index.php
@@ -26,14 +26,20 @@
&& preg_match("/'password'\s*=>\s*'([^']*)'/", $configSrc, $pM)
&& preg_match("/'port'\s*=>\s*(\d+)/", $configSrc, $portM)) {
$autoHost = strtolower($hM[1]) === 'localhost' ? '127.0.0.1' : $hM[1];
+ // Read DB_PREFIX from config (empty for legacy installs).
+ $autoPrefix = '';
+ if (preg_match("/define\(\s*'DB_PREFIX'\s*,\s*'([^']*)'\s*\)/", $configSrc, $pxM)) {
+ $autoPrefix = $pxM[1];
+ }
+ $autoAdminTable = $autoPrefix . 'admin_users';
try {
$autoPdo = new PDO(
"mysql:host={$autoHost};port={$portM[1]};dbname={$nM[1]};charset=utf8mb4",
$uM[1], $pM[1],
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_TIMEOUT => 5]
);
- $hasAdminTable = (bool) $autoPdo->query("SHOW TABLES LIKE 'admin_users'")->fetch();
- $adminCount = $hasAdminTable ? (int) $autoPdo->query("SELECT COUNT(*) FROM admin_users")->fetchColumn() : 0;
+ $hasAdminTable = (bool) $autoPdo->query("SHOW TABLES LIKE " . $autoPdo->quote($autoAdminTable))->fetch();
+ $adminCount = $hasAdminTable ? (int) $autoPdo->query("SELECT COUNT(*) FROM `{$autoAdminTable}`")->fetchColumn() : 0;
if (!$hasAdminTable || $adminCount === 0) {
@unlink($lockFile);
@file_put_contents(
diff --git a/FINAL_PRODUCTION_SYSTEM/secure-admin.php b/FINAL_PRODUCTION_SYSTEM/secure-admin.php
index f043af9..a91e547 100644
--- a/FINAL_PRODUCTION_SYSTEM/secure-admin.php
+++ b/FINAL_PRODUCTION_SYSTEM/secure-admin.php
@@ -39,7 +39,7 @@ function checkIPWhitelist() {
// Get all active whitelist entries
$stmt = $pdo->prepare("
- SELECT ip_address, ip_range FROM admin_ip_whitelist
+ SELECT ip_address, ip_range FROM `" . t('admin_ip_whitelist') . "`
WHERE is_active = 1
");
$stmt->execute();
@@ -77,7 +77,7 @@ function checkIPWhitelist() {
// Handle logout
if (isset($_GET['logout'])) {
if (isset($_SESSION['admin_token'])) {
- $stmt = $pdo->prepare("UPDATE admin_sessions SET is_active = 0 WHERE session_token = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('admin_sessions') . "` SET is_active = 0 WHERE session_token = ?");
$stmt->execute([$_SESSION['admin_token']]);
logAdminActivity($_SESSION['admin_id'], $_SESSION['session_id'], 'LOGOUT', 'User logout');
}
diff --git a/FINAL_PRODUCTION_SYSTEM/setup/index.php b/FINAL_PRODUCTION_SYSTEM/setup/index.php
index 6dcc95e..9d0e839 100644
--- a/FINAL_PRODUCTION_SYSTEM/setup/index.php
+++ b/FINAL_PRODUCTION_SYSTEM/setup/index.php
@@ -500,7 +500,7 @@ function setupAdminAccount() {
$db['username'], $db['password']);
$stmt = $pdo->prepare("
- INSERT INTO admin_users (username, full_name, email, password_hash, role, must_change_password)
+ INSERT INTO `" . t('admin_users') . "` (username, full_name, email, password_hash, role, must_change_password)
VALUES (?, ?, ?, ?, 'super_admin', 0)
");
$stmt->execute([$admin['username'], $admin['full_name'], $admin['email'], $admin['password']]);
@@ -524,7 +524,7 @@ function applySystemConfiguration() {
['admin_ip_whitelist_enabled', $config['enable_ip_whitelist'] ? '1' : '0'],
];
- $stmt = $pdo->prepare("UPDATE system_config SET config_value = ? WHERE config_key = ?");
+ $stmt = $pdo->prepare("UPDATE `" . t('system_config') . "` SET config_value = ? WHERE config_key = ?");
foreach ($configs as $cfg) {
$stmt->execute([$cfg[1], $cfg[0]]);
}
diff --git a/tools/prefix-codemod.php b/tools/prefix-codemod.php
new file mode 100644
index 0000000..06a932d
--- /dev/null
+++ b/tools/prefix-codemod.php
@@ -0,0 +1,398 @@
+ overrides default detection. Useful inside Docker where
+// FINAL_PRODUCTION_SYSTEM lives at /var/www/html/activate, not next to tools/.
+$customRoot = '';
+foreach ($argv as $i => $arg) {
+ if ($arg === '--root' && isset($argv[$i + 1])) {
+ $customRoot = $argv[$i + 1];
+ break;
+ }
+ if (str_starts_with($arg, '--root=')) {
+ $customRoot = substr($arg, 7);
+ break;
+ }
+}
+
+if ($customRoot !== '') {
+ $appRoot = realpath($customRoot);
+} else {
+ $root = realpath(__DIR__ . '/..');
+ $appRoot = $root . DIRECTORY_SEPARATOR . 'FINAL_PRODUCTION_SYSTEM';
+}
+if (!is_dir($appRoot)) {
+ fwrite(STDERR, "FINAL_PRODUCTION_SYSTEM not found at {$appRoot}\n");
+ exit(1);
+}
+
+$dbDir = $appRoot . DIRECTORY_SEPARATOR . 'database';
+
+// ── 1. Discover canonical table list ──────────────────────────────
+$tables = discoverTables($dbDir);
+sort($tables);
+if (!$quiet) {
+ fwrite(STDOUT, "Discovered " . count($tables) . " tables.\n");
+}
+
+// Sort by length descending so longer names match before substring siblings
+// (e.g. `admin_users` before `admin`).
+usort($tables, fn($a, $b) => strlen($b) - strlen($a));
+
+// Build deny list — never rewrite these even if they appear in SQL contexts.
+// They are SQL keywords / column names that happen to look like table names.
+$denyAlias = [
+ 'config_value', // column in system_config
+ 'value', // generic column name
+ 'key', // SQL keyword + common column
+ 'name', // common column
+ 'role', // common column
+];
+$tables = array_values(array_diff($tables, $denyAlias));
+
+if (count($tables) < 5) {
+ fwrite(STDERR, "Refusing to run: only " . count($tables) . " tables discovered. Something is wrong.\n");
+ exit(2);
+}
+
+// ── 2. SQL pass ───────────────────────────────────────────────────
+$sqlFiles = glob($dbDir . '/*.sql');
+$sqlChanges = 0;
+$sqlFilesChanged = [];
+
+foreach ($sqlFiles as $f) {
+ $orig = file_get_contents($f);
+ $new = rewriteSqlBody($orig, $tables);
+ if ($new !== $orig) {
+ $sqlChanges += substr_count($new, '#__') - substr_count($orig, '#__');
+ $sqlFilesChanged[] = basename($f);
+ if ($apply) {
+ file_put_contents($f, $new);
+ }
+ }
+}
+
+if (!$quiet) {
+ fwrite(STDOUT, "SQL: " . count($sqlFilesChanged) . " files changed, +{$sqlChanges} `#__` markers.\n");
+}
+
+// ── 3. PHP pass ───────────────────────────────────────────────────
+$phpFiles = collectPhpFiles($appRoot);
+$phpChanges = 0;
+$phpFilesChanged = [];
+
+foreach ($phpFiles as $f) {
+ $orig = file_get_contents($f);
+ $new = rewritePhpBody($orig, $tables);
+ if ($new !== $orig) {
+ $phpFilesChanged[] = str_replace($appRoot . DIRECTORY_SEPARATOR, '', $f);
+ $diffLines = countDiff($orig, $new);
+ $phpChanges += $diffLines;
+ if ($apply) {
+ file_put_contents($f, $new);
+ }
+ }
+}
+
+if (!$quiet) {
+ fwrite(STDOUT, "PHP: " . count($phpFilesChanged) . " files changed, ~{$phpChanges} site rewrites.\n");
+}
+
+// ── 4. Verify pass (when --verify) ────────────────────────────────
+if ($verify) {
+ $stillBad = [];
+ foreach ($sqlFiles as $f) {
+ $body = file_get_contents($f);
+ foreach ($tables as $t) {
+ // Look for un-prefixed backticked refs.
+ // Pattern: `tablename` not preceded by `#__
+ if (preg_match('/(?isFile()) continue;
+ if (substr($f->getFilename(), -4) !== '.php') continue;
+ $path = str_replace('\\', '/', $f->getPathname());
+ foreach ($skip as $s) {
+ if (strpos($path, $s) !== false) continue 2;
+ }
+ $files[] = $f->getPathname();
+ }
+ return $files;
+}
+
+/**
+ * Rewrite SQL body: `tablename` → `#__tablename` for every canonical table.
+ * Idempotent: skips already-prefixed.
+ */
+function rewriteSqlBody(string $body, array $tables): string {
+ $kw = '(?:CREATE\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?|DROP\s+TABLE(?:\s+IF\s+EXISTS)?|ALTER\s+TABLE|INSERT\s+INTO|REPLACE\s+INTO|SELECT\s+(?:[^;]*?)FROM|UPDATE|DELETE\s+FROM|FROM|JOIN|REFERENCES|TRUNCATE(?:\s+TABLE)?|RENAME\s+TABLE|LOCK\s+TABLES|DESCRIBE|EXPLAIN)';
+
+ foreach ($tables as $t) {
+ // ── Pattern A: backticked refs ────────────────────────────
+ // (?