using Newtonsoft.Json; using System; using System.IO; namespace GB5Shared.Config { /// /// Singleton that loads GB5Shared library defaults from the physical /// gb5shared.json file published alongside every GB5 module binary. /// /// Why a physical file (not embedded resource): /// Operations teams and clients can change settings such as /// by editing gb5shared.json /// in the deployment directory and restarting the service — no recompile needed. /// /// File location at runtime: /// {AppContext.BaseDirectory}/gb5shared.json /// The .NET SDK copies this file to the publish output automatically because /// it is declared as a Content item with CopyToPublishDirectory=PreserveNewest /// in GB5Shared.csproj. /// /// Override behaviour (priority, highest first): /// 1. Module's own appsettings.json → Gb5SystemDTO:SessionExpiryMinutes > 0 /// 2. gb5shared.json (this file) in the deployment directory /// 3. Code default (15 minutes) — used when the file is absent or unreadable /// /// Usage (read-only): /// int minutes = GB5SharedSettings.Instance.SessionExpiryMinutes; /// public sealed class GB5SharedSettings { private static GB5SharedSettings? _instance; private static readonly object _lock = new(); // ── Settings ───────────────────────────────────────────────────────── /// /// Master on/off switch for the session heartbeat check. /// "Y" (default) — enforce sliding session expiry on every API call. /// "N" — skip session check entirely (useful during debugging). /// Change in gb5shared.json and restart the service. /// public string SessionHeartbeatEnabled { get; set; } = "Y"; /// /// Session idle timeout in minutes. /// uses this value /// when the host module has not overridden Gb5SystemDTO:SessionExpiryMinutes /// in its own appsettings.json. /// Default (in gb5shared.json): 15. /// public int SessionExpiryMinutes { get; set; } = 15; // ── Singleton access ────────────────────────────────────────────────── /// /// The shared instance, lazily loaded from gb5shared.json on first access. /// Cached for the lifetime of the process; restart the service after editing the file. /// public static GB5SharedSettings Instance { get { if (_instance is not null) return _instance; lock (_lock) { if (_instance is not null) return _instance; _instance = Load(); } return _instance; } } // ── Loader ──────────────────────────────────────────────────────────── private static GB5SharedSettings Load() { try { // AppContext.BaseDirectory is the publish output folder at runtime — // the same directory where gb5shared.json is copied during dotnet publish. string filePath = Path.Combine(AppContext.BaseDirectory, "gb5shared.json"); if (!File.Exists(filePath)) return new GB5SharedSettings(); // file absent — use in-code defaults string json = File.ReadAllText(filePath); return JsonConvert.DeserializeObject(json) ?? new GB5SharedSettings(); } catch { // File unreadable or JSON malformed — fall back to in-code defaults. // The middleware always has a valid expiry value regardless. return new GB5SharedSettings(); } } } }