Mode auto (auto-launch d'une version désignée au démarrage et après exit) : - Master toggle + version désignée via bouton AUTO (orange) sur chaque row - Countdown 5 s configurable avec popup d'annulation (StartAutoLaunchCountdown) - Args CLI passés à PROSERVE : opérateur tape juste le nom (autoconnect, login), le launcher ajoute -/=/quotes. Format produit identique à un .bat. Fix : passage de ArgumentList à Arguments string pour éviter le quotage auto .NET sur les args contenant '=' (cassait FParse::Value). - Garde-fou anti double-lancement : refuse de lancer si _runningProserve vivant OU IProcessLauncher.IsRunning() détecte une instance externe. Silent pour les triggers auto, popup pour les clics manuels. - Option « Attendre santé système » : countdown différé tant que les health checks ne sont pas tous OK (phase 1 du dialog avec liste des pending). Settings lock par license (remplace l'ancien lock global manifest) : - Colonne settings_lock_password_hash sur table licenses (migration 003) - Backoffice : bouton 🔒 par license pour set/clear hash SHA-256 - Payload /license/validate inclut settingsLockPasswordHash (v3 canonique) - 3-tier fallback signature : v3 → v2 → legacy pour compat cache offline - SettingsLockService : in-memory unlock state, gate l'expander Avancés - SettingsLockDialog : prompt mdp, persiste déverrouillé jusqu'au restart Fix post-install : la row restait en visuel « Installing » jusqu'au prochain Check Updates. Reset explicite row.State=InstalledIdle + _activeRow=null AVANT le RebuildList post-install pour purger l'instance orpheline. Migrations : - 002_channel_betas.sql réécrit en ALTER simples (DELIMITER cassait migrate.php qui split sur ';\n') - migrate.php tolère « Duplicate column/key name » comme idempotent Strings (5 langues, ~25 nouvelles) : - Renomme « Relance automatique » → « Lancement automatique » (dialog utilisé pour les 3 entry points : clic, startup, post-exit) - Tooltips auto-mode, settings lock prompts, health wait phase, etc. Bumps : 0.27.4 → 0.28.10 (csproj + .iss). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
80 lines
2.9 KiB
C#
80 lines
2.9 KiB
C#
using System.Text.Json.Serialization;
|
|
|
|
namespace PSLauncher.Models;
|
|
|
|
public sealed class LicenseValidationResponse
|
|
{
|
|
[JsonPropertyName("status")]
|
|
public string Status { get; set; } = "invalid";
|
|
|
|
[JsonPropertyName("licenseId")]
|
|
public string? LicenseId { get; set; }
|
|
|
|
[JsonPropertyName("ownerName")]
|
|
public string? OwnerName { get; set; }
|
|
|
|
[JsonPropertyName("issuedAt")]
|
|
public DateTime? IssuedAt { get; set; }
|
|
|
|
[JsonPropertyName("downloadEntitlementUntil")]
|
|
public DateTime? DownloadEntitlementUntil { get; set; }
|
|
|
|
[JsonPropertyName("maxMachines")]
|
|
public int? MaxMachines { get; set; }
|
|
|
|
/// <summary>
|
|
/// Channel de manifest associé à la license. NULL = manifest default
|
|
/// (versions.json). Sinon le launcher fetch versions-{Channel}.json. Le
|
|
/// champ est inclus dans la signature Ed25519, donc un user ne peut pas
|
|
/// modifier sa réponse cachée pour basculer sur un autre channel.
|
|
/// </summary>
|
|
[JsonPropertyName("channel")]
|
|
public string? Channel { get; set; }
|
|
|
|
/// <summary>
|
|
/// True si la license autorise l'affichage des versions taggées
|
|
/// <c>isBeta=true</c> dans le launcher. Le filtrage est côté client (le
|
|
/// serveur peut servir le manifest complet — la signature Ed25519
|
|
/// protège contre toute modif locale du flag).
|
|
/// </summary>
|
|
[JsonPropertyName("canSeeBetas")]
|
|
public bool CanSeeBetas { get; set; }
|
|
|
|
/// <summary>
|
|
/// Hash SHA-256 (hex lowercase) du mot de passe qui verrouille les Settings
|
|
/// avancés du launcher. NULL = pas de verrouillage. Défini par-license dans
|
|
/// le backoffice (table <c>licenses.settings_lock_password_hash</c>) → permet
|
|
/// un mot de passe différent par client. Inclus dans la signature Ed25519.
|
|
/// </summary>
|
|
[JsonPropertyName("settingsLockPasswordHash")]
|
|
public string? SettingsLockPasswordHash { get; set; }
|
|
|
|
[JsonPropertyName("serverTime")]
|
|
public DateTime? ServerTime { get; set; }
|
|
|
|
[JsonPropertyName("message")]
|
|
public string? Message { get; set; }
|
|
|
|
[JsonPropertyName("signature")]
|
|
public string? Signature { get; set; }
|
|
|
|
public bool IsValid => Status == "valid";
|
|
public bool IsExpired => Status == "expired";
|
|
|
|
public bool CanDownload(VersionManifest version)
|
|
{
|
|
if (!IsValid && !IsExpired) return false;
|
|
if (DownloadEntitlementUntil is null) return false;
|
|
if (version.MinLicenseDate is null) return true; // pas de minimum imposé
|
|
return DownloadEntitlementUntil >= version.MinLicenseDate;
|
|
}
|
|
}
|
|
|
|
public sealed class LicenseValidationRequest
|
|
{
|
|
[JsonPropertyName("licenseKey")] public string LicenseKey { get; set; } = string.Empty;
|
|
[JsonPropertyName("machineId")] public string MachineId { get; set; } = string.Empty;
|
|
[JsonPropertyName("machineLabel")] public string? MachineLabel { get; set; }
|
|
[JsonPropertyName("launcherVersion")] public string LauncherVersion { get; set; } = string.Empty;
|
|
}
|