using Newtonsoft.Json; using PKISharp.WACS.Plugins.Base.Options; using PKISharp.WACS.Services; using PKISharp.WACS.Services.Serialization; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; namespace PKISharp.WACS.DomainObjects { /// /// Main unit of work for the program, contains all the information /// required to generate a target, do the validation, store the resulting /// certificate somewhere and finally run installation steps to update /// software. /// [DebuggerDisplay("Renewal {Id}: {FriendlyName}")] public class Renewal { internal static Renewal Create(string? id, int renewalDays, PasswordGenerator generator) { var ret = new Renewal { New = true, Id = string.IsNullOrEmpty(id) ? ShortGuid.NewGuid().ToString() : id, PfxPassword = new ProtectedString(generator.Generate()), RenewalDays = renewalDays }; return ret; } /// /// Is this renewal a test? /// [JsonIgnore] internal bool Test { get; set; } /// /// Has this renewal been changed? /// [JsonIgnore] internal bool Updated { get; set; } /// /// Has this renewal been deleted? /// [JsonIgnore] internal bool Deleted { get; set; } /// /// Current renewal days setting, stored /// here as a shortcut because its not /// otherwise available to the instance /// [JsonIgnore] internal int RenewalDays { get; set; } /// /// Is this renewal new /// [JsonIgnore] internal bool New { get; set; } /// /// Unique identifer for the renewal /// public string Id { get; set; } = ""; /// /// Friendly name for the certificate. If left /// blank or empty, the CommonName will be used. /// public string? FriendlyName { get; set; } /// /// Display name, as the program shows this certificate /// in the interface. This is set to the most recently /// used FriendlyName /// public string? LastFriendlyName { get; set; } /// /// Plain text readable version of the PfxFile password /// [JsonProperty(PropertyName = "PfxPasswordProtected")] public ProtectedString? PfxPassword { get; set; } public DateTime? GetDueDate() { var lastSuccess = History.LastOrDefault(x => x.Success)?.Date; if (lastSuccess.HasValue) { return lastSuccess. Value. AddDays(RenewalDays). ToLocalTime(); } else { return null; } } public bool IsDue() => GetDueDate() == null || GetDueDate() < DateTime.Now; /// /// Store information about TargetPlugin /// public TargetPluginOptions TargetPluginOptions { get; set; } = new TargetPluginOptions(); /// /// Store information about ValidationPlugin /// public ValidationPluginOptions ValidationPluginOptions { get; set; } = new ValidationPluginOptions(); /// /// Store information about CsrPlugin /// public CsrPluginOptions? CsrPluginOptions { get; set; } /// /// Store information about OrderPlugin /// public OrderPluginOptions? OrderPluginOptions { get; set; } /// /// Store information about StorePlugin /// public List StorePluginOptions { get; set; } = new List(); /// /// Store information about InstallationPlugins /// public List InstallationPluginOptions { get; set; } = new List(); /// /// History for this renewal /// public List History { get; set; } = new List(); /// /// Pretty format /// /// public override string ToString() => ToString(null); /// /// Pretty format /// /// public string ToString(IInputService? inputService) { var success = History.FindAll(x => x.Success).Count; var errors = History.AsEnumerable().Reverse().TakeWhile(x => !x.Success); var ret = $"{LastFriendlyName} - renewed {success} time{(success != 1 ? "s" : "")}"; var due = IsDue(); var dueDate = GetDueDate(); if (inputService == null) { ret += due ? ", due now" : dueDate == null ? "" : $", due after {dueDate}"; } else { ret += due ? ", due now" : dueDate == null ? "" : $", due after {inputService.FormatDate(dueDate.Value)}"; } if (errors.Count() > 0) { var messages = errors.SelectMany(x => x.ErrorMessages).Where(x => !string.IsNullOrEmpty(x)); ret += $", {errors.Count()} error{(errors.Count() != 1 ? "s" : "")} like \"{messages.FirstOrDefault() ?? "[null]"}\""; } return ret; } } }