From 131aaaddbf85431ec100218ec6266fdd42fb0fd9 Mon Sep 17 00:00:00 2001 From: cproudlock Date: Fri, 12 Dec 2025 08:11:28 -0500 Subject: [PATCH] Centralize credentials and make migration idempotent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move all DB credentials to config.asp with DSN/ODBC toggle - Add Zabbix API URL and token to centralized config - Update sql.asp, api.asp, apiusb.asp, zabbix.asp to use config - Add GetConnectionString() and GetEmployeeConnectionString() functions - Make migration SQL idempotent (safe to run multiple times) - Add duplicate index cleanup (appname_2) to migration - Document employee DB access limitation in CLAUDE.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- CLAUDE.md | 1 + api.asp | 18 ++----- apiusb.asp | 19 +++---- displayprofile.asp | 7 ++- includes/config.asp | 85 +++++++++++++++++++++++++----- includes/sql.asp | 19 ++----- includes/wjf_employees-sql.asp | 12 +++-- includes/zabbix.asp | 5 +- sql/migration_cleanup_pc_types.sql | 61 ++++++++++++++++----- 9 files changed, 150 insertions(+), 77 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 26698ef..96bbcee 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -24,6 +24,7 @@ ShopDB is a Classic ASP/VBScript web application for managing manufacturing shop - Production IIS logs - Production MySQL database - Zabbix server (10.48.130.113) +- Employee database (wjf_employees) - used by displayprofile.asp (can update code, cannot test) For production tasks, user must: - Relay production data/logs to Claude diff --git a/api.asp b/api.asp index f981ecd..018bfba 100644 --- a/api.asp +++ b/api.asp @@ -1,21 +1,13 @@ <%@ Language=VBScript %> + <% ' ============================================================================ -' DATABASE CONNECTION - Created directly in api.asp to avoid scoping issues +' DATABASE CONNECTION - Uses centralized config.asp ' ============================================================================ -Dim objConn, rs, DB_CONN_STRING -' Use direct MySQL ODBC driver connection (same as sql.asp) instead of DSN -DB_CONN_STRING = "Driver={MySQL ODBC 9.4 Unicode Driver};" & _ - "Server=192.168.122.1;" & _ - "Port=3306;" & _ - "Database=shopdb;" & _ - "User=570005354;" & _ - "Password=570005354;" & _ - "Option=3;" & _ - "Pooling=True;Max Pool Size=100;" -Session.Timeout = 15 +Dim objConn, rs +Session.Timeout = APP_SESSION_TIMEOUT Set objConn = Server.CreateObject("ADODB.Connection") -objConn.ConnectionString = DB_CONN_STRING +objConn.ConnectionString = GetConnectionString() objConn.Open Set rs = Server.CreateObject("ADODB.Recordset") diff --git a/apiusb.asp b/apiusb.asp index 205efbe..5e875a8 100644 --- a/apiusb.asp +++ b/apiusb.asp @@ -1,30 +1,25 @@ <%@ Language="VBScript" %> <% +Option Explicit +%> + +<% '============================================================================= ' FILE: apiusb.asp ' PURPOSE: API endpoints for USB device operations ' SECURITY: Parameterized queries, JSON output ' CREATED: 2025-12-07 '============================================================================= -Option Explicit Response.ContentType = "application/json" Response.Charset = "utf-8" Response.Buffer = True -' Create database connection directly (avoid sql.asp scoping issues) -Dim objConn, DB_CONN_STRING -DB_CONN_STRING = "Driver={MySQL ODBC 9.4 Unicode Driver};" & _ - "Server=192.168.122.1;" & _ - "Port=3306;" & _ - "Database=shopdb;" & _ - "User=570005354;" & _ - "Password=570005354;" & _ - "Option=3;" & _ - "Pooling=True;Max Pool Size=100;" +' Database connection using centralized config +Dim objConn On Error Resume Next Set objConn = Server.CreateObject("ADODB.Connection") -objConn.ConnectionString = DB_CONN_STRING +objConn.ConnectionString = GetConnectionString() objConn.Open If Err.Number <> 0 Then diff --git a/displayprofile.asp b/displayprofile.asp index 010c061..06a8659 100644 --- a/displayprofile.asp +++ b/displayprofile.asp @@ -7,6 +7,7 @@ Option Explicit + @@ -280,15 +281,13 @@ END IF
USB Checkout History
<% -' Connect to shopdb for USB history +' Connect to shopdb for USB history (uses centralized config) Dim objConnShopdb, shopdbAvailable shopdbAvailable = False On Error Resume Next Set objConnShopdb = Server.CreateObject("ADODB.Connection") -objConnShopdb.ConnectionString = "Driver={MySQL ODBC 9.4 Unicode Driver};" & _ - "Server=192.168.122.1;Port=3306;Database=shopdb;" & _ - "User=570005354;Password=570005354;Option=3;" +objConnShopdb.ConnectionString = GetConnectionString() objConnShopdb.Open If Err.Number = 0 Then shopdbAvailable = True diff --git a/includes/config.asp b/includes/config.asp index 31a1cb8..c0d3920 100644 --- a/includes/config.asp +++ b/includes/config.asp @@ -10,8 +10,17 @@ '============================================================================= '----------------------------------------------------------------------------- -' Database Configuration +' Database Configuration - ShopDB (primary) '----------------------------------------------------------------------------- +' Set USE_DSN = True for production (DSN-based), False for dev (direct ODBC) +Const USE_DSN = False + +' DSN configuration (production) +Const DB_DSN = "shopdb" +Const DB_DSN_USER = "570005354" +Const DB_DSN_PASSWORD = "570005354" + +' Direct ODBC configuration (development) Const DB_DRIVER = "MySQL ODBC 9.4 Unicode Driver" Const DB_SERVER = "192.168.122.1" Const DB_PORT = "3306" @@ -19,6 +28,25 @@ Const DB_NAME = "shopdb" Const DB_USER = "570005354" Const DB_PASSWORD = "570005354" +'----------------------------------------------------------------------------- +' Database Configuration - Employee Database +'----------------------------------------------------------------------------- +' Set USE_EMP_DSN = True for production (DSN-based), False for dev (direct ODBC) +Const USE_EMP_DSN = True + +' DSN configuration (production) +Const EMP_DB_DSN = "wjf_employees" +Const EMP_DB_DSN_USER = "root" +Const EMP_DB_DSN_PASSWORD = "WJF11sql" + +' Direct ODBC configuration (development) - configure if needed +Const EMP_DB_DRIVER = "MySQL ODBC 9.4 Unicode Driver" +Const EMP_DB_SERVER = "localhost" +Const EMP_DB_PORT = "3306" +Const EMP_DB_NAME = "wjf_employees" +Const EMP_DB_USER = "root" +Const EMP_DB_PASSWORD = "WJF11sql" + '----------------------------------------------------------------------------- ' Application Settings '----------------------------------------------------------------------------- @@ -42,11 +70,17 @@ Const DEFAULT_MODEL_ID = 1 ' Default model Const DEFAULT_OS_ID = 1 ' Default operating system '----------------------------------------------------------------------------- -' External Services +' External Services - ServiceNow '----------------------------------------------------------------------------- Const SNOW_BASE_URL = "https://geit.service-now.com/now/nav/ui/search/" Const SNOW_TICKET_PREFIXES = "geinc,gechg,gerit,gesct" ' Valid ServiceNow ticket prefixes +'----------------------------------------------------------------------------- +' External Services - Zabbix API +'----------------------------------------------------------------------------- +Const ZABBIX_URL = "http://10.48.130.113:8080/api_jsonrpc.php" +Const ZABBIX_API_TOKEN = "9e60b0544ec77131d94825eaa2f3f1645335539361fd33644aeb8326697aa48d" + '----------------------------------------------------------------------------- ' File Upload '----------------------------------------------------------------------------- @@ -59,18 +93,45 @@ Const ALLOWED_EXTENSIONS = "jpg,jpeg,png,gif,pdf" '----------------------------------------------------------------------------- ' FUNCTION: GetConnectionString -' PURPOSE: Returns the database connection string with all parameters -' RETURNS: Complete ODBC connection string +' PURPOSE: Returns the database connection string based on USE_DSN setting +' RETURNS: DSN connection string (production) or direct ODBC string (dev) '----------------------------------------------------------------------------- Function GetConnectionString() - GetConnectionString = "Driver={" & DB_DRIVER & "};" & _ - "Server=" & DB_SERVER & ";" & _ - "Port=" & DB_PORT & ";" & _ - "Database=" & DB_NAME & ";" & _ - "User=" & DB_USER & ";" & _ - "Password=" & DB_PASSWORD & ";" & _ - "Option=3;" & _ - "Pooling=True;Max Pool Size=100;" + If USE_DSN Then + ' Production: DSN-based connection with pooling + GetConnectionString = "DSN=" & DB_DSN & ";Uid=" & DB_DSN_USER & ";Pwd=" & DB_DSN_PASSWORD & ";Option=3;Pooling=True;Max Pool Size=100;" + Else + ' Development: Direct ODBC driver connection + GetConnectionString = "Driver={" & DB_DRIVER & "};" & _ + "Server=" & DB_SERVER & ";" & _ + "Port=" & DB_PORT & ";" & _ + "Database=" & DB_NAME & ";" & _ + "User=" & DB_USER & ";" & _ + "Password=" & DB_PASSWORD & ";" & _ + "Option=3;" & _ + "Pooling=True;Max Pool Size=100;" + End If +End Function + +'----------------------------------------------------------------------------- +' FUNCTION: GetEmployeeConnectionString +' PURPOSE: Returns the employee database connection string based on USE_EMP_DSN +' RETURNS: DSN connection string (production) or direct ODBC string (dev) +'----------------------------------------------------------------------------- +Function GetEmployeeConnectionString() + If USE_EMP_DSN Then + ' Production: DSN-based connection + GetEmployeeConnectionString = "DSN=" & EMP_DB_DSN & ";Uid=" & EMP_DB_DSN_USER & ";Pwd=" & EMP_DB_DSN_PASSWORD + Else + ' Development: Direct ODBC driver connection + GetEmployeeConnectionString = "Driver={" & EMP_DB_DRIVER & "};" & _ + "Server=" & EMP_DB_SERVER & ";" & _ + "Port=" & EMP_DB_PORT & ";" & _ + "Database=" & EMP_DB_NAME & ";" & _ + "User=" & EMP_DB_USER & ";" & _ + "Password=" & EMP_DB_PASSWORD & ";" & _ + "Option=3;" + End If End Function '----------------------------------------------------------------------------- diff --git a/includes/sql.asp b/includes/sql.asp index 7e6da7f..5ef4dc0 100644 --- a/includes/sql.asp +++ b/includes/sql.asp @@ -1,18 +1,9 @@ + <% ' objConn - script-global connection object (no Dim for global scope) - Session.Timeout=15 - Set objConn=Server.CreateObject("ADODB.Connection") - ' Old DSN connection: - ' objConn.ConnectionString="DSN=shopdb;Uid=root;Pwd=WJF11sql" - ' Direct MySQL ODBC connection with pooling enabled: - objConn.ConnectionString="Driver={MySQL ODBC 9.4 Unicode Driver};" & _ - "Server=192.168.122.1;" & _ - "Port=3306;" & _ - "Database=shopdb;" & _ - "User=570005354;" & _ - "Password=570005354;" & _ - "Option=3;" & _ - "Pooling=True;Max Pool Size=100;" + Session.Timeout = APP_SESSION_TIMEOUT + Set objConn = Server.CreateObject("ADODB.Connection") + objConn.ConnectionString = GetConnectionString() objConn.Open - set rs = server.createobject("ADODB.Recordset") + Set rs = Server.CreateObject("ADODB.Recordset") %> \ No newline at end of file diff --git a/includes/wjf_employees-sql.asp b/includes/wjf_employees-sql.asp index 624a09a..7113eaa 100644 --- a/includes/wjf_employees-sql.asp +++ b/includes/wjf_employees-sql.asp @@ -1,8 +1,10 @@ + <% + ' Employee database connection - uses centralized config Dim objConn - Session.Timeout=15 - Set objConn=Server.CreateObject("ADODB.Connection") - objConn.ConnectionString="DSN=wjf_employees;Uid=root;Pwd=WJF11sql" - objConn.Open - set rs = server.createobject("ADODB.Recordset") + Session.Timeout = APP_SESSION_TIMEOUT + Set objConn = Server.CreateObject("ADODB.Connection") + objConn.ConnectionString = GetEmployeeConnectionString() + objConn.Open + Set rs = Server.CreateObject("ADODB.Recordset") %> \ No newline at end of file diff --git a/includes/zabbix.asp b/includes/zabbix.asp index 1999e17..7dbdd2c 100644 --- a/includes/zabbix.asp +++ b/includes/zabbix.asp @@ -1,7 +1,6 @@ + <% -' Zabbix API Configuration -Const ZABBIX_URL = "http://10.48.130.113:8080/api_jsonrpc.php" -Const ZABBIX_API_TOKEN = "9e60b0544ec77131d94825eaa2f3f1645335539361fd33644aeb8326697aa48d" +' Zabbix API Configuration - uses ZABBIX_URL and ZABBIX_API_TOKEN from config.asp ' Function to make HTTP POST request to Zabbix API with Bearer token Function ZabbixAPICall(jsonRequest) diff --git a/sql/migration_cleanup_pc_types.sql b/sql/migration_cleanup_pc_types.sql index b34eb43..8a67794 100644 --- a/sql/migration_cleanup_pc_types.sql +++ b/sql/migration_cleanup_pc_types.sql @@ -5,10 +5,13 @@ -- ============================================================================ -- -- CHANGES: --- 1. Add primary key to installedapps table --- 2. Migrate machines using PC-specific machinetypes to generic PC (33) + pctypeid --- 3. Update models to use generic PC machinetype --- 4. Remove unused PC machinetypes (34-43, 45-46), keep USB Device (44) +-- 1. Drop duplicate appname_2 index on applications table +-- 2. Add primary key to installedapps table (if not exists) +-- 3. Migrate machines using PC-specific machinetypes to generic PC (33) + pctypeid +-- 4. Update models to use generic PC machinetype +-- 5. Remove unused PC machinetypes (34-43, 45-46), keep USB Device (44) +-- +-- NOTE: This migration is IDEMPOTENT - safe to run multiple times -- -- RUN ON: Production database -- BACKUP FIRST: mysqldump -u root -p shopdb > shopdb_backup_$(date +%Y%m%d).sql @@ -18,16 +21,42 @@ START TRANSACTION; -- ============================================================================ --- 1. ADD PRIMARY KEY TO INSTALLEDAPPS TABLE +-- 1. DROP DUPLICATE INDEX ON APPLICATIONS -- ============================================================================ -ALTER TABLE installedapps -ADD COLUMN installedappid INT AUTO_INCREMENT PRIMARY KEY FIRST; +-- Check if appname_2 index exists before dropping +SET @index_exists = (SELECT COUNT(*) FROM information_schema.STATISTICS + WHERE table_schema = DATABASE() + AND table_name = 'applications' + AND index_name = 'appname_2'); -SELECT 'Added PK to installedapps' AS status; +SET @sql = IF(@index_exists > 0, 'DROP INDEX appname_2 ON applications', 'SELECT "Index appname_2 does not exist" AS status'); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SELECT IF(@index_exists > 0, 'Dropped duplicate appname_2 index', 'Index appname_2 already removed') AS status; -- ============================================================================ --- 2. MIGRATE MACHINES FROM PC-SPECIFIC TYPES TO GENERIC PC (33) + PCTYPEID +-- 2. ADD PRIMARY KEY TO INSTALLEDAPPS TABLE (if not exists) -- ============================================================================ +SET @col_exists = (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE table_schema = DATABASE() + AND table_name = 'installedapps' + AND column_name = 'installedappid'); + +SET @sql = IF(@col_exists = 0, + 'ALTER TABLE installedapps ADD COLUMN installedappid INT AUTO_INCREMENT PRIMARY KEY FIRST', + 'SELECT "Column installedappid already exists" AS status'); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SELECT IF(@col_exists = 0, 'Added PK to installedapps', 'PK installedappid already exists') AS status; + +-- ============================================================================ +-- 3. MIGRATE MACHINES FROM PC-SPECIFIC TYPES TO GENERIC PC (33) + PCTYPEID +-- ============================================================================ +-- These UPDATEs are already idempotent (won't change rows that don't match) -- PC - Standard (36) → machinetypeid=33, pctypeid=1 (Standard) UPDATE machines @@ -64,11 +93,11 @@ UPDATE machines SET machinetypeid = 33, pctypeid = 4 WHERE machinetypeid BETWEEN 34 AND 46 AND pctypeid IS NULL; -SELECT CONCAT('Total machines now using machinetypeid 34-46: ', +SELECT CONCAT('Total machines still using machinetypeid 34-46: ', (SELECT COUNT(*) FROM machines WHERE machinetypeid BETWEEN 34 AND 46)) AS status; -- ============================================================================ --- 3. UPDATE MODELS TO USE GENERIC PC MACHINETYPE (33) +-- 4. UPDATE MODELS TO USE GENERIC PC MACHINETYPE (33) -- ============================================================================ UPDATE models SET machinetypeid = 33 @@ -77,9 +106,10 @@ WHERE machinetypeid BETWEEN 34 AND 46; SELECT CONCAT('Updated ', ROW_COUNT(), ' models to generic PC type') AS status; -- ============================================================================ --- 4. DELETE REDUNDANT MACHINETYPES +-- 5. DELETE REDUNDANT MACHINETYPES -- ============================================================================ -- Keep 33 (PC) and 44 (USB Device), remove 34-43 and 45-46 +-- These DELETEs are already idempotent (won't delete if rows don't exist) DELETE FROM machinetypes WHERE machinetypeid BETWEEN 34 AND 43; SELECT CONCAT('Deleted ', ROW_COUNT(), ' machinetypes (34-43)') AS status; @@ -101,10 +131,13 @@ WHERE m.pctypeid IS NOT NULL GROUP BY m.pctypeid ORDER BY count DESC; +SELECT 'VERIFICATION - Applications indexes:' AS info; +SELECT index_name, column_name FROM information_schema.STATISTICS +WHERE table_schema = DATABASE() AND table_name = 'applications'; + -- ============================================================================ --- COMMIT (uncomment when ready to apply) +-- COMMIT -- ============================================================================ COMMIT; --- ROLLBACK; -- Use this instead if something looks wrong SELECT 'Migration completed successfully!' AS status;