From 82c3b80c745d5923e09d5b4b48910fd175ffc23e Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 10:42:49 -0400 Subject: [PATCH 01/23] refactor: update device path handling and enhance script generation for Fleet setup - Replaced environment variable references for device paths with hardcoded values for macOS and Windows. - Enhanced SQL queries in `createFleetLabelForOrg` and `createFleetLabel` functions to include additional fallback paths and registry checks. - Refactored script generation logic for macOS and Windows, improving clarity and adding detailed logging for setup processes. - Introduced common utility functions for script filename and package retrieval, promoting code reuse and maintainability. --- .../device/create-fleet-label-for-org.ts | 23 +- .../src/app/api/download-agent/fleet-label.ts | 5 +- .../src/app/api/download-agent/route.ts | 8 +- .../src/app/api/download-agent/scripts.ts | 84 +------- .../app/api/download-agent/scripts/common.ts | 44 ++++ .../app/api/download-agent/scripts/index.ts | 3 + .../src/app/api/download-agent/scripts/mac.ts | 120 +++++++++++ .../app/api/download-agent/scripts/windows.ts | 203 ++++++++++++++++++ .../src/app/api/download-agent/token/route.ts | 16 +- 9 files changed, 406 insertions(+), 100 deletions(-) create mode 100644 apps/portal/src/app/api/download-agent/scripts/common.ts create mode 100644 apps/portal/src/app/api/download-agent/scripts/index.ts create mode 100644 apps/portal/src/app/api/download-agent/scripts/mac.ts create mode 100644 apps/portal/src/app/api/download-agent/scripts/windows.ts diff --git a/apps/app/src/jobs/tasks/device/create-fleet-label-for-org.ts b/apps/app/src/jobs/tasks/device/create-fleet-label-for-org.ts index deb595fae..1fead4360 100644 --- a/apps/app/src/jobs/tasks/device/create-fleet-label-for-org.ts +++ b/apps/app/src/jobs/tasks/device/create-fleet-label-for-org.ts @@ -29,16 +29,21 @@ export const createFleetLabelForOrg = task({ return; } - const fleetDevicePathMac = process.env.FLEET_DEVICE_PATH_MAC; - const fleetDevicePathWindows = process.env.FLEET_DEVICE_PATH_WINDOWS; + const fleetDevicePathMac = '/Users/Shared/.fleet'; + const fleetDevicePathWindows = 'C\\\\ProgramData\\\\CompAI\\\\Fleet'.replace(/\\\\/g, '\\'); + const windowsFallbackDir = 'C\\\\Users\\\\Public\\\\CompAI\\\\Fleet'.replace(/\\\\/g, '\\'); - if (!fleetDevicePathMac || !fleetDevicePathWindows) { - logger.error('FLEET_DEVICE_PATH_MAC or FLEET_DEVICE_PATH_WINDOWS not configured'); - return; - } - - // Create a query that matches devices from either macOS or Windows - const query = `SELECT 1 FROM file WHERE path = '${fleetDevicePathMac}/${organizationId}' OR path = '${fleetDevicePathWindows}\\${organizationId}' LIMIT 1;`; + // Create a query that matches devices from macOS or Windows across multiple possible locations + // - macOS: ${fleetDevicePathMac}/${organizationId} + // - Windows primary: ${fleetDevicePathWindows}\\${organizationId} + // - Windows fallback: C:\\Users\\Public\\CompAI\\${organizationId} + // - Windows registry (HKLM/HKCU): OrgId == organizationId + const query = `SELECT 1 FROM file WHERE path = '${fleetDevicePathMac}/${organizationId}' + OR path = '${fleetDevicePathWindows}\\${organizationId}' + OR path = '${windowsFallbackDir}\\${organizationId}' + OR (SELECT data FROM registry WHERE key = 'HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\CompAI\\\\Device' AND name = 'OrgId' AND data = '${organizationId}' LIMIT 1) IS NOT NULL + OR (SELECT data FROM registry WHERE key = 'HKEY_CURRENT_USER\\\\Software\\\\CompAI\\\\Device' AND name = 'OrgId' AND data = '${organizationId}' LIMIT 1) IS NOT NULL + LIMIT 1;`; logger.info('Creating label', { name: organization.id, diff --git a/apps/portal/src/app/api/download-agent/fleet-label.ts b/apps/portal/src/app/api/download-agent/fleet-label.ts index 2ebaa546e..f844dac78 100644 --- a/apps/portal/src/app/api/download-agent/fleet-label.ts +++ b/apps/portal/src/app/api/download-agent/fleet-label.ts @@ -28,7 +28,10 @@ export async function createFleetLabel({ const query = os === 'macos' ? `SELECT 1 FROM file WHERE path = '${fleetDevicePathMac}/${employeeId}' LIMIT 1;` - : `SELECT 1 FROM file WHERE path = '${fleetDevicePathWindows}\\${employeeId}' LIMIT 1;`; + : `SELECT 1 FROM file WHERE path = '${fleetDevicePathWindows}\\${employeeId}' OR path = 'C:\\Users\\Public\\CompAI\\Fleet\\${employeeId}' + OR (SELECT data FROM registry WHERE key = 'HKEY_LOCAL_MACHINE\\SOFTWARE\\CompAI\\Device' AND name = 'EmployeeId' AND data = '${employeeId}' LIMIT 1) IS NOT NULL + OR (SELECT data FROM registry WHERE key = 'HKEY_CURRENT_USER\\Software\\CompAI\\Device' AND name = 'EmployeeId' AND data = '${employeeId}' LIMIT 1) IS NOT NULL + LIMIT 1;`; logger('Generated Fleet query for label creation', { employeeId, diff --git a/apps/portal/src/app/api/download-agent/route.ts b/apps/portal/src/app/api/download-agent/route.ts index 40e085e11..6fc8ec56a 100644 --- a/apps/portal/src/app/api/download-agent/route.ts +++ b/apps/portal/src/app/api/download-agent/route.ts @@ -39,12 +39,12 @@ export async function GET(req: NextRequest) { os: 'macos' | 'windows'; }; - // Check environment configuration - const fleetDevicePathMac = process.env.FLEET_DEVICE_PATH_MAC; - const fleetDevicePathWindows = process.env.FLEET_DEVICE_PATH_WINDOWS; + // Hardcoded device marker paths used by the setup scripts + const fleetDevicePathMac = '/Users/Shared/.fleet'; + const fleetDevicePathWindows = 'C:\\ProgramData\\CompAI\\Fleet'; const fleetBucketName = process.env.FLEET_AGENT_BUCKET_NAME; - if (!fleetDevicePathMac || !fleetDevicePathWindows || !fleetBucketName) { + if (!fleetBucketName) { return new NextResponse('Server configuration error', { status: 500 }); } diff --git a/apps/portal/src/app/api/download-agent/scripts.ts b/apps/portal/src/app/api/download-agent/scripts.ts index 11b25c9de..11e3d7c6b 100644 --- a/apps/portal/src/app/api/download-agent/scripts.ts +++ b/apps/portal/src/app/api/download-agent/scripts.ts @@ -1,73 +1,11 @@ -import type { ScriptConfig, SupportedOS } from './types'; - -export function generateMacScript(config: ScriptConfig): string { - const { orgId, employeeId, fleetDevicePath } = config; - - return `#!/bin/bash -# Create org marker for Fleet policies/labels -set -euo pipefail -ORG_ID="${orgId}" -EMPLOYEE_ID="${employeeId}" -FLEET_DIR="${fleetDevicePath}" -mkdir -p "$FLEET_DIR" -echo "$ORG_ID" > "$FLEET_DIR/${orgId}" -echo "$EMPLOYEE_ID" > "$FLEET_DIR/${employeeId}" -chmod 755 "$FLEET_DIR" -chmod 644 "$FLEET_DIR/${orgId}" -chmod 644 "$FLEET_DIR/${employeeId}" -exit 0`; -} - -export function generateWindowsScript(config: ScriptConfig): string { - const { orgId, employeeId, fleetDevicePath } = config; - - return `@echo off -REM Create org marker for Fleet policies/labels -setlocal -set ORG_ID=${orgId} -set EMPLOYEE_ID=${employeeId} -set FLEET_DIR=${fleetDevicePath} -if not exist "%FLEET_DIR%" mkdir "%FLEET_DIR%" -echo %ORG_ID% > "%FLEET_DIR%\\%ORG_ID%" -echo %EMPLOYEE_ID% > "%FLEET_DIR%\\%EMPLOYEE_ID%" -exit /b 0`; -} - -export function getScriptFilename(os: SupportedOS): string { - return os === 'macos' ? 'run_me_first.command' : 'run_me_first.bat'; -} - -export function getPackageFilename(os: SupportedOS): string { - return os === 'macos' ? 'compai-device-agent.pkg' : 'compai-device-agent.msi'; -} - -export function getReadmeContent(os: SupportedOS): string { - if (os === 'macos') { - return `Installation Instructions for macOS: - -1. First, run the setup script by double-clicking "run_me_first.command" - - This will create the necessary organization markers for device management - - You may need to allow the script to run in System Preferences > Security & Privacy - -2. Then, install the agent by double-clicking "compai-device-agent.pkg" - - Follow the installation wizard - - You may need to allow the installer in System Preferences > Security & Privacy - -3. The agent will start automatically after installation -`; - } - - return `Installation Instructions for Windows: - -1. First, run the setup script: - - Right-click on "run_me_first.bat" and select "Run as administrator" - - This will create the necessary organization markers for device management - -2. Then, install the agent: - - Double-click "compai-device-agent.msi" - - Follow the installation wizard - - Windows may show a security warning - click "More info" and then "Run anyway" - -3. The agent will start automatically after installation -`; -} +import { getPackageFilename, getReadmeContent, getScriptFilename } from './scripts/common'; +import { generateMacScript } from './scripts/mac'; +import { generateWindowsScript } from './scripts/windows'; + +export { + generateMacScript, + generateWindowsScript, + getPackageFilename, + getReadmeContent, + getScriptFilename, +}; diff --git a/apps/portal/src/app/api/download-agent/scripts/common.ts b/apps/portal/src/app/api/download-agent/scripts/common.ts new file mode 100644 index 000000000..dbe01eeac --- /dev/null +++ b/apps/portal/src/app/api/download-agent/scripts/common.ts @@ -0,0 +1,44 @@ +import type { SupportedOS } from '../types'; + +export function getScriptFilename(os: SupportedOS): string { + return os === 'macos' ? 'run_me_first.command' : 'run_me_first.bat'; +} + +export function getPackageFilename(os: SupportedOS): string { + return os === 'macos' ? 'compai-device-agent.pkg' : 'compai-device-agent.msi'; +} + +export function getReadmeContent(os: SupportedOS): string { + if (os === 'macos') { + return `Installation Instructions for macOS: + +1. First, run the setup script by double-clicking "run_me_first.command" + - This will create the necessary organization markers for device management + - You may need to allow the script to run in System Preferences > Security & Privacy + +2. Then, install the agent by double-clicking "compai-device-agent.pkg" + - Follow the installation wizard + - You may need to allow the installer in System Preferences > Security & Privacy + +3. The agent will start automatically after installation +`; + } + + return `Installation Instructions for Windows: + +1. First, run the setup script: + - Right-click on "run_me_first.bat" and select "Run as administrator" (required) + - This writes organization markers to the device and registry + - If prompted by SmartScreen, click "More info" -> "Run anyway" + +2. Then, install the agent: + - Double-click "compai-device-agent.msi" and follow the wizard + +3. Troubleshooting: + - If setup fails, open the log at: %ProgramData%\\CompAI\\Fleet or %Public%\\CompAI\\Fleet -> setup.log + - Ensure your antivirus or endpoint protection allows running local .bat files + - If you cannot run as administrator, ask IT to assist or install both files and registry keys manually + +4. After installation, the agent will start automatically. +`; +} diff --git a/apps/portal/src/app/api/download-agent/scripts/index.ts b/apps/portal/src/app/api/download-agent/scripts/index.ts new file mode 100644 index 000000000..613fb7274 --- /dev/null +++ b/apps/portal/src/app/api/download-agent/scripts/index.ts @@ -0,0 +1,3 @@ +export { getPackageFilename, getReadmeContent, getScriptFilename } from './common'; +export { generateMacScript } from './mac'; +export { generateWindowsScript } from './windows'; diff --git a/apps/portal/src/app/api/download-agent/scripts/mac.ts b/apps/portal/src/app/api/download-agent/scripts/mac.ts new file mode 100644 index 000000000..d51c854f2 --- /dev/null +++ b/apps/portal/src/app/api/download-agent/scripts/mac.ts @@ -0,0 +1,120 @@ +import type { ScriptConfig } from '../types'; + +export function generateMacScript(config: ScriptConfig): string { + const { orgId, employeeId, fleetDevicePath } = config; + + return `#!/bin/bash +# CompAI Device Setup (macOS) +# Creates organization markers for Fleet policies/labels with clear, human-readable output + +set -uo pipefail + +ORG_ID="${orgId}" +EMPLOYEE_ID="${employeeId}" +FLEET_DIR="${fleetDevicePath}" +LOG_FILE="/tmp/compai-setup.log" +HAS_ERROR=0 +ERROR_TEXT="" + +# Colors (ANSI escapes) +NC='\x1b[0m' +GREEN='\x1b[0;32m' +YELLOW='\x1b[0;33m' +RED='\x1b[0;31m' +BOLD='\x1b[1m' + +timestamp() { date '+%Y-%m-%d %H:%M:%S'; } +log_info() { printf "[%s] %bINFO%b %s\n" "$(timestamp)" "$GREEN" "$NC" "$1" | tee -a "$LOG_FILE"; } +log_warn() { printf "[%s] %bWARN%b %s\n" "$(timestamp)" "$YELLOW" "$NC" "$1" | tee -a "$LOG_FILE"; } +log_error() { printf "[%s] %bERROR%b %s\n" "$(timestamp)" "$RED" "$NC" "$1" | tee -a "$LOG_FILE"; HAS_ERROR=1; ERROR_TEXT+=" - $1"$'\n'; } + +echo "------------------------------------------------------------" +printf "%b\n" "$BOLD CompAI Device Setup (macOS)$NC" +echo "Organization: $ORG_ID" +echo "Employee: $EMPLOYEE_ID" +echo "Date: $(timestamp)" +echo "Log file: $LOG_FILE" +echo "------------------------------------------------------------" +echo + +# Determine if we need sudo for the fleet directory +SUDO="" +if [ ! -d "$FLEET_DIR" ]; then + log_info "Creating directory: $FLEET_DIR" + if mkdir -p "$FLEET_DIR" 2>>"$LOG_FILE"; then + : + else + log_warn "No write access creating $FLEET_DIR; retrying with sudo (you may be prompted for your password)." + if sudo mkdir -p "$FLEET_DIR" 2>>"$LOG_FILE"; then + SUDO="sudo" + else + log_error "Failed to create directory $FLEET_DIR even with sudo." + fi + fi +fi + +if [ -d "$FLEET_DIR" ] && [ ! -w "$FLEET_DIR" ]; then + SUDO="sudo" +fi + +if [ -z "$SUDO" ]; then + log_info "Using directory: $FLEET_DIR (no sudo needed)" +else + log_info "Using directory: $FLEET_DIR (sudo required)" +fi + +# Write marker files +if [ -d "$FLEET_DIR" ]; then + log_info "Writing organization marker file..." + if printf "%s" "$ORG_ID" | $SUDO tee "$FLEET_DIR/$ORG_ID" >/dev/null 2>>"$LOG_FILE"; then + log_info "[OK] Organization marker: $FLEET_DIR/$ORG_ID" + else + log_error "Failed writing organization marker to $FLEET_DIR/$ORG_ID" + fi + + log_info "Writing employee marker file..." + if printf "%s" "$EMPLOYEE_ID" | $SUDO tee "$FLEET_DIR/$EMPLOYEE_ID" >/dev/null 2>>"$LOG_FILE"; then + log_info "[OK] Employee marker: $FLEET_DIR/$EMPLOYEE_ID" + else + log_error "Failed writing employee marker to $FLEET_DIR/$EMPLOYEE_ID" + fi + + # Permissions + $SUDO chmod 755 "$FLEET_DIR" 2>>"$LOG_FILE" || log_warn "Could not chmod 755 on $FLEET_DIR" + $SUDO chmod 644 "$FLEET_DIR/$ORG_ID" 2>>"$LOG_FILE" || log_warn "Could not chmod 644 on $FLEET_DIR/$ORG_ID" + $SUDO chmod 644 "$FLEET_DIR/$EMPLOYEE_ID" 2>>"$LOG_FILE" || log_warn "Could not chmod 644 on $FLEET_DIR/$EMPLOYEE_ID" +else + log_error "Directory not available: $FLEET_DIR" +fi + +# Verify markers +echo +log_info "Verifying markers..." +if [ -f "$FLEET_DIR/$EMPLOYEE_ID" ]; then + log_info "[OK] Employee marker file present." +else + log_error "Employee marker file missing at $FLEET_DIR/$EMPLOYEE_ID" +fi + +# Summary +echo +echo "------------------------------------------------------------" +if [ "$HAS_ERROR" -eq 0 ]; then + printf "%b\n" "$GREEN RESULT: SUCCESS $NC" + echo "Setup completed successfully for $EMPLOYEE_ID." + echo "Files created in: $FLEET_DIR" +else + printf "%b\n" "$RED RESULT: COMPLETED WITH ISSUES $NC" + echo "One or more steps did not complete successfully. Details:" + printf "%b" "$ERROR_TEXT" + echo + echo "Next steps:" + echo " - Take a screenshot of this window." + echo " - Attach the log file from: $LOG_FILE" + echo " - Share both with your CompAI support contact." +fi +echo "------------------------------------------------------------" +echo +read -r -p "Press Return to close this window..." _ +exit $HAS_ERROR`; +} diff --git a/apps/portal/src/app/api/download-agent/scripts/windows.ts b/apps/portal/src/app/api/download-agent/scripts/windows.ts new file mode 100644 index 000000000..0f0be9e47 --- /dev/null +++ b/apps/portal/src/app/api/download-agent/scripts/windows.ts @@ -0,0 +1,203 @@ +import type { ScriptConfig } from '../types'; + +export function generateWindowsScript(config: ScriptConfig): string { + const { orgId, employeeId, fleetDevicePath } = config; + + const script = `@echo off +title CompAI Device Setup +setlocal EnableExtensions EnableDelayedExpansion +color 0A + +echo ------------------------------------------------------------ +echo CompAI Device Setup +echo Organization: ${orgId} +echo Employee: ${employeeId} +echo Date: %date% %time% +echo ------------------------------------------------------------ +echo. + +REM Variables +set "ORG_ID=${orgId}" +set "EMPLOYEE_ID=${employeeId}" +set "PRIMARY_DIR=${fleetDevicePath}" +set "FALLBACK_DIR=%PUBLIC%\CompAI\Fleet" +set "CHOSEN_DIR=" +set "LOG_FILE=" +set "HAS_ERROR=0" +set "ERRORS=" + +REM Self-elevate if not running as administrator +net session >nul 2>&1 +if not %errorlevel%==0 ( + color 0E + echo Administrator permission is required. + echo A prompt will appear asking for permission. Please click "Yes". + echo If no prompt appears, right-click this file and select "Run as administrator". + echo. + powershell -NoProfile -ExecutionPolicy Bypass -Command "Start-Process -FilePath '%~f0' -Verb RunAs" + echo This window will now close. The setup will continue in the new window. + pause + exit /b +) +echo Running with administrator privileges. +echo. + +REM Choose a writable directory (primary first, then fallback) +echo Choosing destination directory... +echo Trying primary: %PRIMARY_DIR% +for %%D in ("%PRIMARY_DIR%" "%FALLBACK_DIR%") do ( + if not defined CHOSEN_DIR ( + mkdir "%%~D" >nul 2>&1 + if exist "%%~D" ( + set "CHOSEN_DIR=%%~D" + ) + ) +) + +if not defined CHOSEN_DIR ( + color 0E + echo WARNING: No writable directory found. + echo Primary attempted: %PRIMARY_DIR% + echo Fallback attempted: %FALLBACK_DIR% + echo [%date% %time%] No writable directory found. Primary: %PRIMARY_DIR%, Fallback: %FALLBACK_DIR% >> "%~dp0setup.log" + set "LOG_FILE=%~dp0setup.log" + set "HAS_ERROR=1" + set "ERRORS=!ERRORS!- No writable directory found (Primary: %PRIMARY_DIR%, Fallback: %FALLBACK_DIR%).!nl!" +) else ( + set "LOG_FILE=%CHOSEN_DIR%\setup.log" + echo Using directory: %CHOSEN_DIR% +) +echo Logs will be written to: %LOG_FILE% +echo. + +REM Write marker files +if defined CHOSEN_DIR ( + echo Writing organization marker file... + > "%CHOSEN_DIR%\%ORG_ID%" (echo %ORG_ID%) 2>>"%LOG_FILE%" + if errorlevel 1 ( + color 0E + echo WARNING: Failed writing organization marker file to %CHOSEN_DIR%. + echo [%date% %time%] Failed writing org marker file >> "%LOG_FILE%" + set "HAS_ERROR=1" + set "ERRORS=!ERRORS!- Failed writing organization marker file.!nl!" + ) else ( + echo [OK] Organization marker file: %CHOSEN_DIR%\%ORG_ID% + ) + + echo Writing employee marker file... + > "%CHOSEN_DIR%\%EMPLOYEE_ID%" (echo %EMPLOYEE_ID%) 2>>"%LOG_FILE%" + if errorlevel 1 ( + color 0E + echo WARNING: Failed writing employee marker file to %CHOSEN_DIR%. + echo [%date% %time%] Failed writing employee marker file >> "%LOG_FILE%" + set "HAS_ERROR=1" + set "ERRORS=!ERRORS!- Failed writing employee marker file.!nl!" + ) else ( + echo [OK] Employee marker file: %CHOSEN_DIR%\%EMPLOYEE_ID% + ) +) + +REM Set permissive read ACLs for SYSTEM and Administrators +if defined CHOSEN_DIR ( + echo Setting permissions on marker files... + icacls "%CHOSEN_DIR%" /inheritance:e >nul 2>&1 + icacls "%CHOSEN_DIR%\%ORG_ID%" /grant *S-1-5-18:R *S-1-5-32-544:R /T >nul 2>&1 + icacls "%CHOSEN_DIR%\%EMPLOYEE_ID%" /grant *S-1-5-18:R *S-1-5-32-544:R /T >nul 2>&1 +) + +echo. +echo Writing registry entries (HKLM preferred)... +reg add "HKLM\SOFTWARE\CompAI\Device" /f >nul 2>&1 +if %errorlevel%==0 ( + reg add "HKLM\SOFTWARE\CompAI\Device" /v OrgId /t REG_SZ /d "%ORG_ID" /f >nul 2>&1 + if errorlevel 1 ( + color 0E + echo WARNING: Failed writing OrgId to HKLM. + echo [%date% %time%] Failed writing OrgId to HKLM >> "%LOG_FILE%" + set "HAS_ERROR=1" + set "ERRORS=!ERRORS!- Failed writing OrgId to HKLM registry.!nl!" + ) + reg add "HKLM\SOFTWARE\CompAI\Device" /v EmployeeId /t REG_SZ /d "%EMPLOYEE_ID%" /f >nul 2>&1 + if errorlevel 1 ( + color 0E + echo WARNING: Failed writing EmployeeId to HKLM. + echo [%date% %time%] Failed writing EmployeeId to HKLM >> "%LOG_FILE%" + set "HAS_ERROR=1" + set "ERRORS=!ERRORS!- Failed writing EmployeeId to HKLM registry.!nl!" + ) +) else ( + color 0E + echo Could not write to HKLM (system-wide). Falling back to current user registry (HKCU). + echo [%date% %time%] No admin registry access (HKLM). Falling back to HKCU. >> "%LOG_FILE%" + reg add "HKCU\Software\CompAI\Device" /f >nul 2>&1 + reg add "HKCU\Software\CompAI\Device" /v OrgId /t REG_SZ /d "%ORG_ID%" /f >nul 2>&1 + if errorlevel 1 ( + color 0E + echo WARNING: Failed writing OrgId to HKCU. + echo [%date% %time%] Failed writing OrgId to HKCU >> "%LOG_FILE%" + set "HAS_ERROR=1" + set "ERRORS=!ERRORS!- Failed writing OrgId to HKCU registry.!nl!" + ) + reg add "HKCU\Software\CompAI\Device" /v EmployeeId /t REG_SZ /d "%EMPLOYEE_ID%" /f >nul 2>&1 + if errorlevel 1 ( + color 0E + echo WARNING: Failed writing EmployeeId to HKCU. + echo [%date% %time%] Failed writing EmployeeId to HKCU >> "%LOG_FILE%" + set "HAS_ERROR=1" + set "ERRORS=!ERRORS!- Failed writing EmployeeId to HKCU registry.!nl!" + ) +) + +echo. +echo Verifying markers... +if defined CHOSEN_DIR ( + if not exist "%CHOSEN_DIR%\%EMPLOYEE_ID%" ( + color 0E + echo WARNING: Employee marker file missing at %CHOSEN_DIR%\%EMPLOYEE_ID% + echo [%date% %time%] Verification failed: employee marker file missing >> "%LOG_FILE%" + set "HAS_ERROR=1" + set "ERRORS=!ERRORS!- Employee marker file missing at %CHOSEN_DIR%\%EMPLOYEE_ID%.!nl!" + ) else ( + echo [OK] Employee marker file present. + ) +) +reg query "HKLM\SOFTWARE\CompAI\Device" /v EmployeeId | find "%EMPLOYEE_ID%" >nul 2>&1 +if errorlevel 1 reg query "HKCU\Software\CompAI\Device" /v EmployeeId | find "%EMPLOYEE_ID%" >nul 2>&1 +if errorlevel 1 ( + color 0E + echo WARNING: Registry check failed: EmployeeId not found or mismatched in HKLM/HKCU. + echo [%date% %time%] Warning: registry EmployeeId value not found or mismatched >> "%LOG_FILE%" + set "HAS_ERROR=1" + set "ERRORS=!ERRORS!- Registry EmployeeId not found or mismatched in HKLM/HKCU.!nl!" +) else ( + echo [OK] Registry value found for EmployeeId. +) + +echo. +echo ------------------------------------------------------------ +if "%HAS_ERROR%"=="0" ( + color 0A + echo RESULT: SUCCESS + echo Setup completed successfully for %EMPLOYEE_ID%. + if defined CHOSEN_DIR echo Files created in: %CHOSEN_DIR% + echo Log file: %LOG_FILE% +) else ( + color 0C + echo RESULT: COMPLETED WITH ISSUES + echo One or more steps did not complete successfully. Details: + echo. + echo !ERRORS! + echo. + echo Next steps: + echo - Take a screenshot of this window. + echo - Attach the log file from: %LOG_FILE% + echo - Share both with your CompAI support contact. +) +echo ------------------------------------------------------------ +echo. +echo Press any key to close this window. This will not affect installation. +pause >nul +if "%HAS_ERROR%"=="0" (exit /b 0) else (exit /b 1)`; + + return script.replace(/\n/g, '\r\n'); +} diff --git a/apps/portal/src/app/api/download-agent/token/route.ts b/apps/portal/src/app/api/download-agent/token/route.ts index fabaf8032..883f3e8d1 100644 --- a/apps/portal/src/app/api/download-agent/token/route.ts +++ b/apps/portal/src/app/api/download-agent/token/route.ts @@ -49,19 +49,9 @@ export async function POST(req: NextRequest) { userId: session.user.id, }); - // Check environment configuration for fleet label creation - const fleetDevicePathMac = process.env.FLEET_DEVICE_PATH_MAC; - const fleetDevicePathWindows = process.env.FLEET_DEVICE_PATH_WINDOWS; - - if (!fleetDevicePathMac || !fleetDevicePathWindows) { - logger('Fleet device paths not configured in token route', { - fleetDevicePathMac: !!fleetDevicePathMac, - fleetDevicePathWindows: !!fleetDevicePathWindows, - }); - return new NextResponse('Server configuration error: Fleet device paths are missing.', { - status: 500, - }); - } + // Hardcoded device marker paths used by the setup scripts + const fleetDevicePathMac = '/Users/Shared/.fleet'; + const fleetDevicePathWindows = 'C:\\ProgramData\\CompAI\\Fleet'; // Create Fleet label try { From a0f021569b156300557d1764080507be7f1040d2 Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 11:45:47 -0400 Subject: [PATCH 02/23] chore: add logging for device retrieval and organization checks - Introduced console logs in `getEmployeeDevices` to track organization ID and device retrieval processes. - Added logging in `EmployeeDevicesPage` to display fetched devices. - Normalized SQL queries in `createFleetLabelForOrg` and `createFleetLabel` for improved readability and consistency. --- .../[orgId]/people/devices/data/index.ts | 6 +++++ .../app/(app)/[orgId]/people/devices/page.tsx | 2 ++ .../device/create-fleet-label-for-org.ts | 24 ++++++++----------- .../src/app/api/download-agent/fleet-label.ts | 16 +++++++------ 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/apps/app/src/app/(app)/[orgId]/people/devices/data/index.ts b/apps/app/src/app/(app)/[orgId]/people/devices/data/index.ts index 058239ea1..d21458eb6 100644 --- a/apps/app/src/app/(app)/[orgId]/people/devices/data/index.ts +++ b/apps/app/src/app/(app)/[orgId]/people/devices/data/index.ts @@ -16,6 +16,7 @@ export const getEmployeeDevices: () => Promise = async () => { const organizationId = session?.session.activeOrganizationId; if (!organizationId) { + console.log('No organization id'); return null; } @@ -26,17 +27,22 @@ export const getEmployeeDevices: () => Promise = async () => { }); if (!organization) { + console.log('No organization'); return null; } const labelId = organization.fleetDmLabelId; + console.log('labelId', labelId); // Get all hosts to get their ids. const employeeDevices = await fleet.get(`/labels/${labelId}/hosts`); + console.log('employeeDevices', employeeDevices); const allIds = employeeDevices.data.hosts.map((host: { id: number }) => host.id); + console.log('allIds', allIds); // Get all devices by id. in parallel const devices = await Promise.all(allIds.map((id: number) => fleet.get(`/hosts/${id}`))); + console.log('devices', devices); return devices.map((device: { data: { host: Host } }) => device.data.host); }; diff --git a/apps/app/src/app/(app)/[orgId]/people/devices/page.tsx b/apps/app/src/app/(app)/[orgId]/people/devices/page.tsx index 39d608f43..920248e79 100644 --- a/apps/app/src/app/(app)/[orgId]/people/devices/page.tsx +++ b/apps/app/src/app/(app)/[orgId]/people/devices/page.tsx @@ -15,6 +15,8 @@ export default async function EmployeeDevicesPage() { devices = []; } + console.log('devices', devices); + return (
diff --git a/apps/app/src/jobs/tasks/device/create-fleet-label-for-org.ts b/apps/app/src/jobs/tasks/device/create-fleet-label-for-org.ts index 1fead4360..7a551303c 100644 --- a/apps/app/src/jobs/tasks/device/create-fleet-label-for-org.ts +++ b/apps/app/src/jobs/tasks/device/create-fleet-label-for-org.ts @@ -30,24 +30,20 @@ export const createFleetLabelForOrg = task({ } const fleetDevicePathMac = '/Users/Shared/.fleet'; - const fleetDevicePathWindows = 'C\\\\ProgramData\\\\CompAI\\\\Fleet'.replace(/\\\\/g, '\\'); - const windowsFallbackDir = 'C\\\\Users\\\\Public\\\\CompAI\\\\Fleet'.replace(/\\\\/g, '\\'); + const fleetDevicePathWindows = 'C\\ProgramData\\CompAI\\Fleet'; + const windowsFallbackDir = 'C\\Users\\Public\\CompAI\\Fleet'; - // Create a query that matches devices from macOS or Windows across multiple possible locations - // - macOS: ${fleetDevicePathMac}/${organizationId} - // - Windows primary: ${fleetDevicePathWindows}\\${organizationId} - // - Windows fallback: C:\\Users\\Public\\CompAI\\${organizationId} - // - Windows registry (HKLM/HKCU): OrgId == organizationId - const query = `SELECT 1 FROM file WHERE path = '${fleetDevicePathMac}/${organizationId}' - OR path = '${fleetDevicePathWindows}\\${organizationId}' - OR path = '${windowsFallbackDir}\\${organizationId}' - OR (SELECT data FROM registry WHERE key = 'HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\CompAI\\\\Device' AND name = 'OrgId' AND data = '${organizationId}' LIMIT 1) IS NOT NULL - OR (SELECT data FROM registry WHERE key = 'HKEY_CURRENT_USER\\\\Software\\\\CompAI\\\\Device' AND name = 'OrgId' AND data = '${organizationId}' LIMIT 1) IS NOT NULL + // Simple union query: only file table, constrained per platform path + const query = ` + SELECT 1 FROM file WHERE path = '${fleetDevicePathMac}/${organizationId}' + UNION SELECT 1 FROM file WHERE path = '${fleetDevicePathWindows}\\${organizationId}' + UNION SELECT 1 FROM file WHERE path = '${windowsFallbackDir}\\${organizationId}' LIMIT 1;`; + const normalizedQuery = query.replace(/\s+/g, ' ').trim(); logger.info('Creating label', { name: organization.id, - query: query, + query: normalizedQuery, }); const fleet = await getFleetInstance(); @@ -58,7 +54,7 @@ export const createFleetLabelForOrg = task({ // Create a manual label that we can assign to hosts. labelResponse = await fleet.post('/labels', { name: organization.id, - query: query, + query: normalizedQuery, }); logger.info('Label created', { diff --git a/apps/portal/src/app/api/download-agent/fleet-label.ts b/apps/portal/src/app/api/download-agent/fleet-label.ts index f844dac78..259143e31 100644 --- a/apps/portal/src/app/api/download-agent/fleet-label.ts +++ b/apps/portal/src/app/api/download-agent/fleet-label.ts @@ -24,19 +24,21 @@ export async function createFleetLabel({ const fleet = await getFleetInstance(); logger('Fleet instance obtained successfully'); - // Create platform-specific query + // OS-specific queries: mac uses file-only; Windows uses UNION with file and registry const query = os === 'macos' ? `SELECT 1 FROM file WHERE path = '${fleetDevicePathMac}/${employeeId}' LIMIT 1;` - : `SELECT 1 FROM file WHERE path = '${fleetDevicePathWindows}\\${employeeId}' OR path = 'C:\\Users\\Public\\CompAI\\Fleet\\${employeeId}' - OR (SELECT data FROM registry WHERE key = 'HKEY_LOCAL_MACHINE\\SOFTWARE\\CompAI\\Device' AND name = 'EmployeeId' AND data = '${employeeId}' LIMIT 1) IS NOT NULL - OR (SELECT data FROM registry WHERE key = 'HKEY_CURRENT_USER\\Software\\CompAI\\Device' AND name = 'EmployeeId' AND data = '${employeeId}' LIMIT 1) IS NOT NULL + : `SELECT 1 FROM file WHERE path = '${fleetDevicePathWindows}\\${employeeId}' + UNION SELECT 1 FROM file WHERE path = 'C:\\Users\\Public\\CompAI\\Fleet\\${employeeId}' LIMIT 1;`; + // Normalize whitespace to a single line to avoid issues with newlines/tabs + const normalizedQuery = query.replace(/\s+/g, ' ').trim(); + logger('Generated Fleet query for label creation', { employeeId, os, - query, + query: normalizedQuery, }); logger('Sending POST request to Fleet API to create label...', { @@ -44,13 +46,13 @@ export async function createFleetLabel({ endpoint: '/labels', requestBody: { name: employeeId, - query: query, + query: normalizedQuery, }, }); const response = await fleet.post('/labels', { name: employeeId, - query: query, + query: normalizedQuery, }); logger('Fleet API response received', { From 4b54e2a0d7833aed1da113252967a456c611a2cd Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 11:49:35 -0400 Subject: [PATCH 03/23] refactor: remove unnecessary console logs from device retrieval functions - Eliminated console logs in `getEmployeeDevices` and `EmployeeDevicesPage` to clean up the code and improve performance. - Streamlined the device retrieval process by focusing on essential functionality without debug statements. --- apps/app/src/app/(app)/[orgId]/people/devices/data/index.ts | 6 ------ apps/app/src/app/(app)/[orgId]/people/devices/page.tsx | 2 -- 2 files changed, 8 deletions(-) diff --git a/apps/app/src/app/(app)/[orgId]/people/devices/data/index.ts b/apps/app/src/app/(app)/[orgId]/people/devices/data/index.ts index d21458eb6..058239ea1 100644 --- a/apps/app/src/app/(app)/[orgId]/people/devices/data/index.ts +++ b/apps/app/src/app/(app)/[orgId]/people/devices/data/index.ts @@ -16,7 +16,6 @@ export const getEmployeeDevices: () => Promise = async () => { const organizationId = session?.session.activeOrganizationId; if (!organizationId) { - console.log('No organization id'); return null; } @@ -27,22 +26,17 @@ export const getEmployeeDevices: () => Promise = async () => { }); if (!organization) { - console.log('No organization'); return null; } const labelId = organization.fleetDmLabelId; - console.log('labelId', labelId); // Get all hosts to get their ids. const employeeDevices = await fleet.get(`/labels/${labelId}/hosts`); - console.log('employeeDevices', employeeDevices); const allIds = employeeDevices.data.hosts.map((host: { id: number }) => host.id); - console.log('allIds', allIds); // Get all devices by id. in parallel const devices = await Promise.all(allIds.map((id: number) => fleet.get(`/hosts/${id}`))); - console.log('devices', devices); return devices.map((device: { data: { host: Host } }) => device.data.host); }; diff --git a/apps/app/src/app/(app)/[orgId]/people/devices/page.tsx b/apps/app/src/app/(app)/[orgId]/people/devices/page.tsx index 920248e79..39d608f43 100644 --- a/apps/app/src/app/(app)/[orgId]/people/devices/page.tsx +++ b/apps/app/src/app/(app)/[orgId]/people/devices/page.tsx @@ -15,8 +15,6 @@ export default async function EmployeeDevicesPage() { devices = []; } - console.log('devices', devices); - return (
From 900d99a7be390e19036c82a7ccd27ef71f5228bf Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 12:21:56 -0400 Subject: [PATCH 04/23] feat: enhance download agent with improved error handling and configuration - Added runtime, dynamic, and maxDuration settings for the download agent. - Implemented robust error handling for archiving and S3 streaming processes to improve reliability. - Introduced logging for various error scenarios to facilitate debugging and monitoring. --- .../src/app/api/download-agent/route.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/apps/portal/src/app/api/download-agent/route.ts b/apps/portal/src/app/api/download-agent/route.ts index 6fc8ec56a..ccfafac24 100644 --- a/apps/portal/src/app/api/download-agent/route.ts +++ b/apps/portal/src/app/api/download-agent/route.ts @@ -13,6 +13,10 @@ import { getScriptFilename, } from './scripts'; +export const runtime = 'nodejs'; +export const dynamic = 'force-dynamic'; +export const maxDuration = 60; + // GET handler for direct browser downloads using token export async function GET(req: NextRequest) { const searchParams = req.nextUrl.searchParams; @@ -63,6 +67,21 @@ export async function GET(req: NextRequest) { // Pipe archive to passthrough archive.pipe(passThrough); + // Robust error handling for staging/prod reliability + archive.on('error', (err) => { + logger('archiver_error', { message: err?.message, stack: (err as Error)?.stack }); + passThrough.destroy(err as Error); + }); + archive.on('warning', (warn) => { + logger('archiver_warning', { message: (warn as Error)?.message }); + }); + passThrough.on('error', (err) => { + logger('download_stream_error', { + message: (err as Error)?.message, + stack: (err as Error)?.stack, + }); + }); + // Add script file const scriptFilename = getScriptFilename(os); archive.append(script, { name: scriptFilename, mode: 0o755 }); @@ -84,6 +103,13 @@ export async function GET(req: NextRequest) { if (s3Response.Body) { const s3Stream = s3Response.Body as Readable; + s3Stream.on('error', (err) => { + logger('s3_stream_error', { + message: (err as Error)?.message, + stack: (err as Error)?.stack, + }); + passThrough.destroy(err as Error); + }); archive.append(s3Stream, { name: packageFilename, store: true }); } @@ -99,6 +125,7 @@ export async function GET(req: NextRequest) { 'Content-Type': 'application/zip', 'Content-Disposition': `attachment; filename="compai-device-agent-${os}.zip"`, 'Cache-Control': 'no-cache, no-store, must-revalidate', + 'X-Accel-Buffering': 'no', }, }); } catch (error) { From 0254930a0f9c19b5f8959eae3c4cff3e9f89e439 Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 13:30:17 -0400 Subject: [PATCH 05/23] refactor: remove fleet feature flag checks from employee and organization components - Eliminated the `isFleetEnabled` checks from various components, simplifying the logic and ensuring the 'Device' tab is always displayed. - Updated related components to directly render device information without conditional rendering based on fleet feature availability. - Cleaned up imports and props to reflect the removal of fleet feature dependencies. --- .../[employeeId]/components/Employee.tsx | 3 - .../[employeeId]/components/EmployeeTasks.tsx | 80 +++++++++---------- .../[orgId]/people/[employeeId]/page.tsx | 6 -- .../src/app/(app)/[orgId]/people/layout.tsx | 18 +---- .../[orgId]/components/EmployeeTasksList.tsx | 18 ++--- .../components/OrganizationDashboard.tsx | 3 - .../src/app/(app)/(home)/[orgId]/page.tsx | 21 +---- 7 files changed, 51 insertions(+), 98 deletions(-) diff --git a/apps/app/src/app/(app)/[orgId]/people/[employeeId]/components/Employee.tsx b/apps/app/src/app/(app)/[orgId]/people/[employeeId]/components/Employee.tsx index ed9631250..8e786a0b0 100644 --- a/apps/app/src/app/(app)/[orgId]/people/[employeeId]/components/Employee.tsx +++ b/apps/app/src/app/(app)/[orgId]/people/[employeeId]/components/Employee.tsx @@ -16,7 +16,6 @@ interface EmployeeDetailsProps { })[]; fleetPolicies: FleetPolicy[]; host: Host; - isFleetEnabled: boolean; } export function Employee({ @@ -25,7 +24,6 @@ export function Employee({ trainingVideos, fleetPolicies, host, - isFleetEnabled, }: EmployeeDetailsProps) { return (
@@ -36,7 +34,6 @@ export function Employee({ trainingVideos={trainingVideos} fleetPolicies={fleetPolicies} host={host} - isFleetEnabled={isFleetEnabled} />
); diff --git a/apps/app/src/app/(app)/[orgId]/people/[employeeId]/components/EmployeeTasks.tsx b/apps/app/src/app/(app)/[orgId]/people/[employeeId]/components/EmployeeTasks.tsx index 35a938e3f..4a0ecb92b 100644 --- a/apps/app/src/app/(app)/[orgId]/people/[employeeId]/components/EmployeeTasks.tsx +++ b/apps/app/src/app/(app)/[orgId]/people/[employeeId]/components/EmployeeTasks.tsx @@ -13,7 +13,6 @@ export const EmployeeTasks = ({ trainingVideos, host, fleetPolicies, - isFleetEnabled, }: { employee: Member & { user: User; @@ -24,7 +23,6 @@ export const EmployeeTasks = ({ })[]; host: Host; fleetPolicies: FleetPolicy[]; - isFleetEnabled: boolean; }) => { return ( @@ -43,7 +41,7 @@ export const EmployeeTasks = ({ Policies Training Videos - {isFleetEnabled && Device} + Device @@ -116,45 +114,43 @@ export const EmployeeTasks = ({
- {isFleetEnabled && ( - - {host ? ( - - - {host.computer_name}'s Policies - - - {fleetPolicies.map((policy) => ( -
-

{policy.name}

- {policy.response === 'pass' ? ( -
- - Pass -
- ) : ( -
- - Fail -
- )} -
- ))} -
-
- ) : ( -
-

No device found.

-
- )} -
- )} + + {host ? ( + + + {host.computer_name}'s Policies + + + {fleetPolicies.map((policy) => ( +
+

{policy.name}

+ {policy.response === 'pass' ? ( +
+ + Pass +
+ ) : ( +
+ + Fail +
+ )} +
+ ))} +
+
+ ) : ( +
+

No device found.

+
+ )} +
diff --git a/apps/app/src/app/(app)/[orgId]/people/[employeeId]/page.tsx b/apps/app/src/app/(app)/[orgId]/people/[employeeId]/page.tsx index 61e870d0d..859ad22fc 100644 --- a/apps/app/src/app/(app)/[orgId]/people/[employeeId]/page.tsx +++ b/apps/app/src/app/(app)/[orgId]/people/[employeeId]/page.tsx @@ -1,6 +1,5 @@ import { auth } from '@/utils/auth'; -import { getPostHogClient } from '@/app/posthog'; import { type TrainingVideo, trainingVideos as trainingVideosData, @@ -40,10 +39,6 @@ export default async function EmployeeDetailsPage({ } const { fleetPolicies, device } = await getFleetPolicies(employee); - const isFleetEnabled = await getPostHogClient()?.isFeatureEnabled( - 'is-fleet-enabled', - session?.session.userId, - ); return ( ); } diff --git a/apps/app/src/app/(app)/[orgId]/people/layout.tsx b/apps/app/src/app/(app)/[orgId]/people/layout.tsx index f0aa85263..2efccc86b 100644 --- a/apps/app/src/app/(app)/[orgId]/people/layout.tsx +++ b/apps/app/src/app/(app)/[orgId]/people/layout.tsx @@ -1,4 +1,3 @@ -import { getPostHogClient } from '@/app/posthog'; import { auth } from '@/utils/auth'; import { SecondaryMenu } from '@comp/ui/secondary-menu'; import { db } from '@db'; @@ -27,11 +26,6 @@ export default async function Layout({ children }: { children: React.ReactNode } return roles.includes('employee'); }); - const isFleetEnabled = await getPostHogClient()?.isFeatureEnabled( - 'is-fleet-enabled', - session?.session.userId, - ); - return (
diff --git a/apps/portal/src/app/(app)/(home)/[orgId]/components/EmployeeTasksList.tsx b/apps/portal/src/app/(app)/(home)/[orgId]/components/EmployeeTasksList.tsx index 69e5292da..4113cdcc2 100644 --- a/apps/portal/src/app/(app)/(home)/[orgId]/components/EmployeeTasksList.tsx +++ b/apps/portal/src/app/(app)/(home)/[orgId]/components/EmployeeTasksList.tsx @@ -15,7 +15,6 @@ interface EmployeeTasksListProps { member: Member; fleetPolicies: FleetPolicy[]; host: Host | null; - isFleetEnabled: boolean; } export const EmployeeTasksList = ({ @@ -24,7 +23,6 @@ export const EmployeeTasksList = ({ member, fleetPolicies, host, - isFleetEnabled, }: EmployeeTasksListProps) => { // Check completion status const hasAcceptedPolicies = @@ -58,16 +56,12 @@ export const EmployeeTasksList = ({ title: 'Accept security policies', content: , }, - ...(isFleetEnabled - ? [ - { - title: 'Download and install Comp AI Device Agent', - content: ( - - ), - }, - ] - : []), + { + title: 'Download and install Comp AI Device Agent', + content: ( + + ), + }, { title: 'Complete general security awareness training', content: , diff --git a/apps/portal/src/app/(app)/(home)/[orgId]/components/OrganizationDashboard.tsx b/apps/portal/src/app/(app)/(home)/[orgId]/components/OrganizationDashboard.tsx index a8a56080e..48feb21e8 100644 --- a/apps/portal/src/app/(app)/(home)/[orgId]/components/OrganizationDashboard.tsx +++ b/apps/portal/src/app/(app)/(home)/[orgId]/components/OrganizationDashboard.tsx @@ -15,7 +15,6 @@ interface OrganizationDashboardProps { member: MemberWithUserOrg; // Pass the full member object for user info etc. fleetPolicies: FleetPolicy[]; host: Host | null; - isFleetEnabled: boolean; } export async function OrganizationDashboard({ @@ -23,7 +22,6 @@ export async function OrganizationDashboard({ member, fleetPolicies, host, - isFleetEnabled, }: OrganizationDashboardProps) { // Fetch policies specific to the selected organization const policies = await db.policy.findMany({ @@ -74,7 +72,6 @@ export async function OrganizationDashboard({ member={member} // Pass the member object down fleetPolicies={fleetPolicies} host={host} - isFleetEnabled={isFleetEnabled ?? false} /> ); } diff --git a/apps/portal/src/app/(app)/(home)/[orgId]/page.tsx b/apps/portal/src/app/(app)/(home)/[orgId]/page.tsx index 91a7483d7..79b16971c 100644 --- a/apps/portal/src/app/(app)/(home)/[orgId]/page.tsx +++ b/apps/portal/src/app/(app)/(home)/[orgId]/page.tsx @@ -1,7 +1,6 @@ 'use server'; import { auth } from '@/app/lib/auth'; -import { getPostHogClient } from '@/app/posthog'; import { getFleetInstance } from '@/utils/fleet'; import type { Member } from '@db'; import { db } from '@db'; @@ -45,26 +44,13 @@ export default async function OrganizationPage({ params }: { params: Promise<{ o return redirect('/'); // Or appropriate login/auth route } - // Check fleet feature flag first - let isFleetEnabled = false; - try { - const postHogClient = await getPostHogClient(); - isFleetEnabled = - (await postHogClient?.isFeatureEnabled('is-fleet-enabled', session?.user.id)) ?? false; - } catch (error) { - console.error('Error checking fleet feature flag:', error); - // Default to false if there's an error - } - // Only fetch fleet policies if fleet is enabled let fleetPolicies: FleetPolicy[] = []; let device: Host | null = null; - if (isFleetEnabled) { - const fleetData = await getFleetPolicies(member); - fleetPolicies = fleetData.fleetPolicies; - device = fleetData.device; - } + const fleetData = await getFleetPolicies(member); + fleetPolicies = fleetData.fleetPolicies; + device = fleetData.device; return ( ); } catch (error) { From fe37a738822d0ec16437652724e76280224e13ca Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 13:45:16 -0400 Subject: [PATCH 06/23] fix: update marker file handling in Windows script - Changed references from CHOSEN_DIR to MARKER_DIR for improved clarity and consistency in file path handling. - Ensured that marker files are written and permissions are set correctly using the updated MARKER_DIR variable. - Enhanced logging messages to reflect the new directory variable for better debugging. --- .../app/api/download-agent/scripts/windows.ts | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/apps/portal/src/app/api/download-agent/scripts/windows.ts b/apps/portal/src/app/api/download-agent/scripts/windows.ts index 0f0be9e47..b3ed61529 100644 --- a/apps/portal/src/app/api/download-agent/scripts/windows.ts +++ b/apps/portal/src/app/api/download-agent/scripts/windows.ts @@ -64,8 +64,10 @@ if not defined CHOSEN_DIR ( set "HAS_ERROR=1" set "ERRORS=!ERRORS!- No writable directory found (Primary: %PRIMARY_DIR%, Fallback: %FALLBACK_DIR%).!nl!" ) else ( - set "LOG_FILE=%CHOSEN_DIR%\setup.log" - echo Using directory: %CHOSEN_DIR% + set "MARKER_DIR=%CHOSEN_DIR%" + if not "%MARKER_DIR:~-1%"=="\\" set "MARKER_DIR=%MARKER_DIR%\\" + set "LOG_FILE=%MARKER_DIR%setup.log" + echo Using directory: %MARKER_DIR% ) echo Logs will be written to: %LOG_FILE% echo. @@ -73,36 +75,36 @@ echo. REM Write marker files if defined CHOSEN_DIR ( echo Writing organization marker file... - > "%CHOSEN_DIR%\%ORG_ID%" (echo %ORG_ID%) 2>>"%LOG_FILE%" + > "%MARKER_DIR%%ORG_ID%" (echo %ORG_ID%) 2>>"%LOG_FILE%" if errorlevel 1 ( color 0E - echo WARNING: Failed writing organization marker file to %CHOSEN_DIR%. + echo WARNING: Failed writing organization marker file to %MARKER_DIR%. echo [%date% %time%] Failed writing org marker file >> "%LOG_FILE%" set "HAS_ERROR=1" set "ERRORS=!ERRORS!- Failed writing organization marker file.!nl!" ) else ( - echo [OK] Organization marker file: %CHOSEN_DIR%\%ORG_ID% + echo [OK] Organization marker file: %MARKER_DIR%%ORG_ID% ) echo Writing employee marker file... - > "%CHOSEN_DIR%\%EMPLOYEE_ID%" (echo %EMPLOYEE_ID%) 2>>"%LOG_FILE%" + > "%MARKER_DIR%%EMPLOYEE_ID%" (echo %EMPLOYEE_ID%) 2>>"%LOG_FILE%" if errorlevel 1 ( color 0E - echo WARNING: Failed writing employee marker file to %CHOSEN_DIR%. + echo WARNING: Failed writing employee marker file to %MARKER_DIR%. echo [%date% %time%] Failed writing employee marker file >> "%LOG_FILE%" set "HAS_ERROR=1" set "ERRORS=!ERRORS!- Failed writing employee marker file.!nl!" ) else ( - echo [OK] Employee marker file: %CHOSEN_DIR%\%EMPLOYEE_ID% + echo [OK] Employee marker file: %MARKER_DIR%%EMPLOYEE_ID% ) ) REM Set permissive read ACLs for SYSTEM and Administrators if defined CHOSEN_DIR ( echo Setting permissions on marker files... - icacls "%CHOSEN_DIR%" /inheritance:e >nul 2>&1 - icacls "%CHOSEN_DIR%\%ORG_ID%" /grant *S-1-5-18:R *S-1-5-32-544:R /T >nul 2>&1 - icacls "%CHOSEN_DIR%\%EMPLOYEE_ID%" /grant *S-1-5-18:R *S-1-5-32-544:R /T >nul 2>&1 + icacls "%MARKER_DIR%" /inheritance:e >nul 2>&1 + icacls "%MARKER_DIR%%ORG_ID%" /grant *S-1-5-18:R *S-1-5-32-544:R /T >nul 2>&1 + icacls "%MARKER_DIR%%EMPLOYEE_ID%" /grant *S-1-5-18:R *S-1-5-32-544:R /T >nul 2>&1 ) echo. @@ -151,9 +153,9 @@ if %errorlevel%==0 ( echo. echo Verifying markers... if defined CHOSEN_DIR ( - if not exist "%CHOSEN_DIR%\%EMPLOYEE_ID%" ( + if not exist "%MARKER_DIR%%EMPLOYEE_ID%" ( color 0E - echo WARNING: Employee marker file missing at %CHOSEN_DIR%\%EMPLOYEE_ID% + echo WARNING: Employee marker file missing at %MARKER_DIR%%EMPLOYEE_ID% echo [%date% %time%] Verification failed: employee marker file missing >> "%LOG_FILE%" set "HAS_ERROR=1" set "ERRORS=!ERRORS!- Employee marker file missing at %CHOSEN_DIR%\%EMPLOYEE_ID%.!nl!" From a313739b3ff8c6481342ef4872fec4b2698886c8 Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 13:48:01 -0400 Subject: [PATCH 07/23] fix: improve PowerShell command in Windows script for better execution - Updated the PowerShell command to use '%comspec%' for improved compatibility and added argument handling for better execution context. - Ensured the working directory is set correctly to maintain the script's operational context during execution. --- apps/portal/src/app/api/download-agent/scripts/windows.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/portal/src/app/api/download-agent/scripts/windows.ts b/apps/portal/src/app/api/download-agent/scripts/windows.ts index b3ed61529..640403d91 100644 --- a/apps/portal/src/app/api/download-agent/scripts/windows.ts +++ b/apps/portal/src/app/api/download-agent/scripts/windows.ts @@ -34,7 +34,7 @@ if not %errorlevel%==0 ( echo A prompt will appear asking for permission. Please click "Yes". echo If no prompt appears, right-click this file and select "Run as administrator". echo. - powershell -NoProfile -ExecutionPolicy Bypass -Command "Start-Process -FilePath '%~f0' -Verb RunAs" + powershell -NoProfile -ExecutionPolicy Bypass -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/k','\"%~f0\"' -WorkingDirectory '%cd%'" echo This window will now close. The setup will continue in the new window. pause exit /b From 9b4aeee2cfca20766bc6d457ef83f465dc52f700 Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 13:56:09 -0400 Subject: [PATCH 08/23] fix: enhance elevation process in Windows script for better user experience - Updated the script to create a temporary VBS file for elevating permissions, improving the user experience during setup. - Added clear messaging to inform users about the elevation process and the behavior of the new window. - Ensured the temporary VBS file is deleted after execution to maintain a clean environment. --- apps/portal/src/app/api/download-agent/scripts/windows.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/portal/src/app/api/download-agent/scripts/windows.ts b/apps/portal/src/app/api/download-agent/scripts/windows.ts index 640403d91..a15c7fb6c 100644 --- a/apps/portal/src/app/api/download-agent/scripts/windows.ts +++ b/apps/portal/src/app/api/download-agent/scripts/windows.ts @@ -34,8 +34,12 @@ if not %errorlevel%==0 ( echo A prompt will appear asking for permission. Please click "Yes". echo If no prompt appears, right-click this file and select "Run as administrator". echo. - powershell -NoProfile -ExecutionPolicy Bypass -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/k','\"%~f0\"' -WorkingDirectory '%cd%'" - echo This window will now close. The setup will continue in the new window. + echo Elevating... A new window will open and remain open after running. + > "%TEMP%\getadmin.vbs" echo Set UAC = CreateObject^("Shell.Application"^) + >> "%TEMP%\getadmin.vbs" echo UAC.ShellExecute "%~f0", "", "", "runas", 1 + wscript "%TEMP%\getadmin.vbs" >nul 2>&1 + del "%TEMP%\getadmin.vbs" >nul 2>&1 + echo This window will now close. The setup will continue in the new (admin) window. pause exit /b ) From 1a67177a638a87576c662dafefaad39158ef0884 Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 14:05:56 -0400 Subject: [PATCH 09/23] fix: enhance elevation and error handling in Windows script - Improved the elevation process by allowing users to choose between automatic elevation and manual execution as Administrator. - Updated messaging to provide clearer instructions during the elevation process. - Added exit codes for better error handling and logging throughout the script execution. - Ensured consistent use of the MARKER_DIR variable for file path handling and improved logging for error scenarios. --- .../app/api/download-agent/scripts/windows.ts | 63 ++++++++++++++----- 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/apps/portal/src/app/api/download-agent/scripts/windows.ts b/apps/portal/src/app/api/download-agent/scripts/windows.ts index a15c7fb6c..91d63f53c 100644 --- a/apps/portal/src/app/api/download-agent/scripts/windows.ts +++ b/apps/portal/src/app/api/download-agent/scripts/windows.ts @@ -25,25 +25,51 @@ set "CHOSEN_DIR=" set "LOG_FILE=" set "HAS_ERROR=0" set "ERRORS=" +set "EXIT_CODE=0" -REM Self-elevate if not running as administrator -net session >nul 2>&1 -if not %errorlevel%==0 ( +REM Capture elevation flag if passed +set "ELEVATED_FLAG=%~1" + +REM Self-elevate if not running as administrator (check High Mandatory Level) +whoami /groups | find "S-1-16-12288" >nul 2>&1 +if errorlevel 1 if /I not "%ELEVATED_FLAG%"=="elevated" ( color 0E echo Administrator permission is required. echo A prompt will appear asking for permission. Please click "Yes". echo If no prompt appears, right-click this file and select "Run as administrator". echo. - echo Elevating... A new window will open and remain open after running. - > "%TEMP%\getadmin.vbs" echo Set UAC = CreateObject^("Shell.Application"^) - >> "%TEMP%\getadmin.vbs" echo UAC.ShellExecute "%~f0", "", "", "runas", 1 - wscript "%TEMP%\getadmin.vbs" >nul 2>&1 - del "%TEMP%\getadmin.vbs" >nul 2>&1 - echo This window will now close. The setup will continue in the new (admin) window. - pause - exit /b + echo Choose an option: + echo [Y] Try to auto-elevate (recommended) + echo [N] I will re-run manually as Administrator + choice /C YN /N /M "Attempt automatic elevation? (Y/N): " + if errorlevel 2 ( + echo. + echo Please close this window and re-run the script by right-clicking it and selecting "Run as administrator". + echo Press any key to exit. + pause >nul + exit /b + ) else ( + echo Elevating... A new window will open and remain open after running. + rem Try PowerShell elevation first (keeps admin window open with /k) + powershell -NoProfile -ExecutionPolicy Bypass -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/k','\"%~f0 elevated\"' -WorkingDirectory '%~dp0'" 2>nul + rem Fallback to VBScript if PowerShell attempt failed or is blocked + if not exist "%TEMP%\elevate.tmp" ( + > "%TEMP%\getadmin.vbs" echo Set UAC = CreateObject^("Shell.Application"^) + >> "%TEMP%\getadmin.vbs" echo UAC.ShellExecute "%~f0", "elevated", "", "runas", 1 + wscript "%TEMP%\getadmin.vbs" >nul 2>&1 + del "%TEMP%\getadmin.vbs" >nul 2>&1 + ) + echo. + echo This window will now stay open so you can see messages. + echo Once the new admin window appears, you may close this one after confirming progress. + echo Press any key to exit this non-admin window. + pause >nul + exit /b + ) ) echo Running with administrator privileges. +echo Current directory: %cd% +echo Script path: %~f0 echo. REM Choose a writable directory (primary first, then fallback) @@ -67,6 +93,7 @@ if not defined CHOSEN_DIR ( set "LOG_FILE=%~dp0setup.log" set "HAS_ERROR=1" set "ERRORS=!ERRORS!- No writable directory found (Primary: %PRIMARY_DIR%, Fallback: %FALLBACK_DIR%).!nl!" + set "EXIT_CODE=1" ) else ( set "MARKER_DIR=%CHOSEN_DIR%" if not "%MARKER_DIR:~-1%"=="\\" set "MARKER_DIR=%MARKER_DIR%\\" @@ -86,6 +113,7 @@ if defined CHOSEN_DIR ( echo [%date% %time%] Failed writing org marker file >> "%LOG_FILE%" set "HAS_ERROR=1" set "ERRORS=!ERRORS!- Failed writing organization marker file.!nl!" + set "EXIT_CODE=1" ) else ( echo [OK] Organization marker file: %MARKER_DIR%%ORG_ID% ) @@ -98,6 +126,7 @@ if defined CHOSEN_DIR ( echo [%date% %time%] Failed writing employee marker file >> "%LOG_FILE%" set "HAS_ERROR=1" set "ERRORS=!ERRORS!- Failed writing employee marker file.!nl!" + set "EXIT_CODE=1" ) else ( echo [OK] Employee marker file: %MARKER_DIR%%EMPLOYEE_ID% ) @@ -122,6 +151,7 @@ if %errorlevel%==0 ( echo [%date% %time%] Failed writing OrgId to HKLM >> "%LOG_FILE%" set "HAS_ERROR=1" set "ERRORS=!ERRORS!- Failed writing OrgId to HKLM registry.!nl!" + set "EXIT_CODE=1" ) reg add "HKLM\SOFTWARE\CompAI\Device" /v EmployeeId /t REG_SZ /d "%EMPLOYEE_ID%" /f >nul 2>&1 if errorlevel 1 ( @@ -130,6 +160,7 @@ if %errorlevel%==0 ( echo [%date% %time%] Failed writing EmployeeId to HKLM >> "%LOG_FILE%" set "HAS_ERROR=1" set "ERRORS=!ERRORS!- Failed writing EmployeeId to HKLM registry.!nl!" + set "EXIT_CODE=1" ) ) else ( color 0E @@ -143,6 +174,7 @@ if %errorlevel%==0 ( echo [%date% %time%] Failed writing OrgId to HKCU >> "%LOG_FILE%" set "HAS_ERROR=1" set "ERRORS=!ERRORS!- Failed writing OrgId to HKCU registry.!nl!" + set "EXIT_CODE=1" ) reg add "HKCU\Software\CompAI\Device" /v EmployeeId /t REG_SZ /d "%EMPLOYEE_ID%" /f >nul 2>&1 if errorlevel 1 ( @@ -151,6 +183,7 @@ if %errorlevel%==0 ( echo [%date% %time%] Failed writing EmployeeId to HKCU >> "%LOG_FILE%" set "HAS_ERROR=1" set "ERRORS=!ERRORS!- Failed writing EmployeeId to HKCU registry.!nl!" + set "EXIT_CODE=1" ) ) @@ -162,7 +195,8 @@ if defined CHOSEN_DIR ( echo WARNING: Employee marker file missing at %MARKER_DIR%%EMPLOYEE_ID% echo [%date% %time%] Verification failed: employee marker file missing >> "%LOG_FILE%" set "HAS_ERROR=1" - set "ERRORS=!ERRORS!- Employee marker file missing at %CHOSEN_DIR%\%EMPLOYEE_ID%.!nl!" + set "ERRORS=!ERRORS!- Employee marker file missing at %MARKER_DIR%%EMPLOYEE_ID%.!nl!" + set "EXIT_CODE=2" ) else ( echo [OK] Employee marker file present. ) @@ -175,6 +209,7 @@ if errorlevel 1 ( echo [%date% %time%] Warning: registry EmployeeId value not found or mismatched >> "%LOG_FILE%" set "HAS_ERROR=1" set "ERRORS=!ERRORS!- Registry EmployeeId not found or mismatched in HKLM/HKCU.!nl!" + set "EXIT_CODE=2" ) else ( echo [OK] Registry value found for EmployeeId. ) @@ -202,8 +237,8 @@ if "%HAS_ERROR%"=="0" ( echo ------------------------------------------------------------ echo. echo Press any key to close this window. This will not affect installation. -pause >nul -if "%HAS_ERROR%"=="0" (exit /b 0) else (exit /b 1)`; +pause +if "%HAS_ERROR%"=="0" (exit /b 0) else (exit /b %EXIT_CODE%)`; return script.replace(/\n/g, '\r\n'); } From 2705540a6c21cffc581c546ee1d4f7eab7e9e1ce Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 14:18:59 -0400 Subject: [PATCH 10/23] fix: streamline elevation process in Windows script for clarity - Removed the option for automatic elevation, simplifying the user experience. - Updated messaging to clearly instruct users to run the script as Administrator. - Enhanced error handling by providing a specific exit code when not run with elevated privileges. --- .../app/api/download-agent/scripts/windows.ts | 43 +++---------------- 1 file changed, 7 insertions(+), 36 deletions(-) diff --git a/apps/portal/src/app/api/download-agent/scripts/windows.ts b/apps/portal/src/app/api/download-agent/scripts/windows.ts index 91d63f53c..fa8e5a5fe 100644 --- a/apps/portal/src/app/api/download-agent/scripts/windows.ts +++ b/apps/portal/src/app/api/download-agent/scripts/windows.ts @@ -27,45 +27,16 @@ set "HAS_ERROR=0" set "ERRORS=" set "EXIT_CODE=0" -REM Capture elevation flag if passed -set "ELEVATED_FLAG=%~1" - -REM Self-elevate if not running as administrator (check High Mandatory Level) +REM Require Administrator (check High Mandatory Level) and exit with instructions if not elevated whoami /groups | find "S-1-16-12288" >nul 2>&1 -if errorlevel 1 if /I not "%ELEVATED_FLAG%"=="elevated" ( +if errorlevel 1 ( color 0E - echo Administrator permission is required. - echo A prompt will appear asking for permission. Please click "Yes". - echo If no prompt appears, right-click this file and select "Run as administrator". + echo This script must be run as Administrator. + echo Please right-click the file and select "Run as administrator". echo. - echo Choose an option: - echo [Y] Try to auto-elevate (recommended) - echo [N] I will re-run manually as Administrator - choice /C YN /N /M "Attempt automatic elevation? (Y/N): " - if errorlevel 2 ( - echo. - echo Please close this window and re-run the script by right-clicking it and selecting "Run as administrator". - echo Press any key to exit. - pause >nul - exit /b - ) else ( - echo Elevating... A new window will open and remain open after running. - rem Try PowerShell elevation first (keeps admin window open with /k) - powershell -NoProfile -ExecutionPolicy Bypass -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/k','\"%~f0 elevated\"' -WorkingDirectory '%~dp0'" 2>nul - rem Fallback to VBScript if PowerShell attempt failed or is blocked - if not exist "%TEMP%\elevate.tmp" ( - > "%TEMP%\getadmin.vbs" echo Set UAC = CreateObject^("Shell.Application"^) - >> "%TEMP%\getadmin.vbs" echo UAC.ShellExecute "%~f0", "elevated", "", "runas", 1 - wscript "%TEMP%\getadmin.vbs" >nul 2>&1 - del "%TEMP%\getadmin.vbs" >nul 2>&1 - ) - echo. - echo This window will now stay open so you can see messages. - echo Once the new admin window appears, you may close this one after confirming progress. - echo Press any key to exit this non-admin window. - pause >nul - exit /b - ) + echo Press any key to exit, then try again with Administrator privileges. + pause + exit /b 5 ) echo Running with administrator privileges. echo Current directory: %cd% From bfad924a7ecf8149f978c4545524c98a93a77573 Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 14:27:36 -0400 Subject: [PATCH 11/23] fix: add persistent cmd session support in Windows script - Implemented a mechanism to relaunch the script in a persistent command window if not already running in one. - Enhanced user experience by ensuring the command window remains open after script completion for better visibility of output and errors. --- apps/portal/src/app/api/download-agent/scripts/windows.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/portal/src/app/api/download-agent/scripts/windows.ts b/apps/portal/src/app/api/download-agent/scripts/windows.ts index fa8e5a5fe..fb3f0fa39 100644 --- a/apps/portal/src/app/api/download-agent/scripts/windows.ts +++ b/apps/portal/src/app/api/download-agent/scripts/windows.ts @@ -38,6 +38,14 @@ if errorlevel 1 ( pause exit /b 5 ) + +REM Ensure this script runs in a persistent cmd session that stays open after completion +if not "%PERSIST%"=="1" ( + set "PERSIST=1" + echo Re-launching in a persistent window... + start "CompAI Device Setup" cmd /k "%~f0 %*" + exit /b +) echo Running with administrator privileges. echo Current directory: %cd% echo Script path: %~f0 From b2da0741cf3148966bc5800f335023f8af43a3b9 Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 14:39:42 -0400 Subject: [PATCH 12/23] fix: improve directory selection logic in Windows script - Enhanced the script to ensure the primary directory is created if it does not exist before attempting to set it as the chosen directory. - Added fallback logic to create and select the fallback directory if the primary directory is unavailable, improving robustness in directory handling. --- .../src/app/api/download-agent/scripts/windows.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/portal/src/app/api/download-agent/scripts/windows.ts b/apps/portal/src/app/api/download-agent/scripts/windows.ts index fb3f0fa39..f061f95b3 100644 --- a/apps/portal/src/app/api/download-agent/scripts/windows.ts +++ b/apps/portal/src/app/api/download-agent/scripts/windows.ts @@ -54,13 +54,16 @@ echo. REM Choose a writable directory (primary first, then fallback) echo Choosing destination directory... echo Trying primary: %PRIMARY_DIR% -for %%D in ("%PRIMARY_DIR%" "%FALLBACK_DIR%") do ( - if not defined CHOSEN_DIR ( - mkdir "%%~D" >nul 2>&1 - if exist "%%~D" ( - set "CHOSEN_DIR=%%~D" - ) +if not exist "%PRIMARY_DIR%" ( + mkdir "%PRIMARY_DIR%" >nul 2>&1 +) +if exist "%PRIMARY_DIR%" set "CHOSEN_DIR=%PRIMARY_DIR%" +if not defined CHOSEN_DIR ( + echo Trying fallback: %FALLBACK_DIR% + if not exist "%FALLBACK_DIR%" ( + mkdir "%FALLBACK_DIR%" >nul 2>&1 ) + if exist "%FALLBACK_DIR%" set "CHOSEN_DIR=%FALLBACK_DIR%" ) if not defined CHOSEN_DIR ( From bfbfca0466d37452bc3aa70116d4eb96adeaa03c Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 14:59:10 -0400 Subject: [PATCH 13/23] fix: refine directory creation logic in Windows script - Updated the script to use 'md' for directory creation and improved error handling by logging warnings if directory creation fails. - Ensured that directory checks include a trailing backslash for more reliable path validation. --- .../src/app/api/download-agent/scripts/windows.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/portal/src/app/api/download-agent/scripts/windows.ts b/apps/portal/src/app/api/download-agent/scripts/windows.ts index f061f95b3..c26cd08fa 100644 --- a/apps/portal/src/app/api/download-agent/scripts/windows.ts +++ b/apps/portal/src/app/api/download-agent/scripts/windows.ts @@ -54,16 +54,16 @@ echo. REM Choose a writable directory (primary first, then fallback) echo Choosing destination directory... echo Trying primary: %PRIMARY_DIR% -if not exist "%PRIMARY_DIR%" ( - mkdir "%PRIMARY_DIR%" >nul 2>&1 +if not exist "%PRIMARY_DIR%\" ( + md "%PRIMARY_DIR%" 2>nul || echo [WARN] mkdir failed for "%PRIMARY_DIR%" ) -if exist "%PRIMARY_DIR%" set "CHOSEN_DIR=%PRIMARY_DIR%" +if exist "%PRIMARY_DIR%\" set "CHOSEN_DIR=%PRIMARY_DIR%" if not defined CHOSEN_DIR ( echo Trying fallback: %FALLBACK_DIR% - if not exist "%FALLBACK_DIR%" ( - mkdir "%FALLBACK_DIR%" >nul 2>&1 + if not exist "%FALLBACK_DIR%\" ( + md "%FALLBACK_DIR%" 2>nul || echo [WARN] mkdir failed for "%FALLBACK_DIR%" ) - if exist "%FALLBACK_DIR%" set "CHOSEN_DIR=%FALLBACK_DIR%" + if exist "%FALLBACK_DIR%\" set "CHOSEN_DIR=%FALLBACK_DIR%" ) if not defined CHOSEN_DIR ( From 71858ec19bcbce3b8e624e84d71a9420e62b668c Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 15:10:24 -0400 Subject: [PATCH 14/23] fix: improve directory creation logic in Windows script - Updated the script to switch to the script's directory before creating directories, enhancing clarity in the execution context. - Refined directory existence checks to use a more reliable method, ensuring that the primary and fallback directories are created correctly if they do not exist. --- .../src/app/api/download-agent/scripts/windows.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/portal/src/app/api/download-agent/scripts/windows.ts b/apps/portal/src/app/api/download-agent/scripts/windows.ts index c26cd08fa..c4a500b1e 100644 --- a/apps/portal/src/app/api/download-agent/scripts/windows.ts +++ b/apps/portal/src/app/api/download-agent/scripts/windows.ts @@ -49,21 +49,24 @@ if not "%PERSIST%"=="1" ( echo Running with administrator privileges. echo Current directory: %cd% echo Script path: %~f0 +echo Switching working directory to script folder... +cd /d "%~dp0" +echo New current directory: %cd% echo. REM Choose a writable directory (primary first, then fallback) echo Choosing destination directory... echo Trying primary: %PRIMARY_DIR% -if not exist "%PRIMARY_DIR%\" ( - md "%PRIMARY_DIR%" 2>nul || echo [WARN] mkdir failed for "%PRIMARY_DIR%" +if not exist "%PRIMARY_DIR%\NUL" ( + mkdir "%PRIMARY_DIR%" 2>nul ) -if exist "%PRIMARY_DIR%\" set "CHOSEN_DIR=%PRIMARY_DIR%" +if exist "%PRIMARY_DIR%\NUL" set "CHOSEN_DIR=%PRIMARY_DIR%" if not defined CHOSEN_DIR ( echo Trying fallback: %FALLBACK_DIR% - if not exist "%FALLBACK_DIR%\" ( - md "%FALLBACK_DIR%" 2>nul || echo [WARN] mkdir failed for "%FALLBACK_DIR%" + if not exist "%FALLBACK_DIR%\NUL" ( + mkdir "%FALLBACK_DIR%" 2>nul ) - if exist "%FALLBACK_DIR%\" set "CHOSEN_DIR=%FALLBACK_DIR%" + if exist "%FALLBACK_DIR%\NUL" set "CHOSEN_DIR=%FALLBACK_DIR%" ) if not defined CHOSEN_DIR ( From d48ea605084f4a4de1d45c59fb9e384167dda0d3 Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 15:37:51 -0400 Subject: [PATCH 15/23] fix: update registry path formatting in Windows script - Corrected the registry path formatting by replacing single backslashes with double backslashes for consistency and to prevent potential parsing issues. - Ensured that the fallback directory path is explicitly defined to improve clarity and reliability in the script's execution. --- .../app/api/download-agent/scripts/windows.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/apps/portal/src/app/api/download-agent/scripts/windows.ts b/apps/portal/src/app/api/download-agent/scripts/windows.ts index c4a500b1e..52e365cc0 100644 --- a/apps/portal/src/app/api/download-agent/scripts/windows.ts +++ b/apps/portal/src/app/api/download-agent/scripts/windows.ts @@ -20,7 +20,7 @@ REM Variables set "ORG_ID=${orgId}" set "EMPLOYEE_ID=${employeeId}" set "PRIMARY_DIR=${fleetDevicePath}" -set "FALLBACK_DIR=%PUBLIC%\CompAI\Fleet" +set "FALLBACK_DIR=C:\\Users\\Public\\CompAI\\Fleet" set "CHOSEN_DIR=" set "LOG_FILE=" set "HAS_ERROR=0" @@ -127,9 +127,9 @@ if defined CHOSEN_DIR ( echo. echo Writing registry entries (HKLM preferred)... -reg add "HKLM\SOFTWARE\CompAI\Device" /f >nul 2>&1 +reg add "HKLM\\SOFTWARE\\CompAI\\Device" /f >nul 2>&1 if %errorlevel%==0 ( - reg add "HKLM\SOFTWARE\CompAI\Device" /v OrgId /t REG_SZ /d "%ORG_ID" /f >nul 2>&1 + reg add "HKLM\\SOFTWARE\\CompAI\\Device" /v OrgId /t REG_SZ /d "%ORG_ID" /f >nul 2>&1 if errorlevel 1 ( color 0E echo WARNING: Failed writing OrgId to HKLM. @@ -138,7 +138,7 @@ if %errorlevel%==0 ( set "ERRORS=!ERRORS!- Failed writing OrgId to HKLM registry.!nl!" set "EXIT_CODE=1" ) - reg add "HKLM\SOFTWARE\CompAI\Device" /v EmployeeId /t REG_SZ /d "%EMPLOYEE_ID%" /f >nul 2>&1 + reg add "HKLM\\SOFTWARE\\CompAI\\Device" /v EmployeeId /t REG_SZ /d "%EMPLOYEE_ID%" /f >nul 2>&1 if errorlevel 1 ( color 0E echo WARNING: Failed writing EmployeeId to HKLM. @@ -151,8 +151,8 @@ if %errorlevel%==0 ( color 0E echo Could not write to HKLM (system-wide). Falling back to current user registry (HKCU). echo [%date% %time%] No admin registry access (HKLM). Falling back to HKCU. >> "%LOG_FILE%" - reg add "HKCU\Software\CompAI\Device" /f >nul 2>&1 - reg add "HKCU\Software\CompAI\Device" /v OrgId /t REG_SZ /d "%ORG_ID%" /f >nul 2>&1 + reg add "HKCU\\Software\\CompAI\\Device" /f >nul 2>&1 + reg add "HKCU\\Software\\CompAI\\Device" /v OrgId /t REG_SZ /d "%ORG_ID%" /f >nul 2>&1 if errorlevel 1 ( color 0E echo WARNING: Failed writing OrgId to HKCU. @@ -161,7 +161,7 @@ if %errorlevel%==0 ( set "ERRORS=!ERRORS!- Failed writing OrgId to HKCU registry.!nl!" set "EXIT_CODE=1" ) - reg add "HKCU\Software\CompAI\Device" /v EmployeeId /t REG_SZ /d "%EMPLOYEE_ID%" /f >nul 2>&1 + reg add "HKCU\\Software\\CompAI\\Device" /v EmployeeId /t REG_SZ /d "%EMPLOYEE_ID%" /f >nul 2>&1 if errorlevel 1 ( color 0E echo WARNING: Failed writing EmployeeId to HKCU. @@ -186,8 +186,8 @@ if defined CHOSEN_DIR ( echo [OK] Employee marker file present. ) ) -reg query "HKLM\SOFTWARE\CompAI\Device" /v EmployeeId | find "%EMPLOYEE_ID%" >nul 2>&1 -if errorlevel 1 reg query "HKCU\Software\CompAI\Device" /v EmployeeId | find "%EMPLOYEE_ID%" >nul 2>&1 +reg query "HKLM\\SOFTWARE\\CompAI\\Device" /v EmployeeId | find "%EMPLOYEE_ID%" >nul 2>&1 +if errorlevel 1 reg query "HKCU\\Software\\CompAI\\Device" /v EmployeeId | find "%EMPLOYEE_ID%" >nul 2>&1 if errorlevel 1 ( color 0E echo WARNING: Registry check failed: EmployeeId not found or mismatched in HKLM/HKCU. From 49e3ec4f51bdee8647aa3c1684abcef041d376df Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 15:49:55 -0400 Subject: [PATCH 16/23] fix: enhance directory and marker file handling in Windows script - Improved the logic for selecting and creating primary and fallback directories, adding detailed logging for success and failure scenarios. - Updated marker file writing commands to include explicit logging messages, enhancing clarity during execution. - Removed outdated registry writing logic as per request, streamlining the script's functionality. --- .../app/api/download-agent/scripts/windows.ts | 96 ++++++------------- 1 file changed, 29 insertions(+), 67 deletions(-) diff --git a/apps/portal/src/app/api/download-agent/scripts/windows.ts b/apps/portal/src/app/api/download-agent/scripts/windows.ts index 52e365cc0..fb39efa52 100644 --- a/apps/portal/src/app/api/download-agent/scripts/windows.ts +++ b/apps/portal/src/app/api/download-agent/scripts/windows.ts @@ -57,16 +57,34 @@ echo. REM Choose a writable directory (primary first, then fallback) echo Choosing destination directory... echo Trying primary: %PRIMARY_DIR% -if not exist "%PRIMARY_DIR%\NUL" ( - mkdir "%PRIMARY_DIR%" 2>nul +if exist "%PRIMARY_DIR%\NUL" ( + echo [OK] Primary exists: "%PRIMARY_DIR%" + set "CHOSEN_DIR=%PRIMARY_DIR%" +) else ( + echo CMD: mkdir "%PRIMARY_DIR%" + mkdir "%PRIMARY_DIR%" 2>&1 + if exist "%PRIMARY_DIR%\NUL" ( + echo [OK] Created primary: "%PRIMARY_DIR%" + set "CHOSEN_DIR=%PRIMARY_DIR%" + ) else ( + echo [WARN] Could not create primary (errorlevel=%errorlevel%): "%PRIMARY_DIR%" + ) ) -if exist "%PRIMARY_DIR%\NUL" set "CHOSEN_DIR=%PRIMARY_DIR%" if not defined CHOSEN_DIR ( echo Trying fallback: %FALLBACK_DIR% - if not exist "%FALLBACK_DIR%\NUL" ( - mkdir "%FALLBACK_DIR%" 2>nul + if exist "%FALLBACK_DIR%\NUL" ( + echo [OK] Fallback exists: "%FALLBACK_DIR%" + set "CHOSEN_DIR=%FALLBACK_DIR%" + ) else ( + echo CMD: mkdir "%FALLBACK_DIR%" + mkdir "%FALLBACK_DIR%" 2>&1 + if exist "%FALLBACK_DIR%\NUL" ( + echo [OK] Created fallback: "%FALLBACK_DIR%" + set "CHOSEN_DIR=%FALLBACK_DIR%" + ) else ( + echo [WARN] Could not create fallback (errorlevel=%errorlevel%): "%FALLBACK_DIR%" + ) ) - if exist "%FALLBACK_DIR%\NUL" set "CHOSEN_DIR=%FALLBACK_DIR%" ) if not defined CHOSEN_DIR ( @@ -91,7 +109,8 @@ echo. REM Write marker files if defined CHOSEN_DIR ( echo Writing organization marker file... - > "%MARKER_DIR%%ORG_ID%" (echo %ORG_ID%) 2>>"%LOG_FILE%" + echo CMD: write org marker to "%MARKER_DIR%%ORG_ID%" + echo %ORG_ID% > "%MARKER_DIR%%ORG_ID%" 2>>"%LOG_FILE%" if errorlevel 1 ( color 0E echo WARNING: Failed writing organization marker file to %MARKER_DIR%. @@ -104,7 +123,8 @@ if defined CHOSEN_DIR ( ) echo Writing employee marker file... - > "%MARKER_DIR%%EMPLOYEE_ID%" (echo %EMPLOYEE_ID%) 2>>"%LOG_FILE%" + echo CMD: write employee marker to "%MARKER_DIR%%EMPLOYEE_ID%" + echo %EMPLOYEE_ID% > "%MARKER_DIR%%EMPLOYEE_ID%" 2>>"%LOG_FILE%" if errorlevel 1 ( color 0E echo WARNING: Failed writing employee marker file to %MARKER_DIR%. @@ -125,53 +145,6 @@ if defined CHOSEN_DIR ( icacls "%MARKER_DIR%%EMPLOYEE_ID%" /grant *S-1-5-18:R *S-1-5-32-544:R /T >nul 2>&1 ) -echo. -echo Writing registry entries (HKLM preferred)... -reg add "HKLM\\SOFTWARE\\CompAI\\Device" /f >nul 2>&1 -if %errorlevel%==0 ( - reg add "HKLM\\SOFTWARE\\CompAI\\Device" /v OrgId /t REG_SZ /d "%ORG_ID" /f >nul 2>&1 - if errorlevel 1 ( - color 0E - echo WARNING: Failed writing OrgId to HKLM. - echo [%date% %time%] Failed writing OrgId to HKLM >> "%LOG_FILE%" - set "HAS_ERROR=1" - set "ERRORS=!ERRORS!- Failed writing OrgId to HKLM registry.!nl!" - set "EXIT_CODE=1" - ) - reg add "HKLM\\SOFTWARE\\CompAI\\Device" /v EmployeeId /t REG_SZ /d "%EMPLOYEE_ID%" /f >nul 2>&1 - if errorlevel 1 ( - color 0E - echo WARNING: Failed writing EmployeeId to HKLM. - echo [%date% %time%] Failed writing EmployeeId to HKLM >> "%LOG_FILE%" - set "HAS_ERROR=1" - set "ERRORS=!ERRORS!- Failed writing EmployeeId to HKLM registry.!nl!" - set "EXIT_CODE=1" - ) -) else ( - color 0E - echo Could not write to HKLM (system-wide). Falling back to current user registry (HKCU). - echo [%date% %time%] No admin registry access (HKLM). Falling back to HKCU. >> "%LOG_FILE%" - reg add "HKCU\\Software\\CompAI\\Device" /f >nul 2>&1 - reg add "HKCU\\Software\\CompAI\\Device" /v OrgId /t REG_SZ /d "%ORG_ID%" /f >nul 2>&1 - if errorlevel 1 ( - color 0E - echo WARNING: Failed writing OrgId to HKCU. - echo [%date% %time%] Failed writing OrgId to HKCU >> "%LOG_FILE%" - set "HAS_ERROR=1" - set "ERRORS=!ERRORS!- Failed writing OrgId to HKCU registry.!nl!" - set "EXIT_CODE=1" - ) - reg add "HKCU\\Software\\CompAI\\Device" /v EmployeeId /t REG_SZ /d "%EMPLOYEE_ID%" /f >nul 2>&1 - if errorlevel 1 ( - color 0E - echo WARNING: Failed writing EmployeeId to HKCU. - echo [%date% %time%] Failed writing EmployeeId to HKCU >> "%LOG_FILE%" - set "HAS_ERROR=1" - set "ERRORS=!ERRORS!- Failed writing EmployeeId to HKCU registry.!nl!" - set "EXIT_CODE=1" - ) -) - echo. echo Verifying markers... if defined CHOSEN_DIR ( @@ -186,18 +159,7 @@ if defined CHOSEN_DIR ( echo [OK] Employee marker file present. ) ) -reg query "HKLM\\SOFTWARE\\CompAI\\Device" /v EmployeeId | find "%EMPLOYEE_ID%" >nul 2>&1 -if errorlevel 1 reg query "HKCU\\Software\\CompAI\\Device" /v EmployeeId | find "%EMPLOYEE_ID%" >nul 2>&1 -if errorlevel 1 ( - color 0E - echo WARNING: Registry check failed: EmployeeId not found or mismatched in HKLM/HKCU. - echo [%date% %time%] Warning: registry EmployeeId value not found or mismatched >> "%LOG_FILE%" - set "HAS_ERROR=1" - set "ERRORS=!ERRORS!- Registry EmployeeId not found or mismatched in HKLM/HKCU.!nl!" - set "EXIT_CODE=2" -) else ( - echo [OK] Registry value found for EmployeeId. -) +rem Skipping registry checks per request echo. echo ------------------------------------------------------------ From 3982150f3ea620097a535d80c7c315b3d7df76c3 Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 16:12:29 -0400 Subject: [PATCH 17/23] fix: refine directory handling and logging in Windows script - Updated the script to improve the logic for selecting and creating primary and fallback directories, ensuring clearer execution flow. - Enhanced logging for directory creation attempts and outcomes, providing better visibility into the script's operations. - Adjusted marker file writing commands to improve error handling and logging clarity. --- .../app/api/download-agent/scripts/windows.ts | 52 ++++++------------- 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/apps/portal/src/app/api/download-agent/scripts/windows.ts b/apps/portal/src/app/api/download-agent/scripts/windows.ts index fb39efa52..1459c34c1 100644 --- a/apps/portal/src/app/api/download-agent/scripts/windows.ts +++ b/apps/portal/src/app/api/download-agent/scripts/windows.ts @@ -5,7 +5,7 @@ export function generateWindowsScript(config: ScriptConfig): string { const script = `@echo off title CompAI Device Setup -setlocal EnableExtensions EnableDelayedExpansion +setlocal EnableExtensions DisableDelayedExpansion color 0A echo ------------------------------------------------------------ @@ -54,44 +54,24 @@ cd /d "%~dp0" echo New current directory: %cd% echo. -REM Choose a writable directory (primary first, then fallback) +REM Choose a writable directory (primary first, then fallback) without parentheses blocks echo Choosing destination directory... -echo Trying primary: %PRIMARY_DIR% -if exist "%PRIMARY_DIR%\NUL" ( - echo [OK] Primary exists: "%PRIMARY_DIR%" - set "CHOSEN_DIR=%PRIMARY_DIR%" -) else ( - echo CMD: mkdir "%PRIMARY_DIR%" - mkdir "%PRIMARY_DIR%" 2>&1 - if exist "%PRIMARY_DIR%\NUL" ( - echo [OK] Created primary: "%PRIMARY_DIR%" - set "CHOSEN_DIR=%PRIMARY_DIR%" - ) else ( - echo [WARN] Could not create primary (errorlevel=%errorlevel%): "%PRIMARY_DIR%" - ) -) -if not defined CHOSEN_DIR ( - echo Trying fallback: %FALLBACK_DIR% - if exist "%FALLBACK_DIR%\NUL" ( - echo [OK] Fallback exists: "%FALLBACK_DIR%" - set "CHOSEN_DIR=%FALLBACK_DIR%" - ) else ( - echo CMD: mkdir "%FALLBACK_DIR%" - mkdir "%FALLBACK_DIR%" 2>&1 - if exist "%FALLBACK_DIR%\NUL" ( - echo [OK] Created fallback: "%FALLBACK_DIR%" - set "CHOSEN_DIR=%FALLBACK_DIR%" - ) else ( - echo [WARN] Could not create fallback (errorlevel=%errorlevel%): "%FALLBACK_DIR%" - ) - ) -) +echo Primary: "%PRIMARY_DIR%" +if exist "%PRIMARY_DIR%\" set "CHOSEN_DIR=%PRIMARY_DIR%" +if not defined CHOSEN_DIR echo CMD: mkdir "%PRIMARY_DIR%" +if not defined CHOSEN_DIR mkdir "%PRIMARY_DIR%" 2>&1 +if not defined CHOSEN_DIR if exist "%PRIMARY_DIR%\" set "CHOSEN_DIR=%PRIMARY_DIR%" +if not defined CHOSEN_DIR echo Fallback: "%FALLBACK_DIR%" +if not defined CHOSEN_DIR if exist "%FALLBACK_DIR%\" set "CHOSEN_DIR=%FALLBACK_DIR%" +if not defined CHOSEN_DIR echo CMD: mkdir "%FALLBACK_DIR%" +if not defined CHOSEN_DIR mkdir "%FALLBACK_DIR%" 2>&1 +if not defined CHOSEN_DIR if exist "%FALLBACK_DIR%\" set "CHOSEN_DIR=%FALLBACK_DIR%" if not defined CHOSEN_DIR ( color 0E echo WARNING: No writable directory found. - echo Primary attempted: %PRIMARY_DIR% - echo Fallback attempted: %FALLBACK_DIR% + echo Primary attempted: "%PRIMARY_DIR%" + echo Fallback attempted: "%FALLBACK_DIR%" echo [%date% %time%] No writable directory found. Primary: %PRIMARY_DIR%, Fallback: %FALLBACK_DIR% >> "%~dp0setup.log" set "LOG_FILE=%~dp0setup.log" set "HAS_ERROR=1" @@ -110,7 +90,7 @@ REM Write marker files if defined CHOSEN_DIR ( echo Writing organization marker file... echo CMD: write org marker to "%MARKER_DIR%%ORG_ID%" - echo %ORG_ID% > "%MARKER_DIR%%ORG_ID%" 2>>"%LOG_FILE%" + (echo %ORG_ID%) ^> "%MARKER_DIR%%ORG_ID%" 2^>^>"%LOG_FILE%" if errorlevel 1 ( color 0E echo WARNING: Failed writing organization marker file to %MARKER_DIR%. @@ -124,7 +104,7 @@ if defined CHOSEN_DIR ( echo Writing employee marker file... echo CMD: write employee marker to "%MARKER_DIR%%EMPLOYEE_ID%" - echo %EMPLOYEE_ID% > "%MARKER_DIR%%EMPLOYEE_ID%" 2>>"%LOG_FILE%" + (echo %EMPLOYEE_ID%) ^> "%MARKER_DIR%%EMPLOYEE_ID%" 2^>^>"%LOG_FILE%" if errorlevel 1 ( color 0E echo WARNING: Failed writing employee marker file to %MARKER_DIR%. From 042db43cd4e45087aaa1e881c4ca59d88947050f Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 16:26:31 -0400 Subject: [PATCH 18/23] fix: improve variable handling and logging in Windows script - Updated the script to enable delayed expansion for better variable management during execution. - Refined directory existence checks to use NUL for more reliable validation. - Enhanced logging for marker file writing to ensure errors are captured correctly, improving overall script robustness. --- .../app/api/download-agent/scripts/windows.ts | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/apps/portal/src/app/api/download-agent/scripts/windows.ts b/apps/portal/src/app/api/download-agent/scripts/windows.ts index 1459c34c1..6b530d16c 100644 --- a/apps/portal/src/app/api/download-agent/scripts/windows.ts +++ b/apps/portal/src/app/api/download-agent/scripts/windows.ts @@ -5,7 +5,7 @@ export function generateWindowsScript(config: ScriptConfig): string { const script = `@echo off title CompAI Device Setup -setlocal EnableExtensions DisableDelayedExpansion +setlocal EnableExtensions EnableDelayedExpansion color 0A echo ------------------------------------------------------------ @@ -26,6 +26,7 @@ set "LOG_FILE=" set "HAS_ERROR=0" set "ERRORS=" set "EXIT_CODE=0" +set "nl=^ REM Require Administrator (check High Mandatory Level) and exit with instructions if not elevated whoami /groups | find "S-1-16-12288" >nul 2>&1 @@ -57,15 +58,15 @@ echo. REM Choose a writable directory (primary first, then fallback) without parentheses blocks echo Choosing destination directory... echo Primary: "%PRIMARY_DIR%" -if exist "%PRIMARY_DIR%\" set "CHOSEN_DIR=%PRIMARY_DIR%" +if exist "%PRIMARY_DIR%\NUL" set "CHOSEN_DIR=%PRIMARY_DIR%" if not defined CHOSEN_DIR echo CMD: mkdir "%PRIMARY_DIR%" if not defined CHOSEN_DIR mkdir "%PRIMARY_DIR%" 2>&1 -if not defined CHOSEN_DIR if exist "%PRIMARY_DIR%\" set "CHOSEN_DIR=%PRIMARY_DIR%" +if not defined CHOSEN_DIR if exist "%PRIMARY_DIR%\NUL" set "CHOSEN_DIR=%PRIMARY_DIR%" if not defined CHOSEN_DIR echo Fallback: "%FALLBACK_DIR%" -if not defined CHOSEN_DIR if exist "%FALLBACK_DIR%\" set "CHOSEN_DIR=%FALLBACK_DIR%" +if not defined CHOSEN_DIR if exist "%FALLBACK_DIR%\NUL" set "CHOSEN_DIR=%FALLBACK_DIR%" if not defined CHOSEN_DIR echo CMD: mkdir "%FALLBACK_DIR%" if not defined CHOSEN_DIR mkdir "%FALLBACK_DIR%" 2>&1 -if not defined CHOSEN_DIR if exist "%FALLBACK_DIR%\" set "CHOSEN_DIR=%FALLBACK_DIR%" +if not defined CHOSEN_DIR if exist "%FALLBACK_DIR%\NUL" set "CHOSEN_DIR=%FALLBACK_DIR%" if not defined CHOSEN_DIR ( color 0E @@ -79,9 +80,9 @@ if not defined CHOSEN_DIR ( set "EXIT_CODE=1" ) else ( set "MARKER_DIR=%CHOSEN_DIR%" - if not "%MARKER_DIR:~-1%"=="\\" set "MARKER_DIR=%MARKER_DIR%\\" - set "LOG_FILE=%MARKER_DIR%setup.log" - echo Using directory: %MARKER_DIR% + if not "!MARKER_DIR:~-1!"=="\\" set "MARKER_DIR=!MARKER_DIR!\\" + set "LOG_FILE=!MARKER_DIR!setup.log" + echo Using directory: !MARKER_DIR! ) echo Logs will be written to: %LOG_FILE% echo. @@ -90,7 +91,7 @@ REM Write marker files if defined CHOSEN_DIR ( echo Writing organization marker file... echo CMD: write org marker to "%MARKER_DIR%%ORG_ID%" - (echo %ORG_ID%) ^> "%MARKER_DIR%%ORG_ID%" 2^>^>"%LOG_FILE%" + (echo %ORG_ID%) > "%MARKER_DIR%%ORG_ID%" 2>>"%LOG_FILE%" if errorlevel 1 ( color 0E echo WARNING: Failed writing organization marker file to %MARKER_DIR%. @@ -104,7 +105,7 @@ if defined CHOSEN_DIR ( echo Writing employee marker file... echo CMD: write employee marker to "%MARKER_DIR%%EMPLOYEE_ID%" - (echo %EMPLOYEE_ID%) ^> "%MARKER_DIR%%EMPLOYEE_ID%" 2^>^>"%LOG_FILE%" + (echo %EMPLOYEE_ID%) > "%MARKER_DIR%%EMPLOYEE_ID%" 2>>"%LOG_FILE%" if errorlevel 1 ( color 0E echo WARNING: Failed writing employee marker file to %MARKER_DIR%. @@ -120,23 +121,23 @@ if defined CHOSEN_DIR ( REM Set permissive read ACLs for SYSTEM and Administrators if defined CHOSEN_DIR ( echo Setting permissions on marker files... - icacls "%MARKER_DIR%" /inheritance:e >nul 2>&1 - icacls "%MARKER_DIR%%ORG_ID%" /grant *S-1-5-18:R *S-1-5-32-544:R /T >nul 2>&1 - icacls "%MARKER_DIR%%EMPLOYEE_ID%" /grant *S-1-5-18:R *S-1-5-32-544:R /T >nul 2>&1 + icacls "!MARKER_DIR!" /inheritance:e >nul 2>&1 + icacls "!MARKER_DIR!!ORG_ID!" /grant *S-1-5-18:R *S-1-5-32-544:R >nul 2>&1 + icacls "!MARKER_DIR!!EMPLOYEE_ID!" /grant *S-1-5-18:R *S-1-5-32-544:R >nul 2>&1 ) echo. echo Verifying markers... if defined CHOSEN_DIR ( - if not exist "%MARKER_DIR%%EMPLOYEE_ID%" ( + if not exist "!MARKER_DIR!!EMPLOYEE_ID!" ( color 0E - echo WARNING: Employee marker file missing at %MARKER_DIR%%EMPLOYEE_ID% - echo [%date% %time%] Verification failed: employee marker file missing >> "%LOG_FILE%" + echo WARNING: Employee marker file missing at !MARKER_DIR!!EMPLOYEE_ID! + echo [%date% %time%] Verification failed: employee marker file missing >> "!LOG_FILE!" set "HAS_ERROR=1" - set "ERRORS=!ERRORS!- Employee marker file missing at %MARKER_DIR%%EMPLOYEE_ID%.!nl!" + set "ERRORS=!ERRORS!- Employee marker file missing at !MARKER_DIR!!EMPLOYEE_ID!!.!nl!" set "EXIT_CODE=2" ) else ( - echo [OK] Employee marker file present. + echo [OK] Employee marker file present: !MARKER_DIR!!EMPLOYEE_ID! ) ) rem Skipping registry checks per request From 9c54eb09fba40a63b4d5a641526f7cd4292f61e3 Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 16:29:25 -0400 Subject: [PATCH 19/23] fix: enhance logging and error handling in Windows script - Introduced a logging mechanism to capture messages and command executions, improving visibility during script execution. - Updated directory handling to switch log files based on the chosen directory, ensuring logs are correctly maintained. - Enhanced error reporting for marker file writing and permission setting, providing clearer feedback on issues encountered during execution. --- .../app/api/download-agent/scripts/windows.ts | 101 ++++++++++++------ 1 file changed, 70 insertions(+), 31 deletions(-) diff --git a/apps/portal/src/app/api/download-agent/scripts/windows.ts b/apps/portal/src/app/api/download-agent/scripts/windows.ts index 6b530d16c..44c0e5327 100644 --- a/apps/portal/src/app/api/download-agent/scripts/windows.ts +++ b/apps/portal/src/app/api/download-agent/scripts/windows.ts @@ -27,6 +27,33 @@ set "HAS_ERROR=0" set "ERRORS=" set "EXIT_CODE=0" set "nl=^ +" + +REM --- bootstrap log (updated once CHOSEN_DIR is known) --- +set "LOG_FILE=%~dp0setup.log" + +REM --- log a message to console and log --- +:log_msg +setlocal EnableDelayedExpansion +set "msg=%~1" +echo [%date% %time%] !msg! +>>"%LOG_FILE%" echo [%date% %time%] !msg! +endlocal & exit /b 0 + +REM --- run a command with logging and error capture --- +:log_run +setlocal EnableDelayedExpansion +set "cmdline=%*" +echo [%date% %time%] CMD: !cmdline! +>>"%LOG_FILE%" echo [%date% %time%] CMD: !cmdline! +%* +set "rc=!errorlevel!" +if not "!rc!"=="0" ( + echo [%date% %time%] ERR !rc!: !cmdline! + >>"%LOG_FILE%" echo [%date% %time%] ERR !rc!: !cmdline! +) +endlocal & set "LAST_RC=%rc%" +exit /b %LAST_RC% REM Require Administrator (check High Mandatory Level) and exit with instructions if not elevated whoami /groups | find "S-1-16-12288" >nul 2>&1 @@ -43,29 +70,27 @@ if errorlevel 1 ( REM Ensure this script runs in a persistent cmd session that stays open after completion if not "%PERSIST%"=="1" ( set "PERSIST=1" - echo Re-launching in a persistent window... + call :log_msg "Re-launching in a persistent window" start "CompAI Device Setup" cmd /k "%~f0 %*" exit /b ) -echo Running with administrator privileges. -echo Current directory: %cd% -echo Script path: %~f0 -echo Switching working directory to script folder... +call :log_msg "Running with administrator privileges" +call :log_msg "Current directory: %cd%" +call :log_msg "Script path: %~f0" +call :log_msg "Switching working directory to script folder" cd /d "%~dp0" -echo New current directory: %cd% +call :log_msg "New current directory: %cd%" echo. REM Choose a writable directory (primary first, then fallback) without parentheses blocks -echo Choosing destination directory... -echo Primary: "%PRIMARY_DIR%" +call :log_msg "Choosing destination directory; primary=%PRIMARY_DIR% fallback=%FALLBACK_DIR%" if exist "%PRIMARY_DIR%\NUL" set "CHOSEN_DIR=%PRIMARY_DIR%" -if not defined CHOSEN_DIR echo CMD: mkdir "%PRIMARY_DIR%" -if not defined CHOSEN_DIR mkdir "%PRIMARY_DIR%" 2>&1 +if not defined CHOSEN_DIR call :log_run mkdir "%PRIMARY_DIR%" if not defined CHOSEN_DIR if exist "%PRIMARY_DIR%\NUL" set "CHOSEN_DIR=%PRIMARY_DIR%" -if not defined CHOSEN_DIR echo Fallback: "%FALLBACK_DIR%" + +if not defined CHOSEN_DIR call :log_msg "Primary not available; trying fallback" if not defined CHOSEN_DIR if exist "%FALLBACK_DIR%\NUL" set "CHOSEN_DIR=%FALLBACK_DIR%" -if not defined CHOSEN_DIR echo CMD: mkdir "%FALLBACK_DIR%" -if not defined CHOSEN_DIR mkdir "%FALLBACK_DIR%" 2>&1 +if not defined CHOSEN_DIR call :log_run mkdir "%FALLBACK_DIR%" if not defined CHOSEN_DIR if exist "%FALLBACK_DIR%\NUL" set "CHOSEN_DIR=%FALLBACK_DIR%" if not defined CHOSEN_DIR ( @@ -81,54 +106,66 @@ if not defined CHOSEN_DIR ( ) else ( set "MARKER_DIR=%CHOSEN_DIR%" if not "!MARKER_DIR:~-1!"=="\\" set "MARKER_DIR=!MARKER_DIR!\\" - set "LOG_FILE=!MARKER_DIR!setup.log" - echo Using directory: !MARKER_DIR! + + REM switch the log file to the chosen directory, carrying over bootstrap logs + set "FINAL_LOG=!MARKER_DIR!setup.log" + if /i not "%LOG_FILE%"=="%FINAL_LOG%" ( + call :log_msg "Switching log to !FINAL_LOG!" + if exist "%LOG_FILE%" type "%LOG_FILE%" >> "!FINAL_LOG!" & del "%LOG_FILE%" + set "LOG_FILE=!FINAL_LOG!" + ) + call :log_msg "Using directory: !MARKER_DIR!" ) echo Logs will be written to: %LOG_FILE% echo. REM Write marker files if defined CHOSEN_DIR ( - echo Writing organization marker file... - echo CMD: write org marker to "%MARKER_DIR%%ORG_ID%" - (echo %ORG_ID%) > "%MARKER_DIR%%ORG_ID%" 2>>"%LOG_FILE%" + call :log_msg "Writing organization marker file" + call :log_msg "Preparing to write org marker to !MARKER_DIR!!ORG_ID!" + call :log_run cmd /c "(echo %ORG_ID%) > \"!MARKER_DIR!!ORG_ID!\"" if errorlevel 1 ( color 0E - echo WARNING: Failed writing organization marker file to %MARKER_DIR%. + call :log_msg "WARNING: Failed writing organization marker file to !MARKER_DIR!" echo [%date% %time%] Failed writing org marker file >> "%LOG_FILE%" set "HAS_ERROR=1" set "ERRORS=!ERRORS!- Failed writing organization marker file.!nl!" set "EXIT_CODE=1" ) else ( - echo [OK] Organization marker file: %MARKER_DIR%%ORG_ID% + call :log_msg "[OK] Organization marker file: !MARKER_DIR!!ORG_ID!" ) - echo Writing employee marker file... - echo CMD: write employee marker to "%MARKER_DIR%%EMPLOYEE_ID%" - (echo %EMPLOYEE_ID%) > "%MARKER_DIR%%EMPLOYEE_ID%" 2>>"%LOG_FILE%" + call :log_msg "Writing employee marker file" + call :log_msg "Preparing to write employee marker to !MARKER_DIR!!EMPLOYEE_ID!" + call :log_run cmd /c "(echo %EMPLOYEE_ID%) > \"!MARKER_DIR!!EMPLOYEE_ID!\"" if errorlevel 1 ( color 0E - echo WARNING: Failed writing employee marker file to %MARKER_DIR%. + call :log_msg "WARNING: Failed writing employee marker file to !MARKER_DIR!" echo [%date% %time%] Failed writing employee marker file >> "%LOG_FILE%" set "HAS_ERROR=1" set "ERRORS=!ERRORS!- Failed writing employee marker file.!nl!" set "EXIT_CODE=1" ) else ( - echo [OK] Employee marker file: %MARKER_DIR%%EMPLOYEE_ID% + call :log_msg "[OK] Employee marker file: !MARKER_DIR!!EMPLOYEE_ID!" ) ) REM Set permissive read ACLs for SYSTEM and Administrators if defined CHOSEN_DIR ( - echo Setting permissions on marker files... - icacls "!MARKER_DIR!" /inheritance:e >nul 2>&1 - icacls "!MARKER_DIR!!ORG_ID!" /grant *S-1-5-18:R *S-1-5-32-544:R >nul 2>&1 - icacls "!MARKER_DIR!!EMPLOYEE_ID!" /grant *S-1-5-18:R *S-1-5-32-544:R >nul 2>&1 + call :log_msg "Setting permissions on marker directory" + call :log_run icacls "!MARKER_DIR!" /inheritance:e + + call :log_msg "Granting read to SYSTEM and Administrators on org marker" + call :log_run icacls "!MARKER_DIR!!ORG_ID!" /grant *S-1-5-18:R *S-1-5-32-544:R + + call :log_msg "Granting read to SYSTEM and Administrators on employee marker" + call :log_run icacls "!MARKER_DIR!!EMPLOYEE_ID!" /grant *S-1-5-18:R *S-1-5-32-544:R ) echo. echo Verifying markers... if defined CHOSEN_DIR ( + call :log_msg "Verifying marker exists: !MARKER_DIR!!EMPLOYEE_ID!" if not exist "!MARKER_DIR!!EMPLOYEE_ID!" ( color 0E echo WARNING: Employee marker file missing at !MARKER_DIR!!EMPLOYEE_ID! @@ -137,7 +174,7 @@ if defined CHOSEN_DIR ( set "ERRORS=!ERRORS!- Employee marker file missing at !MARKER_DIR!!EMPLOYEE_ID!!.!nl!" set "EXIT_CODE=2" ) else ( - echo [OK] Employee marker file present: !MARKER_DIR!!EMPLOYEE_ID! + call :log_msg "[OK] Employee marker file present: !MARKER_DIR!!EMPLOYEE_ID!" ) ) rem Skipping registry checks per request @@ -150,6 +187,7 @@ if "%HAS_ERROR%"=="0" ( echo Setup completed successfully for %EMPLOYEE_ID%. if defined CHOSEN_DIR echo Files created in: %CHOSEN_DIR% echo Log file: %LOG_FILE% + call :log_msg "RESULT: SUCCESS" ) else ( color 0C echo RESULT: COMPLETED WITH ISSUES @@ -161,6 +199,7 @@ if "%HAS_ERROR%"=="0" ( echo - Take a screenshot of this window. echo - Attach the log file from: %LOG_FILE% echo - Share both with your CompAI support contact. + call :log_msg "RESULT: COMPLETED WITH ISSUES (exit=%EXIT_CODE%)" ) echo ------------------------------------------------------------ echo. @@ -168,5 +207,5 @@ echo Press any key to close this window. This will not affect installation. pause if "%HAS_ERROR%"=="0" (exit /b 0) else (exit /b %EXIT_CODE%)`; - return script.replace(/\n/g, '\r\n'); + return script.replace(/\\n/g, '\r\n'); } From e27a0038e1bcb63cca12411cd3cfac0b6867a05b Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 16:38:14 -0400 Subject: [PATCH 20/23] fix: enhance structure and logging in Windows script - Added structured comments to improve readability and organization of the script. - Enhanced logging messages for better clarity during execution, particularly for directory selection and permission settings. - Improved error handling and messaging for missing marker files, ensuring clearer feedback on script status. --- .../app/api/download-agent/scripts/windows.ts | 46 ++++++++++++++----- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/apps/portal/src/app/api/download-agent/scripts/windows.ts b/apps/portal/src/app/api/download-agent/scripts/windows.ts index 44c0e5327..b30a687bf 100644 --- a/apps/portal/src/app/api/download-agent/scripts/windows.ts +++ b/apps/portal/src/app/api/download-agent/scripts/windows.ts @@ -16,7 +16,9 @@ echo Date: %date% %time% echo ------------------------------------------------------------ echo. +REM ========================= REM Variables +REM ========================= set "ORG_ID=${orgId}" set "EMPLOYEE_ID=${employeeId}" set "PRIMARY_DIR=${fleetDevicePath}" @@ -26,6 +28,7 @@ set "LOG_FILE=" set "HAS_ERROR=0" set "ERRORS=" set "EXIT_CODE=0" +REM newline token (exactly this 2-line shape) set "nl=^ " @@ -55,7 +58,11 @@ if not "!rc!"=="0" ( endlocal & set "LAST_RC=%rc%" exit /b %LAST_RC% -REM Require Administrator (check High Mandatory Level) and exit with instructions if not elevated +call :log_msg "Script starting" + +REM ========================= +REM Admin check +REM ========================= whoami /groups | find "S-1-16-12288" >nul 2>&1 if errorlevel 1 ( color 0E @@ -67,13 +74,16 @@ if errorlevel 1 ( exit /b 5 ) -REM Ensure this script runs in a persistent cmd session that stays open after completion +REM ========================= +REM Relaunch persistent window +REM ========================= if not "%PERSIST%"=="1" ( set "PERSIST=1" call :log_msg "Re-launching in a persistent window" start "CompAI Device Setup" cmd /k "%~f0 %*" exit /b ) + call :log_msg "Running with administrator privileges" call :log_msg "Current directory: %cd%" call :log_msg "Script path: %~f0" @@ -82,20 +92,22 @@ cd /d "%~dp0" call :log_msg "New current directory: %cd%" echo. -REM Choose a writable directory (primary first, then fallback) without parentheses blocks +REM ========================= +REM Choose writable directory +REM ========================= call :log_msg "Choosing destination directory; primary=%PRIMARY_DIR% fallback=%FALLBACK_DIR%" -if exist "%PRIMARY_DIR%\NUL" set "CHOSEN_DIR=%PRIMARY_DIR%" +if exist "%PRIMARY_DIR%\\NUL" set "CHOSEN_DIR=%PRIMARY_DIR%" if not defined CHOSEN_DIR call :log_run mkdir "%PRIMARY_DIR%" -if not defined CHOSEN_DIR if exist "%PRIMARY_DIR%\NUL" set "CHOSEN_DIR=%PRIMARY_DIR%" +if not defined CHOSEN_DIR if exist "%PRIMARY_DIR%\\NUL" set "CHOSEN_DIR=%PRIMARY_DIR%" if not defined CHOSEN_DIR call :log_msg "Primary not available; trying fallback" -if not defined CHOSEN_DIR if exist "%FALLBACK_DIR%\NUL" set "CHOSEN_DIR=%FALLBACK_DIR%" +if not defined CHOSEN_DIR if exist "%FALLBACK_DIR%\\NUL" set "CHOSEN_DIR=%FALLBACK_DIR%" if not defined CHOSEN_DIR call :log_run mkdir "%FALLBACK_DIR%" -if not defined CHOSEN_DIR if exist "%FALLBACK_DIR%\NUL" set "CHOSEN_DIR=%FALLBACK_DIR%" +if not defined CHOSEN_DIR if exist "%FALLBACK_DIR%\\NUL" set "CHOSEN_DIR=%FALLBACK_DIR%" if not defined CHOSEN_DIR ( color 0E - echo WARNING: No writable directory found. + call :log_msg "WARNING: No writable directory found" echo Primary attempted: "%PRIMARY_DIR%" echo Fallback attempted: "%FALLBACK_DIR%" echo [%date% %time%] No writable directory found. Primary: %PRIMARY_DIR%, Fallback: %FALLBACK_DIR% >> "%~dp0setup.log" @@ -107,7 +119,7 @@ if not defined CHOSEN_DIR ( set "MARKER_DIR=%CHOSEN_DIR%" if not "!MARKER_DIR:~-1!"=="\\" set "MARKER_DIR=!MARKER_DIR!\\" - REM switch the log file to the chosen directory, carrying over bootstrap logs + REM switch the log file to the chosen directory, carry over bootstrap logs set "FINAL_LOG=!MARKER_DIR!setup.log" if /i not "%LOG_FILE%"=="%FINAL_LOG%" ( call :log_msg "Switching log to !FINAL_LOG!" @@ -119,7 +131,9 @@ if not defined CHOSEN_DIR ( echo Logs will be written to: %LOG_FILE% echo. +REM ========================= REM Write marker files +REM ========================= if defined CHOSEN_DIR ( call :log_msg "Writing organization marker file" call :log_msg "Preparing to write org marker to !MARKER_DIR!!ORG_ID!" @@ -150,7 +164,9 @@ if defined CHOSEN_DIR ( ) ) -REM Set permissive read ACLs for SYSTEM and Administrators +REM ========================= +REM Permissions +REM ========================= if defined CHOSEN_DIR ( call :log_msg "Setting permissions on marker directory" call :log_run icacls "!MARKER_DIR!" /inheritance:e @@ -162,13 +178,16 @@ if defined CHOSEN_DIR ( call :log_run icacls "!MARKER_DIR!!EMPLOYEE_ID!" /grant *S-1-5-18:R *S-1-5-32-544:R ) +REM ========================= +REM Verify +REM ========================= echo. echo Verifying markers... if defined CHOSEN_DIR ( call :log_msg "Verifying marker exists: !MARKER_DIR!!EMPLOYEE_ID!" if not exist "!MARKER_DIR!!EMPLOYEE_ID!" ( color 0E - echo WARNING: Employee marker file missing at !MARKER_DIR!!EMPLOYEE_ID! + call :log_msg "WARNING: Employee marker file missing at !MARKER_DIR!!EMPLOYEE_ID!" echo [%date% %time%] Verification failed: employee marker file missing >> "!LOG_FILE!" set "HAS_ERROR=1" set "ERRORS=!ERRORS!- Employee marker file missing at !MARKER_DIR!!EMPLOYEE_ID!!.!nl!" @@ -179,6 +198,9 @@ if defined CHOSEN_DIR ( ) rem Skipping registry checks per request +REM ========================= +REM Result / Exit +REM ========================= echo. echo ------------------------------------------------------------ if "%HAS_ERROR%"=="0" ( @@ -207,5 +229,5 @@ echo Press any key to close this window. This will not affect installation. pause if "%HAS_ERROR%"=="0" (exit /b 0) else (exit /b %EXIT_CODE%)`; - return script.replace(/\\n/g, '\r\n'); + return script.replace(/\n/g, '\r\n'); } From e9a5afd978b4c0473bfb5ad803aba61f0eba019f Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 16:44:24 -0400 Subject: [PATCH 21/23] fix: streamline script structure and enhance logging in Windows script - Removed redundant echo statements to improve script clarity and reduce clutter in the output. - Introduced a main subroutine to organize script flow and enhance readability. - Added structured comments to delineate sections of the script, improving maintainability and understanding of the code. --- .../app/api/download-agent/scripts/windows.ts | 39 +++++++------------ 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/apps/portal/src/app/api/download-agent/scripts/windows.ts b/apps/portal/src/app/api/download-agent/scripts/windows.ts index b30a687bf..419e2429d 100644 --- a/apps/portal/src/app/api/download-agent/scripts/windows.ts +++ b/apps/portal/src/app/api/download-agent/scripts/windows.ts @@ -8,14 +8,6 @@ title CompAI Device Setup setlocal EnableExtensions EnableDelayedExpansion color 0A -echo ------------------------------------------------------------ -echo CompAI Device Setup -echo Organization: ${orgId} -echo Employee: ${employeeId} -echo Date: %date% %time% -echo ------------------------------------------------------------ -echo. - REM ========================= REM Variables REM ========================= @@ -35,7 +27,11 @@ set "nl=^ REM --- bootstrap log (updated once CHOSEN_DIR is known) --- set "LOG_FILE=%~dp0setup.log" -REM --- log a message to console and log --- +goto :main + +REM ======================================================= +REM Subroutines (placed AFTER main to avoid early execution) +REM ======================================================= :log_msg setlocal EnableDelayedExpansion set "msg=%~1" @@ -43,7 +39,6 @@ echo [%date% %time%] !msg! >>"%LOG_FILE%" echo [%date% %time%] !msg! endlocal & exit /b 0 -REM --- run a command with logging and error capture --- :log_run setlocal EnableDelayedExpansion set "cmdline=%*" @@ -58,11 +53,13 @@ if not "!rc!"=="0" ( endlocal & set "LAST_RC=%rc%" exit /b %LAST_RC% +REM ========================= +REM Main +REM ========================= +:main call :log_msg "Script starting" -REM ========================= REM Admin check -REM ========================= whoami /groups | find "S-1-16-12288" >nul 2>&1 if errorlevel 1 ( color 0E @@ -74,9 +71,7 @@ if errorlevel 1 ( exit /b 5 ) -REM ========================= REM Relaunch persistent window -REM ========================= if not "%PERSIST%"=="1" ( set "PERSIST=1" call :log_msg "Re-launching in a persistent window" @@ -92,9 +87,7 @@ cd /d "%~dp0" call :log_msg "New current directory: %cd%" echo. -REM ========================= REM Choose writable directory -REM ========================= call :log_msg "Choosing destination directory; primary=%PRIMARY_DIR% fallback=%FALLBACK_DIR%" if exist "%PRIMARY_DIR%\\NUL" set "CHOSEN_DIR=%PRIMARY_DIR%" if not defined CHOSEN_DIR call :log_run mkdir "%PRIMARY_DIR%" @@ -131,9 +124,7 @@ if not defined CHOSEN_DIR ( echo Logs will be written to: %LOG_FILE% echo. -REM ========================= REM Write marker files -REM ========================= if defined CHOSEN_DIR ( call :log_msg "Writing organization marker file" call :log_msg "Preparing to write org marker to !MARKER_DIR!!ORG_ID!" @@ -164,9 +155,7 @@ if defined CHOSEN_DIR ( ) ) -REM ========================= REM Permissions -REM ========================= if defined CHOSEN_DIR ( call :log_msg "Setting permissions on marker directory" call :log_run icacls "!MARKER_DIR!" /inheritance:e @@ -178,9 +167,7 @@ if defined CHOSEN_DIR ( call :log_run icacls "!MARKER_DIR!!EMPLOYEE_ID!" /grant *S-1-5-18:R *S-1-5-32-544:R ) -REM ========================= REM Verify -REM ========================= echo. echo Verifying markers... if defined CHOSEN_DIR ( @@ -198,9 +185,7 @@ if defined CHOSEN_DIR ( ) rem Skipping registry checks per request -REM ========================= REM Result / Exit -REM ========================= echo. echo ------------------------------------------------------------ if "%HAS_ERROR%"=="0" ( @@ -227,7 +212,11 @@ echo ------------------------------------------------------------ echo. echo Press any key to close this window. This will not affect installation. pause -if "%HAS_ERROR%"=="0" (exit /b 0) else (exit /b %EXIT_CODE%)`; +if "%HAS_ERROR%"=="0" (exit /b 0) else (exit /b %EXIT_CODE%) + +REM End of main +goto :eof +`; return script.replace(/\n/g, '\r\n'); } From 37ea28b5a3362a1e678e9d23105cb16a00e715c3 Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 17:00:38 -0400 Subject: [PATCH 22/23] fix: refine directory existence checks and logging in Windows script - Updated directory existence checks to use wildcard matching for improved reliability. - Enhanced logging to utilize delayed variable expansion for clearer output during execution. - Ensured consistent logging of chosen directory and log file paths for better visibility. --- .../app/api/download-agent/scripts/windows.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/portal/src/app/api/download-agent/scripts/windows.ts b/apps/portal/src/app/api/download-agent/scripts/windows.ts index 419e2429d..62183d425 100644 --- a/apps/portal/src/app/api/download-agent/scripts/windows.ts +++ b/apps/portal/src/app/api/download-agent/scripts/windows.ts @@ -89,14 +89,14 @@ echo. REM Choose writable directory call :log_msg "Choosing destination directory; primary=%PRIMARY_DIR% fallback=%FALLBACK_DIR%" -if exist "%PRIMARY_DIR%\\NUL" set "CHOSEN_DIR=%PRIMARY_DIR%" +if exist "%PRIMARY_DIR%\\*" set "CHOSEN_DIR=%PRIMARY_DIR%" if not defined CHOSEN_DIR call :log_run mkdir "%PRIMARY_DIR%" -if not defined CHOSEN_DIR if exist "%PRIMARY_DIR%\\NUL" set "CHOSEN_DIR=%PRIMARY_DIR%" +if not defined CHOSEN_DIR if exist "%PRIMARY_DIR%\\*" set "CHOSEN_DIR=%PRIMARY_DIR%" if not defined CHOSEN_DIR call :log_msg "Primary not available; trying fallback" -if not defined CHOSEN_DIR if exist "%FALLBACK_DIR%\\NUL" set "CHOSEN_DIR=%FALLBACK_DIR%" +if not defined CHOSEN_DIR if exist "%FALLBACK_DIR%\\*" set "CHOSEN_DIR=%FALLBACK_DIR%" if not defined CHOSEN_DIR call :log_run mkdir "%FALLBACK_DIR%" -if not defined CHOSEN_DIR if exist "%FALLBACK_DIR%\\NUL" set "CHOSEN_DIR=%FALLBACK_DIR%" +if not defined CHOSEN_DIR if exist "%FALLBACK_DIR%\\*" set "CHOSEN_DIR=%FALLBACK_DIR%" if not defined CHOSEN_DIR ( color 0E @@ -121,7 +121,7 @@ if not defined CHOSEN_DIR ( ) call :log_msg "Using directory: !MARKER_DIR!" ) -echo Logs will be written to: %LOG_FILE% +echo Logs will be written to: !LOG_FILE! echo. REM Write marker files @@ -192,8 +192,8 @@ if "%HAS_ERROR%"=="0" ( color 0A echo RESULT: SUCCESS echo Setup completed successfully for %EMPLOYEE_ID%. - if defined CHOSEN_DIR echo Files created in: %CHOSEN_DIR% - echo Log file: %LOG_FILE% + if defined CHOSEN_DIR echo Files created in: !CHOSEN_DIR! + echo Log file: !LOG_FILE! call :log_msg "RESULT: SUCCESS" ) else ( color 0C @@ -204,7 +204,7 @@ if "%HAS_ERROR%"=="0" ( echo. echo Next steps: echo - Take a screenshot of this window. - echo - Attach the log file from: %LOG_FILE% + echo - Attach the log file from: !LOG_FILE! echo - Share both with your CompAI support contact. call :log_msg "RESULT: COMPLETED WITH ISSUES (exit=%EXIT_CODE%)" ) From f34610fcfcc46a157d80c36204be40147679da7f Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Wed, 20 Aug 2025 17:26:35 -0400 Subject: [PATCH 23/23] fix: correct Windows path formatting in fleet label creation script - Updated directory paths to use double backslashes for proper formatting in Windows. - Ensured consistency in path definitions to prevent potential parsing issues during execution. --- apps/app/src/jobs/tasks/device/create-fleet-label-for-org.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/app/src/jobs/tasks/device/create-fleet-label-for-org.ts b/apps/app/src/jobs/tasks/device/create-fleet-label-for-org.ts index 7a551303c..73548ef27 100644 --- a/apps/app/src/jobs/tasks/device/create-fleet-label-for-org.ts +++ b/apps/app/src/jobs/tasks/device/create-fleet-label-for-org.ts @@ -30,8 +30,8 @@ export const createFleetLabelForOrg = task({ } const fleetDevicePathMac = '/Users/Shared/.fleet'; - const fleetDevicePathWindows = 'C\\ProgramData\\CompAI\\Fleet'; - const windowsFallbackDir = 'C\\Users\\Public\\CompAI\\Fleet'; + const fleetDevicePathWindows = 'C:\\ProgramData\\CompAI\\Fleet'; + const windowsFallbackDir = 'C:\\Users\\Public\\CompAI\\Fleet'; // Simple union query: only file table, constrained per platform path const query = `