Codemaru 1.0.0.0
QR 코드, 모바일 랜딩 페이지, vCard 연락처 저장과 명함 디자인을 한 화면에서 제공하는 디지털 명함 서비스입니다.
로딩중...
검색중...
일치하는것 없음
CertificateMonitorViewModel.cs
이 파일의 문서화 페이지로 가기
4using Microsoft.Extensions.Options;
5using System.ComponentModel;
6using System.Runtime.CompilerServices;
7using System.Windows.Input;
8using System.Windows.Media;
9
10namespace Codemaru.ViewModels;
11
20public sealed class CertificateMonitorViewModel : INotifyPropertyChanged
21{
75 private string _certificateDirectory;
84 private string _wacsPath;
93 private string _nginxPath;
111 private string _statusMessage = "Certificate monitor is ready.";
120 private string _certificatePath = string.Empty;
129 private string _subject = string.Empty;
138 private string _issuer = string.Empty;
147 private string _notAfterText = "-";
156 private string _remainingDaysText = "-";
165 private string _healthText = "Unknown";
174 private Brush _healthBrush = Brushes.Gray;
183 private string _taskName = "-";
192 private string _taskState = "-";
201 private string _lastRunTime = "-";
210 private string _nextRunTime = "-";
219 private string _lastTaskResult = "-";
228 private string _commandOutput = string.Empty;
229
287 IOptions<CertificateMonitorOptions> options,
288 ICertificateMonitorService certificateMonitorService,
289 IWinAcmeService winAcmeService,
290 INginxReloadService nginxReloadService,
291 ICertificateSettingsWriter settingsWriter)
292 {
293 CertificateMonitorOptions value = options?.Value ?? throw new ArgumentNullException(nameof(options));
294 _certificateMonitorService = certificateMonitorService ?? throw new ArgumentNullException(nameof(certificateMonitorService));
295 _winAcmeService = winAcmeService ?? throw new ArgumentNullException(nameof(winAcmeService));
296 _nginxReloadService = nginxReloadService ?? throw new ArgumentNullException(nameof(nginxReloadService));
297 _settingsWriter = settingsWriter ?? throw new ArgumentNullException(nameof(settingsWriter));
298 _baseOptions = CloneOptions(value);
299
301 _wacsPath = value.WacsPath;
302 _nginxPath = value.NginxPath;
304 WarningDays = value.WarningDays;
307 PfxPassword = value.PfxPassword ?? string.Empty;
308
311 RunRenewCommand = new AsyncRelayCommand(() => RunRenewAsync(force: false));
312 ForceRenewCommand = new AsyncRelayCommand(() => RunRenewAsync(force: true));
315 }
316
325 public event PropertyChangedEventHandler? PropertyChanged;
326
336 {
338 set => SetField(ref _certificateDirectory, value);
339 }
340
349 public string WacsPath
350 {
351 get => _wacsPath;
352 set => SetField(ref _wacsPath, value);
353 }
354
363 public string NginxPath
364 {
365 get => _nginxPath;
366 set => SetField(ref _nginxPath, value);
367 }
368
378 {
380 set => SetField(ref _nginxWorkingDirectory, value);
381 }
382
391 public string PfxPassword { get; set; }
392
401 public int WarningDays { get; set; }
402
411 public int CriticalDays { get; set; }
412
421 public int MaxCommandOutputChars { get; set; }
422
431 public string StatusMessage
432 {
433 get => _statusMessage;
434 private set => SetField(ref _statusMessage, value);
435 }
436
445 public string CertificatePath
446 {
447 get => _certificatePath;
448 private set => SetField(ref _certificatePath, value);
449 }
450
459 public string Subject
460 {
461 get => _subject;
462 private set => SetField(ref _subject, value);
463 }
464
473 public string Issuer
474 {
475 get => _issuer;
476 private set => SetField(ref _issuer, value);
477 }
478
487 public string NotAfterText
488 {
489 get => _notAfterText;
490 private set => SetField(ref _notAfterText, value);
491 }
492
501 public string RemainingDaysText
502 {
503 get => _remainingDaysText;
504 private set => SetField(ref _remainingDaysText, value);
505 }
506
515 public string HealthText
516 {
517 get => _healthText;
518 private set => SetField(ref _healthText, value);
519 }
520
529 public Brush HealthBrush
530 {
531 get => _healthBrush;
532 private set => SetField(ref _healthBrush, value);
533 }
534
543 public string TaskName
544 {
545 get => _taskName;
546 private set => SetField(ref _taskName, value);
547 }
548
557 public string TaskState
558 {
559 get => _taskState;
560 private set => SetField(ref _taskState, value);
561 }
562
571 public string LastRunTime
572 {
573 get => _lastRunTime;
574 private set => SetField(ref _lastRunTime, value);
575 }
576
585 public string NextRunTime
586 {
587 get => _nextRunTime;
588 private set => SetField(ref _nextRunTime, value);
589 }
590
599 public string LastTaskResult
600 {
601 get => _lastTaskResult;
602 private set => SetField(ref _lastTaskResult, value);
603 }
604
613 public string CommandOutput
614 {
615 get => _commandOutput;
616 private set => SetField(ref _commandOutput, value);
617 }
618
627 public ICommand RefreshCommand { get; }
628
637 public ICommand CheckRenewalTaskCommand { get; }
638
647 public ICommand RunRenewCommand { get; }
648
657 public ICommand ForceRenewCommand { get; }
658
667 public ICommand ReloadNginxCommand { get; }
668
677 public ICommand SaveSettingsCommand { get; }
678
695 private async Task RefreshAsync()
696 {
698 .GetStatusAsync(CreateOptions(), CancellationToken.None)
699 .ConfigureAwait(true);
700
701 CertificatePath = string.IsNullOrWhiteSpace(status.CertificatePath) ? "-" : status.CertificatePath;
702 Subject = string.IsNullOrWhiteSpace(status.Subject) ? "-" : status.Subject;
703 Issuer = string.IsNullOrWhiteSpace(status.Issuer) ? "-" : status.Issuer;
704 NotAfterText = status.NotAfter?.ToString("yyyy-MM-dd HH:mm:ss") ?? "-";
705 RemainingDaysText = status.RemainingDays.HasValue ? $"{status.RemainingDays.Value} days" : "-";
706 HealthText = status.State.ToString();
708 StatusMessage = status.Message;
709 }
710
727 private async Task CheckRenewalTaskAsync()
728 {
730 .GetRenewalTaskAsync(CancellationToken.None)
731 .ConfigureAwait(true);
732
733 TaskName = FormatTaskName(task);
734 TaskState = string.IsNullOrWhiteSpace(task.State) ? "-" : task.State;
735 LastRunTime = string.IsNullOrWhiteSpace(task.LastRunTime) ? "-" : task.LastRunTime;
736 NextRunTime = string.IsNullOrWhiteSpace(task.NextRunTime) ? "-" : task.NextRunTime;
737 LastTaskResult = string.IsNullOrWhiteSpace(task.LastTaskResult) ? "-" : task.LastTaskResult;
738 StatusMessage = task.Message;
739 }
740
765 private async Task RunRenewAsync(bool force)
766 {
768 .RunRenewAsync(CreateOptions(), force, CancellationToken.None)
769 .ConfigureAwait(true);
770
771 ApplyProcessResult(force ? "Force renew" : "Renew", result);
772 await RefreshAsync().ConfigureAwait(true);
773 }
774
791 private async Task ReloadNginxAsync()
792 {
794 .ReloadAsync(CreateOptions(), CancellationToken.None)
795 .ConfigureAwait(true);
796
797 ApplyProcessResult("Nginx reload", result);
798 }
799
816 private async Task SaveSettingsAsync()
817 {
818 await _settingsWriter.SaveAsync(CreateOptions(), CancellationToken.None).ConfigureAwait(true);
819 StatusMessage = "Certificate settings saved to appsettings.local.json.";
820 }
821
846 private void ApplyProcessResult(string actionName, ProcessExecutionResult result)
847 {
848 StatusMessage = $"{actionName}: {result.Message}";
849 CommandOutput = string.Join(Environment.NewLine, new[]
850 {
851 $"[{actionName}] ExitCode={result.ExitCode}, Success={result.IsSuccess}",
852 result.Output,
853 result.Error
854 }.Where(line => !string.IsNullOrWhiteSpace(line)));
855 }
856
874 {
876 {
878 CertificateFilePatterns = _baseOptions.CertificateFilePatterns.ToArray(),
879 PfxPassword = string.IsNullOrWhiteSpace(PfxPassword) ? null : PfxPassword,
883 NginxReloadArguments = string.IsNullOrWhiteSpace(_baseOptions.NginxReloadArguments)
884 ? "-s reload"
885 : _baseOptions.NginxReloadArguments,
886 WarningDays = Math.Max(1, WarningDays),
887 CriticalDays = Math.Max(1, CriticalDays),
889 };
890 }
891
917 {
919 {
921 CertificateFilePatterns = source.CertificateFilePatterns.ToArray(),
922 PfxPassword = source.PfxPassword,
923 WacsPath = source.WacsPath,
924 NginxPath = source.NginxPath,
926 NginxReloadArguments = source.NginxReloadArguments,
927 WarningDays = source.WarningDays,
928 CriticalDays = source.CriticalDays,
929 MaxCommandOutputChars = source.MaxCommandOutputChars
930 };
931 }
932
957 private static string FormatTaskName(WinAcmeTaskInfo task)
958 {
959 if (string.IsNullOrWhiteSpace(task.TaskName))
960 {
961 return "-";
962 }
963
964 if (string.IsNullOrWhiteSpace(task.TaskPath) || task.TaskPath == @"\")
965 {
966 return task.TaskName;
967 }
968
969 return $"{task.TaskPath}{task.TaskName}";
970 }
971
996 private static Brush ResolveBrush(CertificateHealthState state)
997 {
998 return state switch
999 {
1000 CertificateHealthState.Ok => Brushes.ForestGreen,
1001 CertificateHealthState.Warning => Brushes.DarkOrange,
1002 CertificateHealthState.Critical => Brushes.OrangeRed,
1003 CertificateHealthState.Expired => Brushes.Firebrick,
1004 CertificateHealthState.Error => Brushes.Firebrick,
1005 _ => Brushes.Gray
1006 };
1007 }
1008
1057 private bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
1058 {
1059 if (EqualityComparer<T>.Default.Equals(field, value))
1060 {
1061 return false;
1062 }
1063
1064 field = value;
1065 OnPropertyChanged(propertyName);
1066 return true;
1067 }
1068
1085 private void OnPropertyChanged([CallerMemberName] string? propertyName = null)
1086 {
1087 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
1088 }
1089}
bool SetField< T >(ref T field, T value, [CallerMemberName] string? propertyName=null)
static Brush ResolveBrush(CertificateHealthState state)
void OnPropertyChanged([CallerMemberName] string? propertyName=null)
CertificateMonitorViewModel(IOptions< CertificateMonitorOptions > options, ICertificateMonitorService certificateMonitorService, IWinAcmeService winAcmeService, INginxReloadService nginxReloadService, ICertificateSettingsWriter settingsWriter)
static CertificateMonitorOptions CloneOptions(CertificateMonitorOptions source)
readonly ICertificateMonitorService _certificateMonitorService
void ApplyProcessResult(string actionName, ProcessExecutionResult result)