# EnterpriseChat Server - instalador para Windows. # # Uso (PowerShell elevado / Administrador): # irm https://enterprisechat.es/install.ps1 | iex # # Detecta arquitectura, descarga el instalador firmado mas reciente desde # GitHub Releases, verifica el SHA-256 publicado + la firma Authenticode, # y lo ejecuta en modo silencioso. Tras instalar el servicio Windows # "EnterpriseChat" queda corriendo en :5080. # # El instalador (Inno Setup) genera la clave JWT y la contrasena admin # inicial y las muestra al final del proceso. Tambien las deja en # C:\Program Files\EnterpriseChat\.first-admin-password. # # Mas info: https://enterprisechat.es $ErrorActionPreference = 'Stop' $Repo = 'angelcripto/enterprisechat' $Tmp = Join-Path $env:TEMP "enterprisechat-$([guid]::NewGuid().ToString('N'))" New-Item -ItemType Directory -Force -Path $Tmp | Out-Null function Write-Color { param([string]$Text, [ConsoleColor]$Color = 'White') $prev = $Host.UI.RawUI.ForegroundColor $Host.UI.RawUI.ForegroundColor = $Color Write-Host $Text $Host.UI.RawUI.ForegroundColor = $prev } # Pausa antes de salir si estamos en una consola interactiva. El # patron `irm ... | iex` suele lanzarse desde una ventana de PowerShell # que se cierra automaticamente cuando el script termina con un mensaje # de error, asi que el usuario no llega a leer el motivo. Con esto # pausamos hasta que pulse Enter. Si stdin esta redirigido (CI, pipes) # no bloqueamos, simplemente salimos. function Exit-WithPause { param([int]$Code = 1) try { if ([Environment]::UserInteractive -and -not [Console]::IsInputRedirected) { Write-Host '' Write-Color 'Pulsa Enter para cerrar esta ventana...' DarkGray [void](Read-Host) } } catch { # Si Read-Host falla por algun motivo, salimos directamente. } exit $Code } # ---- 1. Pre-requisitos -------------------------------------------------- if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Write-Color 'El instalador necesita privilegios de administrador.' Yellow Write-Color 'Voy a relanzar PowerShell elevado automaticamente.' Yellow Write-Color 'Acepta el dialogo UAC que aparece a continuacion.' DarkGray # Relanzamos el mismo one-liner en una sesion elevada. Asi no # dependemos de tener el script en disco (irm | iex evalua inline). # Si el usuario cancela UAC, Start-Process lanza Win32Exception y # caemos al catch para dar instrucciones manuales. $relaunchArgs = @( '-NoProfile', '-NoExit', # mantiene la nueva ventana abierta para leer la salida '-ExecutionPolicy', 'Bypass', '-Command', 'irm https://enterprisechat.es/install.ps1 | iex' ) try { Start-Process -FilePath 'powershell.exe' ` -Verb RunAs ` -ArgumentList $relaunchArgs ` -ErrorAction Stop # La nueva ventana elevada toma el control; salimos sin pausa. exit 0 } catch { Write-Color 'No se pudo elevar (UAC cancelado o sin permisos).' Red Write-Color '' White Write-Color 'Para arrancarlo manualmente:' Yellow Write-Color ' 1. Pulsa la tecla Windows.' Yellow Write-Color ' 2. Escribe "PowerShell".' Yellow Write-Color ' 3. Boton derecho -> "Ejecutar como administrador".' Yellow Write-Color ' 4. Pega: irm https://enterprisechat.es/install.ps1 | iex' Yellow Exit-WithPause 1 } } if (-not [Environment]::Is64BitOperatingSystem) { Write-Color 'EnterpriseChat solo soporta Windows 64 bits.' Red Exit-WithPause 1 } # ---- 2. Resolver release mas reciente (incluyendo pre-releases) --------- # La URL /releases/latest/download/... de GitHub SOLO resuelve releases # estables; con prereleases (tag con suffix -alpha/-beta/-rc) devuelve # 404. Usamos la API REST para coger la release mas reciente, # prereleases incluidas, y descargar desde su asset.browser_download_url. $Asset = 'enterprisechat-server-win-x64.exe' $ShaAsset = "$Asset.sha256" $ExePath = Join-Path $Tmp $Asset Write-Color "==> Buscando release mas reciente en GitHub" Cyan try { $headers = @{ 'User-Agent' = 'EnterpriseChat-Installer' } $releases = Invoke-RestMethod ` -Uri "https://api.github.com/repos/$Repo/releases?per_page=10" ` -Headers $headers -ErrorAction Stop $rel = $releases | Where-Object { -not $_.draft } | Select-Object -First 1 if (-not $rel) { throw 'No hay releases publicadas todavia.' } Write-Color " Release: $($rel.tag_name) ($(if ($rel.prerelease) {'prerelease'} else {'estable'}))" Green $assetObj = $rel.assets | Where-Object { $_.name -eq $Asset } | Select-Object -First 1 if (-not $assetObj) { throw "Asset '$Asset' no encontrado en $($rel.tag_name)." } $downloadUrl = $assetObj.browser_download_url $shaObj = $rel.assets | Where-Object { $_.name -eq $ShaAsset } | Select-Object -First 1 $shaUrl = if ($shaObj) { $shaObj.browser_download_url } else { $null } } catch { Write-Color "No se pudo consultar la API de GitHub: $($_.Exception.Message)" Red Write-Color "Verifica conectividad a https://api.github.com y que existan releases en" Yellow Write-Color " https://github.com/$Repo/releases" Yellow Exit-WithPause 1 } Write-Color "==> Descargando $Asset" Cyan try { Invoke-WebRequest -UseBasicParsing -Uri $downloadUrl -OutFile $ExePath } catch { Write-Color "No se pudo descargar $downloadUrl" Red Exit-WithPause 1 } # Verificacion SHA-256. $ShaPath = Join-Path $Tmp $ShaAsset if ($shaUrl) { try { Invoke-WebRequest -UseBasicParsing -Uri $shaUrl -OutFile $ShaPath -ErrorAction Stop Write-Color '==> Verificando SHA-256' Cyan $expected = (Get-Content $ShaPath -Raw).Split(' ')[0].Trim().ToLowerInvariant() $actual = (Get-FileHash -Algorithm SHA256 $ExePath).Hash.ToLowerInvariant() if ($expected -ne $actual) { Write-Color "SHA-256 NO coincide. Esperado: $expected, obtenido: $actual" Red Write-Color 'Aborto por seguridad: el binario descargado no es el publicado.' Red Exit-WithPause 1 } Write-Color ' SHA-256 OK' Green } catch { Write-Color ' (No se pudo verificar SHA-256; continuando)' Yellow } } else { Write-Color ' (Sin checksum publicado todavia; omitido)' Yellow } # Verificacion firma Authenticode (informativa: aceptamos UnknownError # mientras no haya cert EV con reputacion, pero rechazamos HashMismatch # o NotSigned que indican manipulacion). $sig = Get-AuthenticodeSignature $ExePath switch ($sig.Status) { 'Valid' { Write-Color "==> Firma Authenticode OK ($($sig.SignerCertificate.Subject))" Green } 'NotSigned' { Write-Color ' Aviso: el instalador no esta firmado (release temprana).' Yellow } 'HashMismatch' { Write-Color 'Firma Authenticode HashMismatch: el binario esta alterado.' Red Exit-WithPause 1 } default { Write-Color " Aviso firma: $($sig.Status). Continuando." Yellow } } # ---- 3. Ejecutar instalador en silent ----------------------------------- Write-Color '==> Ejecutando instalador (modo silent)' Cyan $LogPath = Join-Path $Tmp 'install.log' $p = Start-Process -FilePath $ExePath ` -ArgumentList "/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /LOG=`"$LogPath`"" ` -Wait -PassThru if ($p.ExitCode -ne 0) { Write-Color "Instalador termino con codigo $($p.ExitCode). Log: $LogPath" Red Exit-WithPause 1 } # ---- 4. Verificar servicio ---------------------------------------------- Write-Color '==> Verificando servicio EnterpriseChat' Cyan $svc = Get-Service -Name 'EnterpriseChat' -ErrorAction SilentlyContinue if (-not $svc) { Write-Color 'El servicio "EnterpriseChat" no aparece tras instalar. Revisa el log:' Red Write-Color " $LogPath" Yellow Exit-WithPause 1 } if ($svc.Status -ne 'Running') { try { Start-Service -Name 'EnterpriseChat' } catch { } $svc = Get-Service -Name 'EnterpriseChat' } Write-Host '' $svc | Format-Table -AutoSize Name, Status, StartType # ---- 5. Mostrar contrasena inicial -------------------------------------- $InstallDir = "$env:ProgramFiles\EnterpriseChat" $PwFile = Join-Path $InstallDir '.first-admin-password' Write-Host '' Write-Color '================================================================' Green Write-Color ' EnterpriseChat instalado correctamente.' Green Write-Color '================================================================' Green Write-Host '' Write-Host " URL admin: http://$($env:COMPUTERNAME):5080/" Write-Host ' Usuario: admin' if (Test-Path $PwFile) { $pwd = (Get-Content $PwFile -Raw).Trim() Write-Host " Contrasena: $pwd" Remove-Item -Force $PwFile Write-Host '' Write-Color ' Esta contrasena SOLO se muestra esta vez. Anotala.' Yellow } else { Write-Host ' Contrasena: (ya consumida; revisa C:\Program Files\EnterpriseChat o regenera con --reset-admin-password)' } Write-Host '' Write-Host ' Servicio: services.msc -> EnterpriseChat' Write-Host " Datos: $InstallDir" Write-Host ''