diff --git a/BLAZAM/BLAZAM.csproj b/BLAZAM/BLAZAM.csproj index cd3a5100..9f8bb20d 100644 --- a/BLAZAM/BLAZAM.csproj +++ b/BLAZAM/BLAZAM.csproj @@ -6,7 +6,7 @@ enable false 1.1.0 - 2024.11.11.2302 + 2024.11.13.1850 false BLAZAM False diff --git a/BLAZAM/updater/update.ps1 b/BLAZAM/updater/update.ps1 index 21b141c4..0184c44d 100644 --- a/BLAZAM/updater/update.ps1 +++ b/BLAZAM/updater/update.ps1 @@ -62,6 +62,8 @@ $updateScript= { if(!$global:iis){ Stop-Process -ID $global:processId -Force + + Stop-Service -Name "Blazam" -Force -ErrorAction Continue } Start-Sleep -Seconds 15 @@ -74,56 +76,11 @@ $updateScript= { Remove-Item -Path $global:destination\app_offline.htm -Force if(!$global:iis){ - Write-Host("Process path: " + $global:processFilePath) - - if($global:processArguments -ne $null -and $global:processArguments -ne "") - { - - Write-Host("Starting with arguments: " + $global:processArguments) - $restartedProcess = Start-Process -FilePath $global:processFilePath -ArgumentList $global:processArguments -WorkingDirectory $global:destination -PassThru + Start-Service -Name "Blazam" -ErrorAction Continue - }else{ - $restartedProcess = Start-Process -FilePath $global:processFilePath -WorkingDirectory $global:destination -PassThru - - } Write-Host("Waiting 15 seconds for Application to restart") Start-Sleep -Seconds 15 - <# - Write-Host("Process Stats: "+($restartedProcess| Select-Object *)) - if ($restartedProcess.ExitTime -eq $null -or $global:iis) { - Write-Host("Error: Web Application failed to restart rolling back changes") - #Perform Rollback Section - $restoreSource = $backupDirectory + "*" - Write-Host("Rolling back update") - Write-Host("Source: " + $restoreSource) - Write-Host("Destination: " + $global:destination) - Copy-Item -Path $restoreSource -Destination $backupDirectory -Recurse -Verbose -Force - Write-Host("Restarting ApplicationPool") - - if($global:processArguments -ne $null -and $global:processArguments -ne "") - { - - Write-Host("Starting with arguments: " + $global:processArguments) - $restartedProcess = Start-Process -FilePath $global:processFilePath -ArgumentList $global:processArguments -PassThru - - }else{ - $restartedProcess = Start-Process -FilePath $global:processFilePath -PassThru - - } - #$runningSite | Start-IISSite - Write-Host("Waiting 15 seconds for Application to restart") - - Start-Sleep -Seconds 15 - if ($restartedProcess.ExitTime -eq $null) { - Write-Host("Error: Rollback performed, but application did not start! Oh no...") - } - else { - Write-Host("Rollback completed successfully") - } - Stop-Transcript - exit - } - #> + } diff --git a/BLAZAMGui/Layouts/UserNotificationsProvider.razor b/BLAZAMGui/Layouts/UserNotificationsProvider.razor index 58f99542..0a918f17 100644 --- a/BLAZAMGui/Layouts/UserNotificationsProvider.razor +++ b/BLAZAMGui/Layouts/UserNotificationsProvider.razor @@ -32,17 +32,14 @@ if (notifications != null && notifications.Select(n => n.User).Contains(UserState.Preferences)) { - Notifications = await Context.UserNotifications.Where(un => un.User.Id == UserState.Id && !un.IsRead).ToListAsync(); - await InvokeAsync(StateHasChanged); + await LoadNotifications(); } }); NotificationPublisher.OnNotificationDeleted += async () => { - Notifications = await Context.UserNotifications.Where(un => un.User.Id == UserState.Id && !un.IsRead).ToListAsync(); - - InvokeAsync(StateHasChanged); + await LoadNotifications(); }; UserState = CurrentUser.State; @@ -50,9 +47,7 @@ if (UserState != null) UserState.OnSettingsChanged += async () => { - Notifications = await Context.UserNotifications.Where(un => un.User.Id == UserState.Id && !un.IsRead).ToListAsync(); - - InvokeAsync(StateHasChanged); + await LoadNotifications(); }; Notifications = await Context.UserNotifications.Where(un => un.User.Id == UserState.Id && !un.IsRead).ToListAsync(); @@ -72,4 +67,13 @@ // }); } + private async Task LoadNotifications() + { + var context = await DbFactory.CreateDbContextAsync(); + lock (Notifications) + { + Notifications = context.UserNotifications.Where(un => un.User.Id == UserState.Id && !un.IsRead).ToList(); + } + await InvokeAsync(StateHasChanged); + } } \ No newline at end of file diff --git a/BLAZAMGui/UI/Settings/AvailableUpdate.razor b/BLAZAMGui/UI/Settings/AvailableUpdate.razor index 91407a6a..5e48345c 100644 --- a/BLAZAMGui/UI/Settings/AvailableUpdate.razor +++ b/BLAZAMGui/UI/Settings/AvailableUpdate.razor @@ -20,12 +20,22 @@ - @if (Update.Newer && Update.PassesPrerequisiteChecks) + @if ((Update.Newer || ApplicationInfo.InDebugMode) && Update.PassesPrerequisiteChecks) { - Apply Update + + @AppLocalization["Apply Update"] + @if (ApplicationInfo.InDebugMode) { - Test Auto Update + + Test Auto Update + } diff --git a/BLAZAMGui/UI/Settings/ManualApplicationUpdater.razor b/BLAZAMGui/UI/Settings/ManualApplicationUpdater.razor index aa322d7e..23c59125 100644 --- a/BLAZAMGui/UI/Settings/ManualApplicationUpdater.razor +++ b/BLAZAMGui/UI/Settings/ManualApplicationUpdater.razor @@ -63,7 +63,10 @@ default: - + @{ int i = 0; } @@ -76,7 +79,11 @@ - @(ShowAllUpdates == false ? "Show Previous Updates" : "Hide Previous Updates") + + @(ShowAllUpdates == false ? "Show Previous Updates" : "Hide Previous Updates") + @@ -90,7 +97,7 @@ @if (ShowAllUpdates) { - @foreach (var update in UpdateService.AvailableUpdates.Where(x => x.Version<=ApplicationInfo.RunningVersion).OrderBy(x => x.Version)) + @foreach (var update in UpdateService.AvailableUpdates.Where(x => x.Version <= ApplicationInfo.RunningVersion).OrderBy(x => x.Version)) { @@ -100,6 +107,7 @@ } } + @if (UpdateService.NewestAvailableUpdate != null) { if (UpdateService.NewestAvailableUpdate.Version.NewerThan(ApplicationInfo.RunningVersion)) @@ -119,7 +127,7 @@ } } - + @if (UpdateService.IncompatibleUpdates.Count > 0) { var latestIncompatibleUpdate = UpdateService.IncompatibleUpdates.Where(x => x.Newer).OrderByDescending(x => x.Release.ReleaseTime).FirstOrDefault(); diff --git a/BLAZAMGui/UI/Settings/Permissions/EditAccessLevel.razor b/BLAZAMGui/UI/Settings/Permissions/EditAccessLevel.razor index e3081078..cfe36587 100644 --- a/BLAZAMGui/UI/Settings/Permissions/EditAccessLevel.razor +++ b/BLAZAMGui/UI/Settings/Permissions/EditAccessLevel.razor @@ -6,8 +6,9 @@ @if (!Self) { - + } @if (!Self) { @@ -70,20 +71,20 @@ } - - - + + + } - @if (objectMap.ObjectType == ActiveDirectoryObjectType.User - && objectMap.ObjectAccessLevelId != ObjectAccessLevels.Deny.Id - && !Self) + @if (objectMap.ObjectType == ActiveDirectoryObjectType.User + && objectMap.ObjectAccessLevelId != ObjectAccessLevels.Deny.Id + && !Self) { } - + @{ @@ -248,13 +249,20 @@ if (Model.Id > 0) buttonLabel = AppLocalization["Update Access Level"]; } -@buttonLabel +@buttonLabel @if (WorkingModel.Id != 0 && !Self) { - @AppLocalization["Delete Access Level"] - - - + @AppLocalization["Delete Access Level"] + + + } @code { @@ -265,7 +273,7 @@ [Parameter] public bool Self { get; set; } - + AppModal? _deleteModal; bool ShowFields @@ -338,7 +346,7 @@ SnackBarService.Success(WorkingModel.Name + " has been updated"); - if (addition&& !Self) + if (addition && !Self) WorkingModel = new(); await LevelsChanged.InvokeAsync(); diff --git a/BLAZAMUpdate/ApplicationUpdate.cs b/BLAZAMUpdate/ApplicationUpdate.cs index 0d212daf..73b1e824 100644 --- a/BLAZAMUpdate/ApplicationUpdate.cs +++ b/BLAZAMUpdate/ApplicationUpdate.cs @@ -14,6 +14,7 @@ using System.Diagnostics; using System.IO.Compression; using System.Security.Principal; +using System.Text; namespace BLAZAM.Update { @@ -97,7 +98,8 @@ public string UpdateCommandArguments { get { - return "/c start Powershell -ExecutionPolicy Bypass -command \"" + CommandProcessPath + CommandArguments + "\""; + return "/c start Powershell -ExecutionPolicy Bypass -command \"& '" + CommandProcessPath + + "' " + CommandArguments + "\""; } } private SystemFile CommandProcessPath @@ -118,18 +120,21 @@ private string CommandArguments { get { - var creds = _updateService.GetImpersonationUser(); - var args = " -UpdateSourcePath '" + UpdateStagingDirectory + "' -ProcessId " + _runningProcess.Id + " -ApplicationDirectory '" + _applicationRootDirectory + "'"; - if (creds != null) - { - args += " -Username " + creds.Username + - " -Password '" + creds.Password.ToPlainText() + "'"; - if (!creds.FQDN.IsNullOrEmpty()) - { - - args += " -Domain " + creds.FQDN; - } - } + //var creds = _updateService.GetImpersonationUser(); + var args = " -UpdateSourcePath '" + UpdateStagingDirectory + "' -ProcessId " + _runningProcess.Id + " -ApplicationDirectory '" + _applicationRootDirectory; + if (Debugger.IsAttached) + args += "bin\\Debug\\net8.0\\"; + args += "'"; + //if (creds != null) + //{ + // args += " -Username " + creds.Username + + // " -Password '" + creds.Password.ToPlainText() + "'"; + // if (!creds.FQDN.IsNullOrEmpty()) + // { + + // args += " -Domain " + creds.FQDN; + // } + //} return args; } @@ -231,18 +236,31 @@ private async Task InitiateFileCopy(JobStep? step) //All prerequisites met - //Update the updater first Loggers.UpdateLogger?.Debug("Copying updater script"); Loggers.UpdateLogger?.Debug("Source: " + UpdateStagingDirectory + "\\updater\\*"); Loggers.UpdateLogger?.Debug("Dest: " + _applicationRootDirectory + "updater\\"); using var context = await _dbFactory.CreateDbContextAsync(); + var updateCredentials = _updateService.GetUpdateCredentials(); + if (updateCredentials != null) + { + return updateCredentials.Run(() => + { + try + { + return ApplyFiles(); + } + catch (Exception ex) + { + Loggers.UpdateLogger?.Error("Error applying update: {@Error}", ex); - - if (_applicationRootDirectory.Writable) + } + return false; + }); + } + else { - Loggers.UpdateLogger?.Warning("The application user has write permission to the application directory!"); try { return ApplyFiles(); @@ -250,64 +268,69 @@ private async Task InitiateFileCopy(JobStep? step) catch (Exception ex) { Loggers.UpdateLogger?.Error("Error applying update: {@Error}", ex); - throw new ApplicationUpdateException("Error trying to apply update files", ex); - } - return false; - } - else - { - var settings = context.ActiveDirectorySettings.FirstOrDefault(); - - - if (settings == null) throw new ApplicationUpdateException("No credentials are configured for updates"); - - - try - { - var updateCredentials = _updateService.GetUpdateCredentials(); - if (updateCredentials != null) - { - - return updateCredentials.Run(() => - { - try - { - return ApplyFiles(); - } - catch (Exception ex) - { - Loggers.UpdateLogger?.Error("Error applying update: {@Error}", ex); - - } - return false; - }); - } - else - { - try - { - return ApplyFiles(); - } - catch (Exception ex) - { - Loggers.UpdateLogger?.Error("Error applying update: {@Error}", ex); - - } - return false; - } - - - } - catch (ApplicationException ex) - { - Loggers.UpdateLogger?.Error("Unable to apply files {@Error}", ex); - return false; } - - } - + return false; + //switch (_updateService.UpdateCredential) + //{ + + // case UpdateCredential.Application: + // Loggers.UpdateLogger?.Warning("The application user has write permission to the application directory!"); + // try + // { + // return ApplyFiles(); + // } + // catch (Exception ex) + // { + // Loggers.UpdateLogger?.Error("Error applying update: {@Error}", ex); + // throw new ApplicationUpdateException("Error trying to apply update files", ex); + // } + // case UpdateCredential.Active_Directory: + // var adCredentials = context.ActiveDirectorySettings.FirstOrDefault()?.CreateDirectoryAdminImpersonator(); + // if (adCredentials != null) + // { + + // return adCredentials.Run(() => + // { + // try + // { + // return ApplyFiles(); + // } + // catch (Exception ex) + // { + // Loggers.UpdateLogger?.Error("Error applying update: {@Error}", ex); + + // } + // return false; + // }); + // } + // break; + // case UpdateCredential.Update: + // var updateCredentials = _updateService.GetUpdateCredentials(); + // if (updateCredentials != null) + // { + + // return updateCredentials.Run(() => + // { + // try + // { + // return ApplyFiles(); + // } + // catch (Exception ex) + // { + // Loggers.UpdateLogger?.Error("Error applying update: {@Error}", ex); + + // } + // return false; + // }); + // } + // break; + // default: + // case UpdateCredential.None: + // return false; + //} + //return false; } @@ -320,9 +343,15 @@ private bool ApplyFiles() SystemDirectory updaterDirFromStagedUpdate = new SystemDirectory(UpdateStagingDirectory.FullPath + "updater\\"); SystemDirectory updaterDir = new SystemDirectory(_applicationRootDirectory.FullPath + "updater\\"); + + + + + + //Update the updater first updaterDirFromStagedUpdate.CopyTo(updaterDir); - //File.Copy(UpdateStagingDirectory + "\\updater\\", _applicationRootDirectory + "updater\\", true); Loggers.UpdateLogger?.Information("Updater updated"); + //If the updater updated we can run the updater var updaterRan = InvokeUpdateExecutable(); @@ -339,8 +368,9 @@ private bool ApplyFiles() } } - private bool InvokeUpdateExecutable() + private bool InvokeUpdateExecutable_old() { + var startTime = DateTime.Now; var process = new Process { StartInfo = new ProcessStartInfo @@ -355,16 +385,69 @@ private bool InvokeUpdateExecutable() } }; + Loggers.UpdateLogger?.Information("Starting update process"); process.Start(); + Loggers.UpdateLogger?.Information("Update process id: " + process.Id); process.WaitForExit(); + Loggers.UpdateLogger?.Information("Update process exited: " + process.ExitCode); + Loggers.UpdateLogger?.Information("Update process execution time: " + (DateTime.Now - startTime).TotalMilliseconds + "ms"); return true; } + private bool InvokeUpdateExecutable() + { + var startTime = DateTime.Now; + var process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = UpdateCommandProcess, + Arguments = UpdateCommandArguments, + RedirectStandardOutput = true, // Enable output redirection + RedirectStandardError = true, + UseShellExecute = false, // Required for redirection + CreateNoWindow = true, + } + }; + + Loggers.UpdateLogger?.Information("Starting update process"); + process.Start(); + Loggers.UpdateLogger?.Information("Update process id: " + process.Id); + + // Read and log the output asynchronously + var output = new StringBuilder(); + process.OutputDataReceived += (sender, e) => + { + if (!string.IsNullOrEmpty(e.Data)) + { + output.AppendLine(e.Data); + Loggers.UpdateLogger?.Information("Update process output: " + e.Data); + } + }; + process.ErrorDataReceived += (sender, e) => + { + if (!string.IsNullOrEmpty(e.Data)) + { + output.AppendLine(e.Data); + Loggers.UpdateLogger?.Error("Update process error: " + e.Data); // Log as error + } + }; + process.BeginOutputReadLine(); // Start asynchronous reading + process.WaitForExit(); + + Loggers.UpdateLogger?.Information("Update process exited: " + process.ExitCode); + Loggers.UpdateLogger?.Information("Update process execution time: " + (DateTime.Now - startTime).TotalMilliseconds + "ms"); + + // Log the complete output (if needed) + Loggers.UpdateLogger?.Information("Complete update process output:\n" + output.ToString()); + + return true; + } public async Task Backup(JobStep? step) { Loggers.UpdateLogger?.Information("Attempting backup of current version to: " + BackupPath); diff --git a/BLAZAMUpdate/Services/UpdateService.cs b/BLAZAMUpdate/Services/UpdateService.cs index 351103c0..82e5fa9e 100644 --- a/BLAZAMUpdate/Services/UpdateService.cs +++ b/BLAZAMUpdate/Services/UpdateService.cs @@ -288,7 +288,7 @@ public UpdateCredential UpdateCredential { Loggers.UpdateLogger.Information("Checking update credentials"); - if (!Debugger.IsAttached && ApplicationInfo.applicationRoot.Writable) + if (ApplicationInfo.applicationRoot.Writable) return UpdateCredential.Application; //Test Directory Credentials diff --git a/PlaywrightTests/UnitTest1.cs b/PlaywrightTests/UnitTest1.cs index 02cfb9ee..15c7d4a6 100644 --- a/PlaywrightTests/UnitTest1.cs +++ b/PlaywrightTests/UnitTest1.cs @@ -24,14 +24,6 @@ public async Task UserMenuTest() await OpenProfileSettings(); await CloseDialog(); - await OpenUserMenu(); - await OpenNotificationSettings(); - await CloseDialog(); - - await OpenRecycleBin(); - - await OpenConfigureSubMenu(); - // Expects the URL to contain intro. //await Expect(Page).ToHaveURLAsync(new Regex(".*home"));