Thomas Fransolet 82e61dcded Flux de provisioning d'une base préprod ou prod
Compose Postgres (PostGIS + pgvector épinglé par digest), scripts de bootstrap
du premier SuperAdmin, de lancement local du service et de migration des
données, et le README du flux en huit étapes.

Le port est lié à 127.0.0.1 et non publié : le Postgres précédent, exposé par
un simple "5432:5432" avec mym/mym, a encaissé 1 074 465 échecs
d'authentification entre juin et octobre 2025. Le compte mym n'a jamais été
tenté — c'est le seul hasard qui a sauvé la base. Les limites de log viennent
du même serveur, où un conteneur avait atteint 516 Mo sur un disque de 20 Go.

Le SuperAdmin passe par le token de réinitialisation plutôt que par un INSERT :
les mots de passe étant hachés en scrypt, seule l'application peut produire le
bon format, et personne d'autre que l'opérateur ne connaît le mot de passe.
MigrationController l'exige et la migration n'en crée aucun, MongoDB n'ayant
pas de champ Role.

Éprouvé sur la préprod le 07/09 : 4 instances, 315 sections migrées et 20
signalées sur 335, 2383 ressources, tout réconcilié avec MongoDB.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 16:11:56 +02:00

51 lines
2.4 KiB
PowerShell

<#
Genere le SQL qui cree le PREMIER compte SuperAdmin.
Pourquoi ce detour plutot qu'un INSERT direct avec un mot de passe :
les mots de passe sont haches en scrypt (PasswordUtils, 16384 iterations),
impossible a calculer hors .NET. Le token de reinitialisation, lui, est un
simple SHA-256 hexadecimal (PasswordTokenHelper). On laisse donc l'application
faire le hachage scrypt via set-password : le format est garanti correct, et
personne d'autre que toi ne connait le mot de passe.
MigrationController est [Authorize(Policy = SuperAdmin)] et la migration ne
cree aucun SuperAdmin (Mongo n'a pas de champ Role). Ce compte est donc le
prealable oblige a toute migration de donnees.
#>
param(
[string]$Email,
# L'instance doit EXISTER : TokensService.cs:82 fait Instances.Find(user.InstanceId)
# puis lit .PinCode sans test de nullite -> 500 au login sinon.
[string]$InstanceId = 'sa-bootstrap'
)
if ([string]::IsNullOrWhiteSpace($Email)) { $Email = Read-Host "Email du compte SuperAdmin" }
$Email = $Email.ToLower() # Authenticate fait login.email.ToLower()
$token = -join ((1..40) | ForEach-Object { '{0:x}' -f (Get-Random -Maximum 16) })
$sha = [System.Security.Cryptography.SHA256]::Create()
$hash = ($sha.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($token)) |
ForEach-Object { $_.ToString('x2') }) -join ''
Write-Host ""
Write-Host "=== ETAPE A : sur une base VIERGE uniquement, creer l'instance d'echafaudage ===" -ForegroundColor Cyan
Write-Host " (a sauter si tu passes -InstanceId d'une instance deja migree)"
Write-Host @"
insert into "Instances" ("Id","Name","DateCreation")
values ('$InstanceId','Bootstrap SuperAdmin', now());
"@
Write-Host "=== ETAPE B : creer le compte ===" -ForegroundColor Cyan
Write-Host @"
insert into "Users"
("Id","Email","Password","FirstName","LastName","Token","DateCreation","InstanceId","Role","PasswordTokenHash","PasswordTokenExpiresAt")
values
('sa-bootstrap-0001','$Email','pending','Super','Admin','',now(),'$InstanceId',0,'$hash', now() + interval '48 hours');
"@
Write-Host "=== ETAPE C : poser le mot de passe (service demarre) ===" -ForegroundColor Cyan
Write-Host " run.cmd 3-set-password.ps1 -Token $token"
Write-Host ""
Write-Host "Le token vaut 48 h et n'est ecrit dans aucun fichier : garde cette fenetre." -ForegroundColor Yellow
Write-Host "N'oublie pas de COMMITER les INSERT : DBeaver n'auto-commite pas toujours." -ForegroundColor Yellow