From d768b243e63dae522ad42be345bf5c2b1296560e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 10:39:41 +0000 Subject: [PATCH 01/30] Bump MailKit from 4.6.0 to 4.7.1.1 Bumps [MailKit](https://github.com/jstedfast/MailKit) from 4.6.0 to 4.7.1.1. - [Changelog](https://github.com/jstedfast/MailKit/blob/master/ReleaseNotes.md) - [Commits](https://github.com/jstedfast/MailKit/compare/4.6.0...4.7.1.1) --- updated-dependencies: - dependency-name: MailKit dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- BLAZAM/BLAZAM.csproj | 2 +- BLAZAMEmail/BLAZAMEmail.csproj | 2 +- BLAZAMServices/BLAZAMServices.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/BLAZAM/BLAZAM.csproj b/BLAZAM/BLAZAM.csproj index 11c7bbf9..d5dc01de 100644 --- a/BLAZAM/BLAZAM.csproj +++ b/BLAZAM/BLAZAM.csproj @@ -57,7 +57,7 @@ - + diff --git a/BLAZAMEmail/BLAZAMEmail.csproj b/BLAZAMEmail/BLAZAMEmail.csproj index 2197dd71..8366bd8f 100644 --- a/BLAZAMEmail/BLAZAMEmail.csproj +++ b/BLAZAMEmail/BLAZAMEmail.csproj @@ -9,7 +9,7 @@ - + diff --git a/BLAZAMServices/BLAZAMServices.csproj b/BLAZAMServices/BLAZAMServices.csproj index 19291ced..1c02493a 100644 --- a/BLAZAMServices/BLAZAMServices.csproj +++ b/BLAZAMServices/BLAZAMServices.csproj @@ -9,7 +9,7 @@ - + From a85daae2b35f6308c1abb68a8777be714590650c Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Tue, 23 Jul 2024 14:14:10 -0400 Subject: [PATCH 02/30] Bump Microsoft.AspNetCore.Identity.UI from 6.0.30 to 6.0.32 --- BLAZAM/BLAZAM.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BLAZAM/BLAZAM.csproj b/BLAZAM/BLAZAM.csproj index dcde2638..a47f4271 100644 --- a/BLAZAM/BLAZAM.csproj +++ b/BLAZAM/BLAZAM.csproj @@ -59,7 +59,7 @@ - + From 4424f357a9b5846876172e994b922581d173fc2a Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Tue, 23 Jul 2024 14:15:04 -0400 Subject: [PATCH 03/30] Bump Microsoft.VisualStudio.Web.CodeGeneration.Design from 6.0.16 to 6.0.17 --- BLAZAM/BLAZAM.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BLAZAM/BLAZAM.csproj b/BLAZAM/BLAZAM.csproj index a47f4271..32343efa 100644 --- a/BLAZAM/BLAZAM.csproj +++ b/BLAZAM/BLAZAM.csproj @@ -77,7 +77,7 @@ - + From 785779487abf74f7cf3ecfbf8a926df77ea153fa Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Tue, 23 Jul 2024 14:16:38 -0400 Subject: [PATCH 04/30] Bump Microsoft.Playwright.NUnit from 1.44.0 to 1.45.1 --- PlaywrightTests/PlaywrightTests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlaywrightTests/PlaywrightTests.csproj b/PlaywrightTests/PlaywrightTests.csproj index 75b48e6a..0518ae38 100644 --- a/PlaywrightTests/PlaywrightTests.csproj +++ b/PlaywrightTests/PlaywrightTests.csproj @@ -17,7 +17,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive From e759797ba019b82e69119b3eacc3de4b4bc3305c Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Tue, 23 Jul 2024 14:27:43 -0400 Subject: [PATCH 05/30] Update all other dependencies --- BLAZAM.Tests/BLAZAM.Tests.csproj | 4 ++-- BLAZAM/BLAZAM.csproj | 12 ++++++------ BLAZAMCommon.Tests/BLAZAMCommon.Tests.csproj | 4 ++-- BLAZAMCommon/BLAZAMCommon.csproj | 4 ++-- BLAZAMDatabase/BLAZAMDatabase.csproj | 2 +- BLAZAMEmailMessage/BLAZAMEmailMessage.csproj | 4 ++-- BLAZAMGui/BLAZAMGui.csproj | 6 +++--- BLAZAMLoggers/BLAZAMLogger.csproj | 4 ++-- BlazamUpdate/BLAZAMUpdate.csproj | 2 +- 9 files changed, 21 insertions(+), 21 deletions(-) diff --git a/BLAZAM.Tests/BLAZAM.Tests.csproj b/BLAZAM.Tests/BLAZAM.Tests.csproj index 08426028..86d716a5 100644 --- a/BLAZAM.Tests/BLAZAM.Tests.csproj +++ b/BLAZAM.Tests/BLAZAM.Tests.csproj @@ -10,8 +10,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/BLAZAM/BLAZAM.csproj b/BLAZAM/BLAZAM.csproj index 32343efa..b5c4d01d 100644 --- a/BLAZAM/BLAZAM.csproj +++ b/BLAZAM/BLAZAM.csproj @@ -60,9 +60,9 @@ - - - + + + @@ -75,16 +75,16 @@ - + - + - + diff --git a/BLAZAMCommon.Tests/BLAZAMCommon.Tests.csproj b/BLAZAMCommon.Tests/BLAZAMCommon.Tests.csproj index 6bbe6bfe..0a8f41bf 100644 --- a/BLAZAMCommon.Tests/BLAZAMCommon.Tests.csproj +++ b/BLAZAMCommon.Tests/BLAZAMCommon.Tests.csproj @@ -16,8 +16,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/BLAZAMCommon/BLAZAMCommon.csproj b/BLAZAMCommon/BLAZAMCommon.csproj index 8c1d33f6..ef1c3db0 100644 --- a/BLAZAMCommon/BLAZAMCommon.csproj +++ b/BLAZAMCommon/BLAZAMCommon.csproj @@ -20,7 +20,7 @@ - + @@ -33,7 +33,7 @@ - + diff --git a/BLAZAMDatabase/BLAZAMDatabase.csproj b/BLAZAMDatabase/BLAZAMDatabase.csproj index 5663a9ab..4d35f064 100644 --- a/BLAZAMDatabase/BLAZAMDatabase.csproj +++ b/BLAZAMDatabase/BLAZAMDatabase.csproj @@ -18,7 +18,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/BLAZAMEmailMessage/BLAZAMEmailMessage.csproj b/BLAZAMEmailMessage/BLAZAMEmailMessage.csproj index bafe9f20..e6af1ffa 100644 --- a/BLAZAMEmailMessage/BLAZAMEmailMessage.csproj +++ b/BLAZAMEmailMessage/BLAZAMEmailMessage.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -13,7 +13,7 @@ - + diff --git a/BLAZAMGui/BLAZAMGui.csproj b/BLAZAMGui/BLAZAMGui.csproj index e135ad9a..ed4643a2 100644 --- a/BLAZAMGui/BLAZAMGui.csproj +++ b/BLAZAMGui/BLAZAMGui.csproj @@ -24,13 +24,13 @@ - + - + - + diff --git a/BLAZAMLoggers/BLAZAMLogger.csproj b/BLAZAMLoggers/BLAZAMLogger.csproj index b7fa8f9c..475406fc 100644 --- a/BLAZAMLoggers/BLAZAMLogger.csproj +++ b/BLAZAMLoggers/BLAZAMLogger.csproj @@ -9,9 +9,9 @@ - + - + diff --git a/BlazamUpdate/BLAZAMUpdate.csproj b/BlazamUpdate/BLAZAMUpdate.csproj index 069c8553..111a5779 100644 --- a/BlazamUpdate/BLAZAMUpdate.csproj +++ b/BlazamUpdate/BLAZAMUpdate.csproj @@ -10,7 +10,7 @@ - + From 75e9100e9af86f948d59420ed447d9c791ac2c91 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Tue, 23 Jul 2024 14:29:50 -0400 Subject: [PATCH 06/30] Update Octokit --- BLAZAM/BLAZAM.csproj | 4 ++-- BLAZAMUpdate/BLAZAMUpdate.csproj | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/BLAZAM/BLAZAM.csproj b/BLAZAM/BLAZAM.csproj index b5c4d01d..50d9e8bc 100644 --- a/BLAZAM/BLAZAM.csproj +++ b/BLAZAM/BLAZAM.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -6,7 +6,7 @@ enable false 0.9.4 - 2024.07.23.0006 + 2024.07.23.1828 false BLAZAM False diff --git a/BLAZAMUpdate/BLAZAMUpdate.csproj b/BLAZAMUpdate/BLAZAMUpdate.csproj index 069c8553..111a5779 100644 --- a/BLAZAMUpdate/BLAZAMUpdate.csproj +++ b/BLAZAMUpdate/BLAZAMUpdate.csproj @@ -10,7 +10,7 @@ - + From 8a2d4897b34b0ac44ec36b6f96b9cb89a74d94d6 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Tue, 23 Jul 2024 14:35:54 -0400 Subject: [PATCH 07/30] Remove redundant group post creation triggers --- BLAZAM/Pages/Groups/ConfirmNewGroup.razor | 4 ++++ BLAZAM/Pages/Groups/CreateGroup.razor | 9 +-------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/BLAZAM/Pages/Groups/ConfirmNewGroup.razor b/BLAZAM/Pages/Groups/ConfirmNewGroup.razor index 8bdc049a..01839885 100644 --- a/BLAZAM/Pages/Groups/ConfirmNewGroup.razor +++ b/BLAZAM/Pages/Groups/ConfirmNewGroup.razor @@ -1,4 +1,6 @@ @inherits AppComponentBase +@inject OUNotificationService OUNotificationService + Confirm Group Creation @if (Group != null) @@ -41,6 +43,8 @@ } await AuditLogger.Group.Created(Group); + _ = OUNotificationService.PostAsync(Group, NotificationType.Create); + var commitJob = Group.CommitChanges(); await Confirmed.InvokeAsync(Group); } diff --git a/BLAZAM/Pages/Groups/CreateGroup.razor b/BLAZAM/Pages/Groups/CreateGroup.razor index 245f7242..9c017f3f 100644 --- a/BLAZAM/Pages/Groups/CreateGroup.razor +++ b/BLAZAM/Pages/Groups/CreateGroup.razor @@ -1,7 +1,6 @@ @page "/groups/create" @inherits TabbedAppComponentBase @attribute [Authorize] -@inject OUNotificationService OUNotificationService Create Group @@ -54,7 +53,7 @@ - + @@ -121,10 +120,4 @@ await InvokeAsync(StateHasChanged); } - async Task GroupCreated(IADGroup ou) - { - await AuditLogger.Group.Created(ou); - _ = OUNotificationService.PostAsync(ou, NotificationType.Create); - - } } From b22c88678f7ee2a623cc00d092f50824708d9823 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Tue, 23 Jul 2024 16:52:00 -0400 Subject: [PATCH 08/30] Fix for first OU not being alphabetical in tree views #386 --- BLAZAMActiveDirectory/Helpers/ActiveDirectoryHelpers.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BLAZAMActiveDirectory/Helpers/ActiveDirectoryHelpers.cs b/BLAZAMActiveDirectory/Helpers/ActiveDirectoryHelpers.cs index cd7dd547..21f49fe1 100644 --- a/BLAZAMActiveDirectory/Helpers/ActiveDirectoryHelpers.cs +++ b/BLAZAMActiveDirectory/Helpers/ActiveDirectoryHelpers.cs @@ -43,7 +43,7 @@ public static IEnumerable MoveToTop(this IEnumerable mathingItems=new List(); - for (int x =1; x < list.Count(); x++) + for (int x =0; x < list.Count(); x++) { if (matchingPredicate.Invoke(list[x])) From a187fc3e0c996338430d5134a797c6a3ada2f7f5 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Tue, 23 Jul 2024 16:54:05 -0400 Subject: [PATCH 09/30] Unused code from another project --- .../Helpers/ActiveDirectoryHelpers.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/BLAZAMActiveDirectory/Helpers/ActiveDirectoryHelpers.cs b/BLAZAMActiveDirectory/Helpers/ActiveDirectoryHelpers.cs index 21f49fe1..6a5df47b 100644 --- a/BLAZAMActiveDirectory/Helpers/ActiveDirectoryHelpers.cs +++ b/BLAZAMActiveDirectory/Helpers/ActiveDirectoryHelpers.cs @@ -63,15 +63,7 @@ public static IEnumerable MoveToTop(this IEnumerable Date: Tue, 23 Jul 2024 16:55:56 -0400 Subject: [PATCH 10/30] Move OU create audit and notification triggers --- BLAZAM/Pages/OU/ConfirmNewOU.razor | 4 ++++ BLAZAM/Pages/OU/CreateOU.razor | 8 +------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/BLAZAM/Pages/OU/ConfirmNewOU.razor b/BLAZAM/Pages/OU/ConfirmNewOU.razor index 6b436a8a..59de0d9d 100644 --- a/BLAZAM/Pages/OU/ConfirmNewOU.razor +++ b/BLAZAM/Pages/OU/ConfirmNewOU.razor @@ -1,4 +1,6 @@ @inherits AppComponentBase +@inject OUNotificationService OUNotificationService + Confirm OU Creation @if (OU != null) @@ -27,6 +29,8 @@ { await OU.CommitChangesAsync(); SnackBarService.Success("OU created"); + await AuditLogger.OU.Created(OU); + _ = OUNotificationService.PostAsync(OU, NotificationType.Create); await Confirmed.InvokeAsync(OU); Nav.NavigateTo("/ou/create",true); } diff --git a/BLAZAM/Pages/OU/CreateOU.razor b/BLAZAM/Pages/OU/CreateOU.razor index f560aac8..2917594e 100644 --- a/BLAZAM/Pages/OU/CreateOU.razor +++ b/BLAZAM/Pages/OU/CreateOU.razor @@ -1,7 +1,6 @@ @page "/ou/create" @inherits TabbedAppComponentBase @attribute [Authorize] -@inject OUNotificationService OUNotificationService Create OU @@ -37,7 +36,7 @@ - + @@ -118,10 +117,5 @@ await InvokeAsync(StateHasChanged); } - async Task OUCreated(IADOrganizationalUnit ou) - { - await AuditLogger.OU.Created(ou); - _ = OUNotificationService.PostAsync(ou, NotificationType.Create); - } } From e0dcb22915935a0f94ba9f9cd74052a29c9148e5 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Tue, 23 Jul 2024 19:08:48 -0400 Subject: [PATCH 11/30] Detect group changes for notifications --- BLAZAM/Pages/Users/ViewUser.razor | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/BLAZAM/Pages/Users/ViewUser.razor b/BLAZAM/Pages/Users/ViewUser.razor index 21741fc5..a90ec1d6 100644 --- a/BLAZAM/Pages/Users/ViewUser.razor +++ b/BLAZAM/Pages/Users/ViewUser.razor @@ -546,6 +546,7 @@ await RefreshEntryComponents(); try { + var changes = User.Changes; var jobResults = await User.CommitChangesAsync(); if (jobResults.Result == JobResult.Passed) @@ -553,8 +554,12 @@ await AuditLogger.User.Changed(User, changes); - if((changes.Count==1 && changes.First().Field==ActiveDirectoryFields.MemberOf.FieldName)==false) + if(changes.Any(c=>c.Field!=ActiveDirectoryFields.MemberOf.FieldName)) _ = OUNotificationService.PostAsync(User, NotificationType.Modify); + else + { + + } EditMode = false; Nav.WarnOnNavigation = false; SnackBarService.Success("The changes made to this user have been saved."); From dae1f90a1dc0c51630d805da1e80689d8e67ebc9 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Wed, 24 Jul 2024 17:03:41 -0400 Subject: [PATCH 12/30] Remove assign and unassign from User and Computer appropriate Object Actions --- BLAZAMDatabase/Models/Permissions/ObjectAction.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/BLAZAMDatabase/Models/Permissions/ObjectAction.cs b/BLAZAMDatabase/Models/Permissions/ObjectAction.cs index b655024b..fc4cd627 100644 --- a/BLAZAMDatabase/Models/Permissions/ObjectAction.cs +++ b/BLAZAMDatabase/Models/Permissions/ObjectAction.cs @@ -26,15 +26,14 @@ public bool IsActionAppropriateForObject(ActiveDirectoryObjectType type) switch (type) { case ActiveDirectoryObjectType.User: - return true; case ActiveDirectoryObjectType.Computer: switch (Name) { + case "Lock": + case "Unlock": case "Move": case "Delete": case "Create": - case "UnAssign": - case "Assign": case "Enable": case "Disable": case "Rename": From a1608808b48f6f1a896f3a914aae6780cd31dea4 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Wed, 24 Jul 2024 17:12:47 -0400 Subject: [PATCH 13/30] Add printer object actions --- BLAZAMDatabase/Models/Permissions/ObjectAction.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/BLAZAMDatabase/Models/Permissions/ObjectAction.cs b/BLAZAMDatabase/Models/Permissions/ObjectAction.cs index fc4cd627..4facce31 100644 --- a/BLAZAMDatabase/Models/Permissions/ObjectAction.cs +++ b/BLAZAMDatabase/Models/Permissions/ObjectAction.cs @@ -54,6 +54,7 @@ public bool IsActionAppropriateForObject(ActiveDirectoryObjectType type) default: return false; } + case ActiveDirectoryObjectType.Printer: case ActiveDirectoryObjectType.OU: switch (Name) { @@ -65,7 +66,7 @@ public bool IsActionAppropriateForObject(ActiveDirectoryObjectType type) default: return false; } - + default: return false; } From c79f61c0e108a2e30b843bc3e78679c2c23bd267 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Wed, 24 Jul 2024 17:13:10 -0400 Subject: [PATCH 14/30] Add Bitlock delete object action --- BLAZAMDatabase/Models/Permissions/ObjectAction.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/BLAZAMDatabase/Models/Permissions/ObjectAction.cs b/BLAZAMDatabase/Models/Permissions/ObjectAction.cs index 4facce31..31779f4b 100644 --- a/BLAZAMDatabase/Models/Permissions/ObjectAction.cs +++ b/BLAZAMDatabase/Models/Permissions/ObjectAction.cs @@ -66,7 +66,15 @@ public bool IsActionAppropriateForObject(ActiveDirectoryObjectType type) default: return false; } - + case ActiveDirectoryObjectType.BitLocker: + switch (Name) + { + case "Delete": + return true; + default: + return false; + } + default: return false; } From 651a51c135b3042b63ae129f1bcc7ffbed374df1 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Wed, 24 Jul 2024 18:38:00 -0400 Subject: [PATCH 15/30] Security update against potential DOS --- BLAZAMCommon/BLAZAMCommon.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BLAZAMCommon/BLAZAMCommon.csproj b/BLAZAMCommon/BLAZAMCommon.csproj index 8c1d33f6..c5ae69ca 100644 --- a/BLAZAMCommon/BLAZAMCommon.csproj +++ b/BLAZAMCommon/BLAZAMCommon.csproj @@ -33,7 +33,7 @@ - + From 12348d12d57b4146b18f1f5edaf8a430464bccbe Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Fri, 26 Jul 2024 19:15:51 -0400 Subject: [PATCH 16/30] Implement Email Notifications --- BLAZAM/GlobalUsings.cs | 3 +- .../Pages/Error/UnhandledExceptionPage.razor | 1 - BLAZAM/ProgramHelpers.cs | 12 --- .../BLAZAMActiveDirectory.csproj | 1 + BLAZAMDatabase/Context/DatabaseContextBase.cs | 3 - .../Notifications/NotificationSubscription.cs | 5 -- BLAZAMEmail/BLAZAMEmail.csproj | 4 + .../EntryCreatedEmailMessage.razor | 28 ++++++ .../EntryDeletedEmailMessage.razor | 28 ++++++ .../EntryEditedEmailMessage.razor | 28 ++++++ .../EntryGroupAssignmentEmailMessage.razor | 28 ++++++ BLAZAMGui/UI/AppComponentBase.razor.cs | 10 +-- BLAZAMGui/UI/AppModalContentBase.razor | 3 +- .../Settings/ManualApplicationUpdater.razor | 1 - BLAZAMJobs/BLAZAMJobs.csproj | 5 ++ BLAZAMJobs/Job.cs | 5 +- .../NotificationTypeExtentions.cs | 18 ++-- BLAZAMServices/BLAZAMServices.csproj | 1 + .../Background}/EmailService.cs | 30 ++++--- .../Background/OUNotificationService.cs | 46 +++++++--- BLAZAMSession/ApplicationUserState.cs | 12 +-- BLAZAMSession/ApplicationUserStateService.cs | 8 +- BLAZAMSession/BLAZAMSession.csproj | 1 - BLAZAMUpdate/ApplicationUpdate.cs | 11 ++- BLAZAMUpdate/Services/UpdateService.cs | 86 +++++-------------- 25 files changed, 230 insertions(+), 148 deletions(-) create mode 100644 BLAZAMEmailMessage/Email/Notifications/EntryCreatedEmailMessage.razor create mode 100644 BLAZAMEmailMessage/Email/Notifications/EntryDeletedEmailMessage.razor create mode 100644 BLAZAMEmailMessage/Email/Notifications/EntryEditedEmailMessage.razor create mode 100644 BLAZAMEmailMessage/Email/Notifications/EntryGroupAssignmentEmailMessage.razor rename {BLAZAMEmail/Services => BLAZAMServices/Background}/EmailService.cs (92%) diff --git a/BLAZAM/GlobalUsings.cs b/BLAZAM/GlobalUsings.cs index 7079d615..f292a6c8 100644 --- a/BLAZAM/GlobalUsings.cs +++ b/BLAZAM/GlobalUsings.cs @@ -1,5 +1,6 @@ global using BLAZAM.Logger; global using BLAZAM.FileSystem; global using BLAZAM.Helpers; -global using BLAZAM.Common.Exceptions; +global using BLAZAM.Services.Background; + diff --git a/BLAZAM/Pages/Error/UnhandledExceptionPage.razor b/BLAZAM/Pages/Error/UnhandledExceptionPage.razor index c4fb7dc9..52ca979d 100644 --- a/BLAZAM/Pages/Error/UnhandledExceptionPage.razor +++ b/BLAZAM/Pages/Error/UnhandledExceptionPage.razor @@ -1,4 +1,3 @@ -@using BLAZAM.Email.Services; @inject EmailService email @inject ApplicationInfo ApplicationInfo @inject IAppDatabaseFactory factory diff --git a/BLAZAM/ProgramHelpers.cs b/BLAZAM/ProgramHelpers.cs index 384bdc39..7a2f7b7d 100644 --- a/BLAZAM/ProgramHelpers.cs +++ b/BLAZAM/ProgramHelpers.cs @@ -1,34 +1,22 @@  using BLAZAM.Common.Data.Services; using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Localization; using MudBlazor.Services; using System.Globalization; using MudBlazor; -using BLAZAM.Server.Data; -using BLAZAM.Update.Services; -using BLAZAM.Update; using BLAZAM.Database.Context; -using BLAZAM.ActiveDirectory.Interfaces; -using BLAZAM.ActiveDirectory; using BLAZAM.Session.Interfaces; using BLAZAM.Notifications.Services; using BLAZAM.Common.Data; -using BLAZAM.Services.Background; -using BLAZAM.Email.Services; using BLAZAM.Services; using BLAZAM.Services.Duo; -using BLAZAM.Server.Data.Services; using System.Diagnostics; using System.Reflection; using BLAZAM.Services.Chat; using BLAZAM.Services.Audit; -using BLAZAM.Common; using BLAZAM.Nav; using BLAZAM.Session; using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Mvc.RazorPages; -using Org.BouncyCastle.Ocsp; using System.Management; namespace BLAZAM.Server diff --git a/BLAZAMActiveDirectory/BLAZAMActiveDirectory.csproj b/BLAZAMActiveDirectory/BLAZAMActiveDirectory.csproj index 30c6322c..5d630802 100644 --- a/BLAZAMActiveDirectory/BLAZAMActiveDirectory.csproj +++ b/BLAZAMActiveDirectory/BLAZAMActiveDirectory.csproj @@ -15,6 +15,7 @@ + diff --git a/BLAZAMDatabase/Context/DatabaseContextBase.cs b/BLAZAMDatabase/Context/DatabaseContextBase.cs index d4323bb1..f0fcbe1a 100644 --- a/BLAZAMDatabase/Context/DatabaseContextBase.cs +++ b/BLAZAMDatabase/Context/DatabaseContextBase.cs @@ -11,15 +11,12 @@ using BLAZAM.Logger; using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.Configuration; using BLAZAM.Database.Models.Chat; using BLAZAM.Server.Data; -using Microsoft.IdentityModel.Tokens; using System.Data; using BLAZAM.FileSystem; -using Microsoft.EntityFrameworkCore.ChangeTracking; using BLAZAM.Database.Models.Notifications; namespace BLAZAM.Database.Context diff --git a/BLAZAMDatabase/Models/Notifications/NotificationSubscription.cs b/BLAZAMDatabase/Models/Notifications/NotificationSubscription.cs index 4def18ee..e699b4a3 100644 --- a/BLAZAMDatabase/Models/Notifications/NotificationSubscription.cs +++ b/BLAZAMDatabase/Models/Notifications/NotificationSubscription.cs @@ -1,9 +1,4 @@ using BLAZAM.Database.Models.User; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace BLAZAM.Database.Models.Notifications { diff --git a/BLAZAMEmail/BLAZAMEmail.csproj b/BLAZAMEmail/BLAZAMEmail.csproj index 2197dd71..a517d824 100644 --- a/BLAZAMEmail/BLAZAMEmail.csproj +++ b/BLAZAMEmail/BLAZAMEmail.csproj @@ -18,4 +18,8 @@ + + + + diff --git a/BLAZAMEmailMessage/Email/Notifications/EntryCreatedEmailMessage.razor b/BLAZAMEmailMessage/Email/Notifications/EntryCreatedEmailMessage.razor new file mode 100644 index 00000000..9abc47db --- /dev/null +++ b/BLAZAMEmailMessage/Email/Notifications/EntryCreatedEmailMessage.razor @@ -0,0 +1,28 @@ +@using BLAZAM.Helpers +@using System.Security +@inherits NotificationTemplateComponent + + + @AppLocalization["Active Directory object created"] + + + + EntryName + AppLocalization[" has been created."]) +
+ + +
+ + +@code{ + [Parameter] + public string EntryName { get; set; } + + public override string Render() => new ComponentRenderer() + .UseLayout() + .AddServiceProvider(ApplicationInfo.services) + .Set(c => c.EntryName, EntryName).Render(); +} + + + diff --git a/BLAZAMEmailMessage/Email/Notifications/EntryDeletedEmailMessage.razor b/BLAZAMEmailMessage/Email/Notifications/EntryDeletedEmailMessage.razor new file mode 100644 index 00000000..ef094124 --- /dev/null +++ b/BLAZAMEmailMessage/Email/Notifications/EntryDeletedEmailMessage.razor @@ -0,0 +1,28 @@ +@using BLAZAM.Helpers +@using System.Security +@inherits NotificationTemplateComponent + + + @AppLocalization["Object deleted"] + + + + @( EntryName + AppLocalization[" has been deltted."]) +
+ + +
+ + +@code{ + [Parameter] + public string EntryName { get; set; } + + public override string Render() => new ComponentRenderer() + .UseLayout() + .AddServiceProvider(ApplicationInfo.services) + .Set(c => c.EntryName, EntryName).Render(); +} + + + diff --git a/BLAZAMEmailMessage/Email/Notifications/EntryEditedEmailMessage.razor b/BLAZAMEmailMessage/Email/Notifications/EntryEditedEmailMessage.razor new file mode 100644 index 00000000..8ca483dd --- /dev/null +++ b/BLAZAMEmailMessage/Email/Notifications/EntryEditedEmailMessage.razor @@ -0,0 +1,28 @@ +@using BLAZAM.Helpers +@using System.Security +@inherits NotificationTemplateComponent + + + @AppLocalization["Entry modified"] + + + + @(EntryName + AppLocalization[" has been modified."]) +
+ + +
+ + +@code{ + [Parameter] + public string EntryName { get; set; } + + public override string Render() => new ComponentRenderer() + .UseLayout() + .AddServiceProvider(ApplicationInfo.services) + .Set(c => c.EntryName, EntryName).Render(); +} + + + diff --git a/BLAZAMEmailMessage/Email/Notifications/EntryGroupAssignmentEmailMessage.razor b/BLAZAMEmailMessage/Email/Notifications/EntryGroupAssignmentEmailMessage.razor new file mode 100644 index 00000000..ee922d5f --- /dev/null +++ b/BLAZAMEmailMessage/Email/Notifications/EntryGroupAssignmentEmailMessage.razor @@ -0,0 +1,28 @@ +@using BLAZAM.Helpers +@using System.Security +@inherits NotificationTemplateComponent + + + @AppLocalization["Group membership changed"] + + + + @(AppLocalization["he password for "] + EntryName + AppLocalization[" has been changed."]) +
+ + +
+ + +@code{ + [Parameter] + public string EntryName { get; set; } + + public override string Render() => new ComponentRenderer() + .UseLayout() + .AddServiceProvider(ApplicationInfo.services) + .Set(c => c.EntryName, EntryName).Render(); +} + + + diff --git a/BLAZAMGui/UI/AppComponentBase.razor.cs b/BLAZAMGui/UI/AppComponentBase.razor.cs index 55ec62a9..e1f08866 100644 --- a/BLAZAMGui/UI/AppComponentBase.razor.cs +++ b/BLAZAMGui/UI/AppComponentBase.razor.cs @@ -1,9 +1,7 @@ using BLAZAM.ActiveDirectory; -using BLAZAM.Email.Services; using BLAZAM.Services.Audit; using BLAZAM.Services.Chat; -using BLAZAM.Common; using BLAZAM.Nav; namespace BLAZAM.Gui.UI @@ -44,8 +42,7 @@ public class AppComponentBase : ComponentBase,IDisposable [Inject] public ICurrentUserStateService CurrentUser { get; set; } - // protected IApplicationUserState? CurrentUser => UserStateService.CurrentUserState; - + [Inject] protected AuditLogger AuditLogger { get; set; } @@ -85,7 +82,6 @@ public class AppComponentBase : ComponentBase,IDisposable protected override void OnInitialized() { base.OnInitialized(); - //Nav = new AppNavigationManager(BaseNav); try { Context = DbFactory.CreateDbContext(); @@ -151,9 +147,7 @@ protected void Refresh(bool forceReload = false) public virtual void Dispose() { - //Remove for issue #235, Dependency Injection automatically - //disposes of objects after they are no longer needed. - //Context?.Dispose(); + //This object requires no further disposal } public async Task CopyToClipboard(string? text) diff --git a/BLAZAMGui/UI/AppModalContentBase.razor b/BLAZAMGui/UI/AppModalContentBase.razor index ac3755ef..bc2027f1 100644 --- a/BLAZAMGui/UI/AppModalContentBase.razor +++ b/BLAZAMGui/UI/AppModalContentBase.razor @@ -1,5 +1,4 @@ -@using BLAZAM.Email.Services; -@using BLAZAM.Services.Chat; +@using BLAZAM.Services.Chat; @code { diff --git a/BLAZAMGui/UI/Settings/ManualApplicationUpdater.razor b/BLAZAMGui/UI/Settings/ManualApplicationUpdater.razor index 68ba1148..4e786d44 100644 --- a/BLAZAMGui/UI/Settings/ManualApplicationUpdater.razor +++ b/BLAZAMGui/UI/Settings/ManualApplicationUpdater.razor @@ -186,7 +186,6 @@ { MessageService.ShowMessage(output.ToDialogParameters(), AppLocalization["Update"]); await output.RunAsync(); - // SnackBarService.Success("Update started successfully. The web application will restart and update momentarily."); } await InvokeAsync(StateHasChanged); diff --git a/BLAZAMJobs/BLAZAMJobs.csproj b/BLAZAMJobs/BLAZAMJobs.csproj index e0a6bcc6..0981eca5 100644 --- a/BLAZAMJobs/BLAZAMJobs.csproj +++ b/BLAZAMJobs/BLAZAMJobs.csproj @@ -7,6 +7,11 @@ BLAZAM.Jobs + + + + + diff --git a/BLAZAMJobs/Job.cs b/BLAZAMJobs/Job.cs index fb03d411..42e2d2f2 100644 --- a/BLAZAMJobs/Job.cs +++ b/BLAZAMJobs/Job.cs @@ -1,7 +1,4 @@ -using BLAZAM.Common.Data; -using BLAZAM.Database.Models.User; -using BLAZAM.Session.Interfaces; -using Microsoft.AspNetCore.Components; + namespace BLAZAM.Jobs { diff --git a/BLAZAMNotifications/Notifications/NotificationTypeExtentions.cs b/BLAZAMNotifications/Notifications/NotificationTypeExtentions.cs index 975e4efb..87e21875 100644 --- a/BLAZAMNotifications/Notifications/NotificationTypeExtentions.cs +++ b/BLAZAMNotifications/Notifications/NotificationTypeExtentions.cs @@ -1,9 +1,4 @@ using BLAZAM.Database.Models.Notifications; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace BLAZAM.Notifications.Notifications { @@ -17,6 +12,19 @@ public static class NotificationTypeExtentions case NotificationType.PasswordChange: notificationTemplate = new PasswordChangedEmailMessage(); break; + case NotificationType.Create: + notificationTemplate = new EntryCreatedEmailMessage(); + break; + case NotificationType.Delete: + notificationTemplate = new EntryDeletedEmailMessage(); + break; + case NotificationType.Modify: + notificationTemplate = new EntryEditedEmailMessage(); + break; + case NotificationType.GroupAssignment: + notificationTemplate = new EntryGroupAssignmentEmailMessage(); + break; + } if(notificationTemplate != null) { diff --git a/BLAZAMServices/BLAZAMServices.csproj b/BLAZAMServices/BLAZAMServices.csproj index 19291ced..168cc399 100644 --- a/BLAZAMServices/BLAZAMServices.csproj +++ b/BLAZAMServices/BLAZAMServices.csproj @@ -12,6 +12,7 @@ + diff --git a/BLAZAMEmail/Services/EmailService.cs b/BLAZAMServices/Background/EmailService.cs similarity index 92% rename from BLAZAMEmail/Services/EmailService.cs rename to BLAZAMServices/Background/EmailService.cs index 164ff8f4..799a5bc1 100644 --- a/BLAZAMEmail/Services/EmailService.cs +++ b/BLAZAMServices/Background/EmailService.cs @@ -5,28 +5,37 @@ using MailKit.Security; using Microsoft.AspNetCore.Components; using MimeKit; -using MimeKit.Text; using MimeKit.Utils; using BLAZAM.Database.Models; using BLAZAM.Database.Context; using BLAZAM.Helpers; using BLAZAM.Common.Exceptions; -using BLAZAM.Logger; using BLAZAM.EmailMessage; using BLAZAM.EmailMessage.Email; using BLAZAM.Common.Data; using BLAZAM.Static; -using PreMailer.Net; using BLAZAM.FileSystem; using BLAZAM.EmailMessage.Email.Base; -namespace BLAZAM.Email.Services +namespace BLAZAM.Services.Background { public class EmailService { public static EmailService? Instance { get; set; } private IAppDatabaseFactory Factory { get; set; } + public bool IsConfigured + { + get + { + EmailSettings? settings = GetSettings(); + if (settings != null && settings.Valid()) + { + return true; + } + return false; + } + } public EmailService(IAppDatabaseFactory factory) { @@ -48,7 +57,7 @@ public EmailService(IAppDatabaseFactory factory) /// renders it, and returns the raw HTML /// /// - /// The provided can not have any Blazorise components, only base Blazor + /// The provided can use basic MudBlazor components and Blazor components /// /// /// @@ -122,9 +131,10 @@ private MimeMessage BuildMessage(string subject, string to, string body, string? { var email = new MimeMessage(); - EmailSettings? settings = GetSettings(); - if (settings != null && settings.Valid()) + if (IsConfigured) { + EmailSettings? settings = GetSettings(); + if (settings.UseSMTPAuth && settings.FromAddress.IsNullOrEmpty()) email.From.Add(MailboxAddress.Parse(settings.SMTPUsername)); else email.From.Add(MailboxAddress.Parse(settings.FromAddress)); @@ -165,7 +175,7 @@ public string PrepareHTMLForEmail(string body) { SystemFile css = new SystemFile(ApplicationInfo.applicationRoot + "\\wwwroot\\lib\\mudblazor\\css\\mudblazor.min.css"); var preMailer = new PreMailer.Net.PreMailer(body); - body = preMailer.MoveCssInline(stripIdAndClassAttributes: true,css:css.ReadAllText()).Html; + body = preMailer.MoveCssInline(stripIdAndClassAttributes: true, css: css.ReadAllText()).Html; return body; } @@ -220,7 +230,7 @@ public async Task SendMessage(string subject, NotificationTemplateComponen var client = await GetSmtpClientAsync(); - var message = BuildMessage(subject, to,body.Render(), cc, bcc); + var message = BuildMessage(subject, to, body.Render(), cc, bcc); return await TrySend(client, message); } @@ -230,7 +240,7 @@ public async Task SendMessage(string subject, NotificationTemplateComponen } - catch(Exception ex) + catch (Exception ex) { throw ex; } diff --git a/BLAZAMServices/Background/OUNotificationService.cs b/BLAZAMServices/Background/OUNotificationService.cs index ddedaf88..1853a728 100644 --- a/BLAZAMServices/Background/OUNotificationService.cs +++ b/BLAZAMServices/Background/OUNotificationService.cs @@ -2,17 +2,14 @@ using BLAZAM.Database.Context; using BLAZAM.Database.Models.Notifications; using BLAZAM.Database.Models.User; +using BLAZAM.EmailMessage.Email.Base; +using BLAZAM.EmailMessage.Email.Notifications; +using BLAZAM.Helpers; using BLAZAM.Localization; using BLAZAM.Logger; +using BLAZAM.Notifications.Notifications; using BLAZAM.Notifications.Services; -using BLAZAM.Session.Interfaces; -using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.Extensions.Localization; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace BLAZAM.Services.Background { @@ -21,12 +18,14 @@ public class OUNotificationService private IAppDatabaseFactory _databaseFactory; private readonly INotificationPublisher _notificationPublisher; private readonly IStringLocalizer _appLocalization; + private readonly EmailService _emailService; - public OUNotificationService(IAppDatabaseFactory databaseFactory,INotificationPublisher notificationPublisher, IStringLocalizerappLocalization) + public OUNotificationService(IAppDatabaseFactory databaseFactory,INotificationPublisher notificationPublisher, IStringLocalizerappLocalization,EmailService emailService) { _databaseFactory = databaseFactory; _notificationPublisher = notificationPublisher; _appLocalization = appLocalization; + _emailService=emailService; } private IDatabaseContext Context => _databaseFactory.CreateDbContext(); public async Task PostAsync(IDirectoryEntryAdapter source, NotificationType notificationType) @@ -37,6 +36,7 @@ public async Task PostAsync(IDirectoryEntryAdapter source, NotificationType noti notificationTitle = _appLocalization[source.ObjectType.ToString()] + " "; string notificationBody; + NotificationTemplateComponent? emailMessage=null; notificationBody = "" + source.CanonicalName + " "; switch (notificationType) @@ -44,26 +44,30 @@ public async Task PostAsync(IDirectoryEntryAdapter source, NotificationType noti case NotificationType.Create: notificationTitle += _appLocalization["Created"]; notificationBody += _appLocalization["was created at"] + source.Created.Value.ToLocalTime(); - + emailMessage = NotificationType.Create.ToNotification(); break; case NotificationType.Delete: notificationTitle += _appLocalization["Deleted"]; notificationBody += _appLocalization["was deleted at"] + source.LastChanged.Value.ToLocalTime(); + emailMessage = NotificationType.Delete.ToNotification(); break; case NotificationType.Modify: notificationTitle += _appLocalization["Modified"]; notificationBody += _appLocalization["was modified at"] + source.LastChanged.Value.ToLocalTime(); + emailMessage = NotificationType.Modify.ToNotification(); break; case NotificationType.GroupAssignment: notificationTitle += _appLocalization["Group Membership Changed"]; notificationBody += _appLocalization["was modified at"] + source.LastChanged.Value.ToLocalTime(); + emailMessage = NotificationType.GroupAssignment.ToNotification(); break; case NotificationType.PasswordChange: notificationTitle += _appLocalization["Password Reset"]; notificationBody += _appLocalization["had a password reset at"] + source.LastChanged.Value.ToLocalTime(); + emailMessage = NotificationType.PasswordChange.ToNotification(); break; @@ -74,8 +78,12 @@ public async Task PostAsync(IDirectoryEntryAdapter source, NotificationType noti notification.Dismissable = true; notification.Created = DateTime.Now; notification.Level = NotificationLevel.Info; - - foreach (var user in Context.UserSettings.ToList()) + var _emailConfigured = false; + if (_emailService.IsConfigured) + { + _emailConfigured = true; + } + foreach (var user in Context.UserSettings.ToList()) { var effectiveInAppSubscriptions = CalculateEffectiveInAppSubscriptions(user, source); var effectiveEmailSubscriptions = CalculateEffectiveEmailSubscriptions(user, source); @@ -83,6 +91,22 @@ public async Task PostAsync(IDirectoryEntryAdapter source, NotificationType noti { _notificationPublisher.PublishNotification(user, notification); } + if (effectiveEmailSubscriptions.NotificationTypes.Any(x => x.NotificationType == notificationType)) + { + if (emailMessage != null) + { + if (_emailConfigured && !user.Email.IsNullOrEmpty()) + { + await _emailService.SendMessage(notificationTitle, emailMessage, user.Email); + + } + } + else + { + var error = new ApplicationException(); + Loggers.SystemLogger.Error("Email message template was not found! {@Error}",error); + } + } } } public NotificationSubscription CalculateEffectiveEmailSubscriptions(AppUser user, IDirectoryEntryAdapter ou) diff --git a/BLAZAMSession/ApplicationUserState.cs b/BLAZAMSession/ApplicationUserState.cs index 1cb17ea5..c1a893ef 100644 --- a/BLAZAMSession/ApplicationUserState.cs +++ b/BLAZAMSession/ApplicationUserState.cs @@ -7,7 +7,6 @@ using BLAZAM.Database.Models.User; using BLAZAM.Helpers; using BLAZAM.Logger; -using BLAZAM.Notifications.Services; using BLAZAM.Session.Interfaces; using Microsoft.AspNetCore.Authentication; using Microsoft.EntityFrameworkCore; @@ -78,20 +77,13 @@ public IList? Notifications public DateTime lastDataRefresh; public AppUser? userSettings { get; set; } - private readonly INotificationPublisher _notificationPublisher; private readonly IAppDatabaseFactory _dbFactory; - public ApplicationUserState(IAppDatabaseFactory factory, INotificationPublisher notificationPublisher) + public ApplicationUserState(IAppDatabaseFactory factory) { - _notificationPublisher = notificationPublisher; _dbFactory = factory; - //userSettings = new(); - _notificationPublisher.OnNotificationPublished += (notifications) => - { - if (notifications.Select(n => n.User).Contains(Preferences)) - GetUserSettingFromDB(); - }; + OnSettingsChanged += (state) => { if (Id == state.Id) { diff --git a/BLAZAMSession/ApplicationUserStateService.cs b/BLAZAMSession/ApplicationUserStateService.cs index 3a2ed11d..c604010f 100644 --- a/BLAZAMSession/ApplicationUserStateService.cs +++ b/BLAZAMSession/ApplicationUserStateService.cs @@ -3,7 +3,6 @@ using BLAZAM.Common.Data.Services; using BLAZAM.Database.Context; using BLAZAM.Logger; -using BLAZAM.Notifications.Services; using BLAZAM.Session.Interfaces; using Microsoft.AspNetCore.Components.Server.Circuits; using Microsoft.AspNetCore.Http; @@ -24,7 +23,6 @@ namespace BLAZAM.Server.Data.Services /// public class ApplicationUserStateService : IApplicationUserStateService { - private INotificationPublisher _notificationPublisher; public static IApplicationUserStateService Instance { get; private set; } @@ -68,10 +66,8 @@ public class ApplicationUserStateService : IApplicationUserStateService /// An HTTP Context Accessor to get the current ClaimsPrincipal of the current session. /// This Principal is persisted via the browser authentication cookie /// Database Context Factory for accessing the Authentication Setting - SessionTimeout - public ApplicationUserStateService(IHttpContextAccessor httpContextAccessor, IAppDatabaseFactory factory, - INotificationPublisher notificationPublisher) + public ApplicationUserStateService(IHttpContextAccessor httpContextAccessor, IAppDatabaseFactory factory) { - _notificationPublisher = notificationPublisher; Instance = this; _httpContextAccessor = httpContextAccessor; _factory = factory; @@ -240,7 +236,7 @@ public void RemoveUserState(IApplicationUserState state) public IApplicationUserState CreateUserState(ClaimsPrincipal user) { - return new ApplicationUserState(_factory, _notificationPublisher) { User = user }; + return new ApplicationUserState(_factory) { User = user }; } } } diff --git a/BLAZAMSession/BLAZAMSession.csproj b/BLAZAMSession/BLAZAMSession.csproj index c1cb444d..1c18bc9b 100644 --- a/BLAZAMSession/BLAZAMSession.csproj +++ b/BLAZAMSession/BLAZAMSession.csproj @@ -10,7 +10,6 @@ - diff --git a/BLAZAMUpdate/ApplicationUpdate.cs b/BLAZAMUpdate/ApplicationUpdate.cs index 09666920..2f3fcf3c 100644 --- a/BLAZAMUpdate/ApplicationUpdate.cs +++ b/BLAZAMUpdate/ApplicationUpdate.cs @@ -188,6 +188,7 @@ public IJob GetUpdateJob() var stagingCheckStep = new JobStep("Check prepared files", (step) => { return UpdateStagingDirectory.Exists; }); var bakupStep = new JobStep("Create backup", Backup); var updateUpdaterStep = new JobStep("Apply Files", InitiateFileCopy); + var waitForRestart = new JobStep("Wait for completion...",Wait); updateJob.AddStep(cleanDownloadStep); updateJob.AddStep(downloadStep); updateJob.AddStep(cleanStageStep); @@ -207,8 +208,14 @@ public IJob GetUpdateJob() throw new ApplicationUpdateException("An unknown error caused the update to fail."); } - - private async Task InitiateFileCopy(JobStep? step) + private async Task Wait(JobStep? step) + { + while (true) + { + await Task.Delay(1000); + } + } + private async Task InitiateFileCopy(JobStep? step) { //All prerequisites met diff --git a/BLAZAMUpdate/Services/UpdateService.cs b/BLAZAMUpdate/Services/UpdateService.cs index f4572c78..b06fabac 100644 --- a/BLAZAMUpdate/Services/UpdateService.cs +++ b/BLAZAMUpdate/Services/UpdateService.cs @@ -1,18 +1,15 @@  using Octokit; -using BLAZAM.Common; using BLAZAM.Update.Exceptions; using BLAZAM.Logger; using BLAZAM.Helpers; using BLAZAM.Common.Data; using BLAZAM.Database.Context; using System.Security.Principal; -using System.Reflection.Metadata.Ecma335; using System.Diagnostics; using BLAZAM.Localization; using Microsoft.AspNetCore.Components; using Microsoft.Extensions.Localization; -using System.Net.WebSockets; namespace BLAZAM.Update.Services { @@ -49,7 +46,7 @@ public class UpdateService : UpdateServiceBase protected readonly IHttpClientFactory httpClientFactory; private readonly ApplicationInfo _applicationInfo; - public UpdateService(IHttpClientFactory _clientFactory, ApplicationInfo applicationInfo, IAppDatabaseFactory? dbFactory = null, IStringLocalizer appLocalization=null) + public UpdateService(IHttpClientFactory _clientFactory, ApplicationInfo applicationInfo, IAppDatabaseFactory? dbFactory = null, IStringLocalizer appLocalization = null) { _dbFactory = dbFactory; httpClientFactory = _clientFactory; @@ -108,7 +105,8 @@ private async Task GetReleases() latestBranchRelease = branchReleases.FirstOrDefault(); //Store all other releases for use later AvailableUpdates.Clear(); - try { + try + { var betaStableReleases = releases.Where(r => r.TagName.Contains("Stable", StringComparison.OrdinalIgnoreCase)); foreach (var release in betaStableReleases) @@ -125,7 +123,7 @@ private async Task GetReleases() { Loggers.UpdateLogger.Error("Error trying to get beta releases {@Error}", ex); } - + foreach (var release in stableReleases) { //Get the release filename to prepare a version object @@ -139,63 +137,18 @@ private async Task GetReleases() var latestBranchUpdate = EncapsulateUpdate(latestBranchRelease, SelectedBranch); if (latestBranchUpdate.Branch != ApplicationReleaseBranches.Stable && latestBranchUpdate.Branch != "Stable") { - if (!AvailableUpdates.Contains(latestBranchUpdate)) - { - AvailableUpdates.Add(latestBranchUpdate); - } - + if (!AvailableUpdates.Contains(latestBranchUpdate)) + { + AvailableUpdates.Add(latestBranchUpdate); + } + } IncompatibleUpdates = AvailableUpdates.Where(x => !x.PassesPrerequisiteChecks).ToList(); foreach (var release in IncompatibleUpdates) { AvailableUpdates.Remove(release); } - ////Override branch if stable has more recent release - //if (latestStableUpdate!=null) - //{ - // if(latestBranchUpdate!=null) - // { - // if (latestStableUpdate.Version.NewerThan(latestBranchUpdate.Version)) - // { - // LatestUpdate = latestStableUpdate; - - // } - // else - // { - // LatestUpdate = latestBranchUpdate; - - // } - - // } - // else - // { - // LatestUpdate = latestStableUpdate; - - // } - - //} - //if (Debugger.IsAttached) - //{ - // ApplicationUpdate? testUpdate = EncapsulateUpdate(latestRelease, SelectedBranch); - - // testUpdate.PreRequisiteChecks.Add(new(() => { - // if (!ApplicationInfo.isUnderIIS && !PrerequisiteChecker.CheckForAspCore()) - // { - // testUpdate.PrequisiteMessage = "ASP NET Core 8 Runtime is missing."; - // return false; - - // } - // if (ApplicationInfo.isUnderIIS && !PrerequisiteChecker.CheckForAspCoreHosting()) - // { - // testUpdate.PrequisiteMessage = "ASP NET Core 8 Web Hosting Bundle is missing."; - // return false; - - // } - // return true; - // })); - // testUpdate.Version = new ApplicationVersion("1.0.0.2024.07.01.0000"); - // LatestUpdate = testUpdate; - //} + } /// @@ -212,9 +165,9 @@ private async Task SetBranch() { using var context = await _dbFactory.CreateDbContextAsync(); SelectedBranch = context.AppSettings.FirstOrDefault()?.UpdateBranch; - if(SelectedBranch == "Stable") + if (SelectedBranch == "Stable") { - context.AppSettings.FirstOrDefault().UpdateBranch= ApplicationReleaseBranches.Stable; + context.AppSettings.FirstOrDefault().UpdateBranch = ApplicationReleaseBranches.Stable; SelectedBranch = ApplicationReleaseBranches.Stable; context.SaveChanges(); } @@ -240,7 +193,7 @@ private async Task SetBranch() releaseVersion = new ApplicationVersion(filename.Substring(filename.IndexOf("-v") + 2)); - + if (releaseToEncapsulate != null && releaseVersion != null) @@ -253,13 +206,14 @@ private async Task SetBranch() }; var update = new ApplicationUpdate(_applicationInfo, _dbFactory) { Release = release }; - if(releaseVersion.NewerThan(new ApplicationVersion("0.9.99"))) + if (releaseVersion.NewerThan(new ApplicationVersion("0.9.99"))) { - update.PreRequisiteChecks.Add(new(() => { - if (!ApplicationInfo.isUnderIIS && !PrerequisiteChecker.CheckForAspCore()) + update.PreRequisiteChecks.Add(new(() => + { + if (!ApplicationInfo.isUnderIIS && !PrerequisiteChecker.CheckForAspCore()) { - if(AppLocalization!=null) - update.PrequisiteMessage = AppLocalization["ASP NET Core 8 Runtime is missing."]; + if (AppLocalization != null) + update.PrequisiteMessage = AppLocalization["ASP NET Core 8 Runtime is missing."]; else update.PrequisiteMessage = "ASP NET Core 8 Runtime is missing."; @@ -354,7 +308,7 @@ private bool TestCustomCredentials() private bool TestDirectoryCredentials() { - if(_dbFactory == null)return false; + if (_dbFactory == null) return false; using var context = _dbFactory.CreateDbContext(); //Prepare impersonation WindowsImpersonation? impersonation = null; From 970ad0f91857d68f8939810f891eb3e92539d9a5 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Sat, 27 Jul 2024 14:03:25 -0400 Subject: [PATCH 17/30] Self Notification Subscription Management --- BLAZAMGui/Layouts/AppUserButton.razor | 9 +++ .../EditNotificationSubscriptionRow.razor | 15 +++-- .../NotificaionSubscriptionEditor.razor | 34 +++++++++++ .../Notifications/NotificationSettings.razor | 29 +-------- .../OUNotificationSubscriptions.razor | 60 ++++++++++++++++--- 5 files changed, 108 insertions(+), 39 deletions(-) create mode 100644 BLAZAMGui/UI/Settings/Notifications/NotificaionSubscriptionEditor.razor diff --git a/BLAZAMGui/Layouts/AppUserButton.razor b/BLAZAMGui/Layouts/AppUserButton.razor index 385c5510..5ca02aa6 100644 --- a/BLAZAMGui/Layouts/AppUserButton.razor +++ b/BLAZAMGui/Layouts/AppUserButton.razor @@ -34,6 +34,9 @@ @AppLocalization["Profile Settings"] + + @AppLocalization["Notification Settings"] + @AppLocalization["Documentation"] @@ -58,8 +61,14 @@ + + + + + @code { AppModal? profileModal; + AppModal? notificationsModal; /// /// Indicates whether the notification panel is open /// diff --git a/BLAZAMGui/UI/Settings/Notifications/EditNotificationSubscriptionRow.razor b/BLAZAMGui/UI/Settings/Notifications/EditNotificationSubscriptionRow.razor index 4c12b319..ba3436dd 100644 --- a/BLAZAMGui/UI/Settings/Notifications/EditNotificationSubscriptionRow.razor +++ b/BLAZAMGui/UI/Settings/Notifications/EditNotificationSubscriptionRow.razor @@ -1,4 +1,4 @@ - +@inject IStringLocalizer AppLocalization @foreach (var type in Enum.GetValues(typeof(NotificationType))) { @@ -11,7 +11,6 @@ ValueChanged=@((bool val)=>{ToggleType(originalEnum,val);}) Value="@(Subscription.NotificationTypes.FirstOrDefault(x=>x.NotificationType==originalEnum)!=null)" /> - } @@ -29,9 +28,13 @@ @if (Subscription.Id == 0) { - + + @AppLocalization["Create"] + } else @@ -40,10 +43,12 @@ diff --git a/BLAZAMGui/UI/Settings/Notifications/NotificaionSubscriptionEditor.razor b/BLAZAMGui/UI/Settings/Notifications/NotificaionSubscriptionEditor.razor new file mode 100644 index 00000000..8785e10c --- /dev/null +++ b/BLAZAMGui/UI/Settings/Notifications/NotificaionSubscriptionEditor.razor @@ -0,0 +1,34 @@ + + + + + @if (_selectedOU != null) + { + + + + } + + + + +@code{ + [Parameter] + public AppUser User {get;set;} + + IDirectoryEntryAdapter? _selectedOU = null; + + + private async void ouChanged(IDirectoryEntryAdapter entry) + { + var ou = (IADOrganizationalUnit)entry; + if (ou != null) + { + _selectedOU = ou; + await InvokeAsync(StateHasChanged); + } + } + +} \ No newline at end of file diff --git a/BLAZAMGui/UI/Settings/Notifications/NotificationSettings.razor b/BLAZAMGui/UI/Settings/Notifications/NotificationSettings.razor index 9e4b1a39..1a050404 100644 --- a/BLAZAMGui/UI/Settings/Notifications/NotificationSettings.razor +++ b/BLAZAMGui/UI/Settings/Notifications/NotificationSettings.razor @@ -1,5 +1,5 @@ @inherits AppComponentBase -

@AppLocalization["Managee Notifications"]

+

@AppLocalization["Manage Notifications"]

@if (_selectedUser != null) { - - - - - @if (_selectedOU != null) - { - - - - } - - - + } @code { - IDirectoryEntryAdapter? _selectedOU = null; IList Users = new List(); AppUser? _selectedUser = null; protected override async Task OnInitializedAsync() @@ -37,15 +22,7 @@ if (value == null) value = String.Empty; return Users.Where(x => x.Username.Contains(value)); } - private async void ouChanged(IDirectoryEntryAdapter entry) - { - var ou = (IADOrganizationalUnit)entry; - if (ou != null) - { - _selectedOU = ou; - await InvokeAsync(StateHasChanged); - } - } + diff --git a/BLAZAMGui/UI/Settings/Notifications/OUNotificationSubscriptions.razor b/BLAZAMGui/UI/Settings/Notifications/OUNotificationSubscriptions.razor index 1351b69f..9f3343fb 100644 --- a/BLAZAMGui/UI/Settings/Notifications/OUNotificationSubscriptions.razor +++ b/BLAZAMGui/UI/Settings/Notifications/OUNotificationSubscriptions.razor @@ -2,28 +2,52 @@ @inject OUNotificationService ouNotificationService + + + @(AppLocalization["Notification Settings for "]+_ou.CanonicalName) + + + + + + @AppLocalization["Events"] + + + @AppLocalization["Delivery"] + + + @AppLocalization[" "] + + + @AppLocalization[" "] + + - + @{ + bool first = true; + } @foreach (var type in Enum.GetValues(typeof(NotificationType))) { var originalEnum = (NotificationType)type; - + @originalEnum.ToString() + first=false; + } - + @AppLocalization["In App"] @AppLocalization["To Email"] - + @AppLocalization["Block"] - + @AppLocalization["Save"] @@ -37,10 +61,24 @@ + OnDeleted="DeleteExisting" /> } } + else + { + + + + @AppLocalization["No subscriptions are set for this OU"] + + + } + + + + + @@ -50,10 +88,16 @@ - - @AppLocalization["Effective Notification Settings"] + + + + + + + @(AppLocalization["Effective Notification Settings for "]+_ou.CanonicalName) + From 6d523d241edba21b840173bbd9fb58350e118c88 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Sat, 27 Jul 2024 14:09:30 -0400 Subject: [PATCH 18/30] App news improvemnts --- BLAZAMGui/UI/Modals/AppNewsItemDialog.razor | 12 ++++++------ BLAZAMGui/UI/Outputs/ApplicationNewsProvider.razor | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/BLAZAMGui/UI/Modals/AppNewsItemDialog.razor b/BLAZAMGui/UI/Modals/AppNewsItemDialog.razor index 2cadf069..997a7ca4 100644 --- a/BLAZAMGui/UI/Modals/AppNewsItemDialog.razor +++ b/BLAZAMGui/UI/Modals/AppNewsItemDialog.razor @@ -1,7 +1,7 @@ @using ApplicationNews @inherits AppComponentBase - + @((MarkupString)Item.Body) @@ -12,11 +12,11 @@ @if (!Item.Link.IsNullOrEmpty()) { @AppLocalization["Link"] + Href="@Item.Link" + Target="_blank">@Item.Link } - - + + @@ -42,7 +42,7 @@ private async void Acknowledge() { var existingReadItem = CurrentUser.State.ReadNewsItems.FirstOrDefault(x => x.NewsItemId == Item.Id); - if (existingReadItem!=null) + if (existingReadItem != null) { existingReadItem.NewsItemUpdatedAt = Item.UpdatedAt; } diff --git a/BLAZAMGui/UI/Outputs/ApplicationNewsProvider.razor b/BLAZAMGui/UI/Outputs/ApplicationNewsProvider.razor index 2e617b57..f9b40b15 100644 --- a/BLAZAMGui/UI/Outputs/ApplicationNewsProvider.razor +++ b/BLAZAMGui/UI/Outputs/ApplicationNewsProvider.razor @@ -27,7 +27,7 @@ - + Blazam @AppLocalization["News"] @foreach (var item in unreadItems.OrderByDescending(x => x.UpdatedAt)) { @item.Title - @if (item.Link != null) + @* @if (item.Link != null) { @item.Link - } + } *@ } From c2efaa1c8509b1bc7792c2c2683aea132377e91b Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Sat, 27 Jul 2024 14:10:10 -0400 Subject: [PATCH 19/30] Auto Update registers actions as Jobs --- BLAZAMUpdate/Services/AutoUpdateService.cs | 113 ++++++++++++--------- 1 file changed, 63 insertions(+), 50 deletions(-) diff --git a/BLAZAMUpdate/Services/AutoUpdateService.cs b/BLAZAMUpdate/Services/AutoUpdateService.cs index fc8073fc..ca6f959d 100644 --- a/BLAZAMUpdate/Services/AutoUpdateService.cs +++ b/BLAZAMUpdate/Services/AutoUpdateService.cs @@ -181,41 +181,47 @@ private void CleanDirectories(object? state) private async void CheckForUpdate(object? state) { - try - { - var appSettings = (await factory.CreateDbContextAsync()).AppSettings.FirstOrDefault(); + IJob updateCheckJob = new Job("Check for Update"); + IJobStep checkForUpdateStep = new JobStep("Execute", async(step) => { + try + { + var appSettings = (await factory.CreateDbContextAsync()).AppSettings.FirstOrDefault(); - Loggers.UpdateLogger.Information("Checking for automatic update"); + Loggers.UpdateLogger.Information("Checking for automatic update"); - var latestUpdate = await updateService.GetUpdates(); - if (latestUpdate != null && latestUpdate.Version.NewerThan(_applicationInfo.RunningVersion)) - { - IsUpdateAvailable = true; - if (appSettings.AutoUpdate && appSettings.AutoUpdateTime != null) + var latestUpdate = await updateService.GetUpdates(); + if (latestUpdate != null && latestUpdate.Version.NewerThan(_applicationInfo.RunningVersion)) { - if (latestUpdate.PassesPrerequisiteChecks) - ScheduleUpdate(appSettings.AutoUpdateTime.Value, latestUpdate); - else + IsUpdateAvailable = true; + if (appSettings.AutoUpdate && appSettings.AutoUpdateTime != null) { - Loggers.UpdateLogger.Warning("Update failed prerequisite check, cancelling scheduling {@Error}", latestUpdate.PrequisiteMessage); + if (latestUpdate.PassesPrerequisiteChecks) + ScheduleUpdate(appSettings.AutoUpdateTime.Value, latestUpdate); + else + { + Loggers.UpdateLogger.Warning("Update failed prerequisite check, cancelling scheduling {@Error}", latestUpdate.PrequisiteMessage); + } } + + } + else + { + IsUpdateAvailable = false; + Cancel(); + Loggers.UpdateLogger.Information("No new updates found."); + } } - else + catch (Exception ex) { - IsUpdateAvailable = false; - Cancel(); - Loggers.UpdateLogger.Information("No new updates found."); - + Loggers.UpdateLogger.Error("Error while checking for auto update {@Error}", ex); } - - } - catch (Exception ex) - { - Loggers.UpdateLogger.Error("Error while checking for auto update {@Error}", ex); - } + return true; + }); + updateCheckJob.AddStep(checkForUpdateStep); + await updateCheckJob.RunAsync(); } public void Cancel() { @@ -227,44 +233,51 @@ public void Cancel() public void ScheduleUpdate(TimeSpan updateTimeOfDay, ApplicationUpdate updateToInstall) { - try + IJob scheduleUpdatteJob = new Job("Schedule Update"); + IJobStep scheduleStep = new JobStep("Execute", async (step) => { - bool justScheduled = ScheduledUpdateTime == DateTime.MinValue && ScheduledUpdate != updateToInstall; - if (ScheduledUpdate != updateToInstall) + try { - Loggers.UpdateLogger.Information("New update found: " + updateToInstall.Version); + bool justScheduled = ScheduledUpdateTime == DateTime.MinValue && ScheduledUpdate != updateToInstall; + if (ScheduledUpdate != updateToInstall) + { + Loggers.UpdateLogger.Information("New update found: " + updateToInstall.Version); - //Update availabled - var now = DateTime.Now; - ScheduledUpdateTime = new DateTime(now.Year, now.Month, now.Day, updateTimeOfDay.Hours, updateTimeOfDay.Minutes, updateTimeOfDay.Seconds); + //Update availabled + var now = DateTime.Now; + ScheduledUpdateTime = new DateTime(now.Year, now.Month, now.Day, updateTimeOfDay.Hours, updateTimeOfDay.Minutes, updateTimeOfDay.Seconds); - //Check if we're past the scheduled time this day - if (ScheduledUpdateTime < now) - { - ScheduledUpdateTime = ScheduledUpdateTime.AddDays(1); - } + //Check if we're past the scheduled time this day + if (ScheduledUpdateTime < now) + { + ScheduledUpdateTime = ScheduledUpdateTime.AddDays(1); + } - TimeSpan timeUntilUpdate = ScheduledUpdateTime - now; + TimeSpan timeUntilUpdate = ScheduledUpdateTime - now; - ScheduledUpdate = updateToInstall; + ScheduledUpdate = updateToInstall; - autoUpdateApplyTimer = new Timer(Update, null, (int)timeUntilUpdate.TotalMilliseconds, Timeout.Infinite); - Loggers.UpdateLogger.Information("Auto-update scheduled: " + timeUntilUpdate.TotalMinutes + "mins from now at " + ScheduledUpdateTime); - if (justScheduled) - { - Loggers.UpdateLogger.Debug("Update just scheduled"); - OnAutoUpdateQueued?.Invoke(ScheduledUpdateTime); + autoUpdateApplyTimer = new Timer(Update, null, (int)timeUntilUpdate.TotalMilliseconds, Timeout.Infinite); + Loggers.UpdateLogger.Information("Auto-update scheduled: " + timeUntilUpdate.TotalMinutes + "mins from now at " + ScheduledUpdateTime); + if (justScheduled) + { + Loggers.UpdateLogger.Debug("Update just scheduled"); + OnAutoUpdateQueued?.Invoke(ScheduledUpdateTime); - } + } + } } - } - catch (Exception ex) - { - Loggers.UpdateLogger.Error("Error during auto update scheduling {@Error}", ex); - } + catch (Exception ex) + { + Loggers.UpdateLogger.Error("Error during auto update scheduling {@Error}", ex); + } + return true; + }); + scheduleUpdatteJob.AddStep(scheduleStep); + scheduleUpdatteJob.Run(); } private async void Update(object? state) From e9a04b7155012297f28357c2837deae17225187e Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Sat, 27 Jul 2024 14:10:28 -0400 Subject: [PATCH 20/30] Async refresh modal --- BLAZAMGui/UI/AppModal.razor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BLAZAMGui/UI/AppModal.razor.cs b/BLAZAMGui/UI/AppModal.razor.cs index 0e5b1dbf..f570d415 100644 --- a/BLAZAMGui/UI/AppModal.razor.cs +++ b/BLAZAMGui/UI/AppModal.razor.cs @@ -131,9 +131,9 @@ protected override void OnInitialized() /// /// Re-renders the modal with the latest property values /// - public void RefreshView() + public async Task RefreshView() { - InvokeAsync(StateHasChanged); + await InvokeAsync(StateHasChanged); } /// From c6a062e7276e6eab865788d54d73ddb0c913f386 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Sat, 27 Jul 2024 14:10:58 -0400 Subject: [PATCH 21/30] Fix for unable to save email in user profile settings --- .../Modals/AppUserProfileModalContent.razor | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/BLAZAMGui/UI/Modals/AppUserProfileModalContent.razor b/BLAZAMGui/UI/Modals/AppUserProfileModalContent.razor index 7e7ce0b8..21dee518 100644 --- a/BLAZAMGui/UI/Modals/AppUserProfileModalContent.razor +++ b/BLAZAMGui/UI/Modals/AppUserProfileModalContent.razor @@ -27,9 +27,9 @@ @if (CurrentUser.State.Preferences.ProfilePicture != null) { @@ -57,10 +57,37 @@ await CurrentUser.State.SaveUserSettings(); + @code { [CascadingParameter] public MainLayout mainLayout { get; set; } + protected override void OnInitialized() + { + base.OnInitialized(); + Modal.SetYesText(AppLocalization["Save"]); + Modal.OnYes += SaveSettings; + Modal.YesEnabled = () => { return !LoadingData; }; + } + private async void SaveSettings() + { + LoadingData = true; + await Modal.RefreshView(); + if (await CurrentUser.State.SaveUserSettings()) + { + SnackBarService.Success(AppLocalization["Settings saved"]); + + } + else + { + SnackBarService.Warning(AppLocalization["Failed to save settings"]); + + } + LoadingData = false; + await Modal.RefreshView(); + + + } #nullable disable warnings async Task UploadProfilePicture(IBrowserFile profilePictureFile) { @@ -69,7 +96,6 @@ await CurrentUser.State.SaveUserSettings(); if (rawBytes != null) { CurrentUser.State.Preferences.ProfilePicture = rawBytes.ReizeRawImage(100, true); - await CurrentUser.State.SaveUserSettings(); } } } From 2e26663ffe7b4305caca3c8d4d1d1a2bf6c75b43 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Sat, 27 Jul 2024 14:11:13 -0400 Subject: [PATCH 22/30] Default user to System --- BLAZAMJobs/Job.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BLAZAMJobs/Job.cs b/BLAZAMJobs/Job.cs index 42e2d2f2..100a04a3 100644 --- a/BLAZAMJobs/Job.cs +++ b/BLAZAMJobs/Job.cs @@ -10,7 +10,7 @@ public class Job : JobStepBase, IJob, IJobStep private DateTime scheduledRunTime = DateTime.Now; private Timer? runScheduler; - public string? User { get; set; } + public string? User { get; set; } = "System"; private IList _steps = new List(); From 13927000913a9062579dc4a830ace29d3806cba5 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Sat, 27 Jul 2024 14:11:33 -0400 Subject: [PATCH 23/30] Global import for notifications gui --- BLAZAMGui/_Imports.razor | 2 ++ 1 file changed, 2 insertions(+) diff --git a/BLAZAMGui/_Imports.razor b/BLAZAMGui/_Imports.razor index 22f193b6..b7d7a6de 100644 --- a/BLAZAMGui/_Imports.razor +++ b/BLAZAMGui/_Imports.razor @@ -33,6 +33,8 @@ @using BLAZAM.Logger @using BLAZAM.Notifications.Services +@using BLAZAM.Gui.UI.Settings.Notifications + @using BLAZAM.Services @using BLAZAM.Services.Background @using BLAZAM.Session.Interfaces From 8ef57956553ffa6c353af2a4fe0fc22f49180f7d Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Sat, 27 Jul 2024 14:22:44 -0400 Subject: [PATCH 24/30] Increment version --- BLAZAM/BLAZAM.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BLAZAM/BLAZAM.csproj b/BLAZAM/BLAZAM.csproj index 50d9e8bc..406f4410 100644 --- a/BLAZAM/BLAZAM.csproj +++ b/BLAZAM/BLAZAM.csproj @@ -6,7 +6,7 @@ enable false 0.9.4 - 2024.07.23.1828 + 2024.07.27.1821 false BLAZAM False From 95c06990851f7663b5f7886673a932cb8799449d Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Sat, 27 Jul 2024 14:32:42 -0400 Subject: [PATCH 25/30] Fix for possible email exception on email setttings page --- BLAZAMGui/UI/Settings/EmailSettings.razor | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/BLAZAMGui/UI/Settings/EmailSettings.razor b/BLAZAMGui/UI/Settings/EmailSettings.razor index 10186cdd..0cd7544b 100644 --- a/BLAZAMGui/UI/Settings/EmailSettings.razor +++ b/BLAZAMGui/UI/Settings/EmailSettings.razor @@ -134,7 +134,8 @@ //message.User = user; //var html = message.Render(); //emailPreview = EmailService.PrepareHTMLForEmail(html); - emailPreview = EmailService.BuildMessage("BLAZAM Test Email", "to@test.com").HtmlBody; + if(EmailService.IsConfigured) + emailPreview = EmailService.BuildMessage("BLAZAM Test Email", "to@test.com").HtmlBody; LoadingData = false; await InvokeAsync(StateHasChanged); From 6b6c6a3808e362ec96ce90264e1df7237be66120 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Sat, 27 Jul 2024 14:47:55 -0400 Subject: [PATCH 26/30] Fix for null insertion error when creating mulitiple notification subscriptions sequentially --- BLAZAMGui/UI/Settings/EmailSettings.razor | 4 ++-- .../Settings/Notifications/OUNotificationSubscriptions.razor | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/BLAZAMGui/UI/Settings/EmailSettings.razor b/BLAZAMGui/UI/Settings/EmailSettings.razor index 0cd7544b..5f501815 100644 --- a/BLAZAMGui/UI/Settings/EmailSettings.razor +++ b/BLAZAMGui/UI/Settings/EmailSettings.razor @@ -91,7 +91,7 @@ Send Test Email - @if (ApplicationInfo.InDebugMode) + @if (ApplicationInfo.InDebugMode && emailPreview!=null) { @code { #nullable disable warnings - string emailPreview; + string? emailPreview=null; BLAZAM.Database.Models.EmailSettings settings = new BLAZAM.Database.Models.EmailSettings(); string testRecipient; protected override async Task OnInitializedAsync() diff --git a/BLAZAMGui/UI/Settings/Notifications/OUNotificationSubscriptions.razor b/BLAZAMGui/UI/Settings/Notifications/OUNotificationSubscriptions.razor index 9f3343fb..3eb3f19d 100644 --- a/BLAZAMGui/UI/Settings/Notifications/OUNotificationSubscriptions.razor +++ b/BLAZAMGui/UI/Settings/Notifications/OUNotificationSubscriptions.razor @@ -261,6 +261,8 @@ if (changes > 0) { newSubscription = new(); + newSubscription.UserId = User.Id; + newSubscription.OU = ou.DN; SnackBarService.Success(AppLocalization["Saved notification subscription"]); UpdateSubscriptions(); From bbf37e5b969681c47b2af0dd973ed2df486e7a3b Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Sat, 27 Jul 2024 15:51:57 -0400 Subject: [PATCH 27/30] Fully functional email notifications --- .../CurrentUserDashboardWidgets.razor | 35 ++++++++---- BLAZAMGui/UI/Dashboard/Widgets/AllWidgets.cs | 2 +- .../Widgets/ChangedEntriesWidget.razor | 2 +- .../Widgets/ChangedPasswordsWidget.razor | 44 +++++++++++++- .../Widgets/DeletedEntriesWidget.razor | 13 +---- BLAZAMGui/UI/Dashboard/Widgets/Widget.razor | 12 ++++ .../OUNotificationSubscriptions.razor | 2 +- BLAZAMServices/Background/EmailService.cs | 8 ++- .../Background/OUNotificationService.cs | 57 ++++++++++--------- 9 files changed, 119 insertions(+), 56 deletions(-) diff --git a/BLAZAMGui/UI/Dashboard/CurrentUserDashboardWidgets.razor b/BLAZAMGui/UI/Dashboard/CurrentUserDashboardWidgets.razor index c812516b..4fe38219 100644 --- a/BLAZAMGui/UI/Dashboard/CurrentUserDashboardWidgets.razor +++ b/BLAZAMGui/UI/Dashboard/CurrentUserDashboardWidgets.razor @@ -40,18 +40,33 @@ @{ - var widget = allWidgets.First(w => w.WidgetType == context.WidgetType); - } - - - @widget.Title - - {await RemoveWidget(context);}) /> - - - + Widget? widget =null; + try + { + widget = allWidgets.First(w => w.WidgetType == context.WidgetType); + + } + catch + { + + } + if (widget != null) + { + + + @widget.Title + + {await RemoveWidget(context);}) /> + + + + + + } + } + } diff --git a/BLAZAMGui/UI/Dashboard/Widgets/AllWidgets.cs b/BLAZAMGui/UI/Dashboard/Widgets/AllWidgets.cs index 5b4caa78..defb9304 100644 --- a/BLAZAMGui/UI/Dashboard/Widgets/AllWidgets.cs +++ b/BLAZAMGui/UI/Dashboard/Widgets/AllWidgets.cs @@ -41,7 +41,7 @@ public static List Available(IApplicationUserState? applicationUser) widgets.Add(new NewComputersWidget() { WidgetType = DashboardWidgetType.NewComputers, Title = "Computers created in the last 14 days" }); if (applicationUser.IsSuperAdmin) { - widgets.Add(new ChangedPasswordsWidget() { WidgetType = DashboardWidgetType.PasswordsChanged, Title = "Password Changed" }); + //widgets.Add(new ChangedPasswordsWidget() { WidgetType = DashboardWidgetType.PasswordsChanged, Title = "Password Changed" }); widgets.Add(new DeletedEntriesWidget() { WidgetType = DashboardWidgetType.DeletedEntries, Title = "Entries deleted in the last 14 days" }); } diff --git a/BLAZAMGui/UI/Dashboard/Widgets/ChangedEntriesWidget.razor b/BLAZAMGui/UI/Dashboard/Widgets/ChangedEntriesWidget.razor index 019aa729..9f65b1cd 100644 --- a/BLAZAMGui/UI/Dashboard/Widgets/ChangedEntriesWidget.razor +++ b/BLAZAMGui/UI/Dashboard/Widgets/ChangedEntriesWidget.razor @@ -57,7 +57,7 @@ { var search = new ADSearch(); - search.Fields.Changed = DateTime.Now.AddDays(-1); + search.Fields.PasswordLastSet = DateTime.Now.AddDays(-1).ToFileTimeUtc().ToString(); changdEntries = (await search.SearchAsync()).Where(x => x.CanRead).ToList(); LoadingData = false; await InvokeAsync(StateHasChanged); diff --git a/BLAZAMGui/UI/Dashboard/Widgets/ChangedPasswordsWidget.razor b/BLAZAMGui/UI/Dashboard/Widgets/ChangedPasswordsWidget.razor index 78b06042..9d654d68 100644 --- a/BLAZAMGui/UI/Dashboard/Widgets/ChangedPasswordsWidget.razor +++ b/BLAZAMGui/UI/Dashboard/Widgets/ChangedPasswordsWidget.razor @@ -1,8 +1,46 @@ @inherits Widget @attribute [Authorize] -
-

User passwords changed in the last 90 days

+ + + + + + @context.Item?.CanonicalName + + + + + + @(((IADUser)context.Item).PasswordLastSet) + + + + + + + + + + + + + +@*
+
@foreach (var user in LockedUsers) @@ -21,7 +59,7 @@ }
-
+
*@ @code { List LockedUsers = new(); diff --git a/BLAZAMGui/UI/Dashboard/Widgets/DeletedEntriesWidget.razor b/BLAZAMGui/UI/Dashboard/Widgets/DeletedEntriesWidget.razor index fe93b838..8bb5a0d7 100644 --- a/BLAZAMGui/UI/Dashboard/Widgets/DeletedEntriesWidget.razor +++ b/BLAZAMGui/UI/Dashboard/Widgets/DeletedEntriesWidget.razor @@ -56,16 +56,7 @@ } - void RowClicked(DataGridRowClickEventArgs args) - { - if (args.Item != null) - { - GoTo(args.Item); - } - } + - void GoTo(IDirectoryEntryAdapter args) - { - Nav.NavigateTo(args.SearchUri); - } + } diff --git a/BLAZAMGui/UI/Dashboard/Widgets/Widget.razor b/BLAZAMGui/UI/Dashboard/Widgets/Widget.razor index 36fb0916..175da2ed 100644 --- a/BLAZAMGui/UI/Dashboard/Widgets/Widget.razor +++ b/BLAZAMGui/UI/Dashboard/Widgets/Widget.razor @@ -5,4 +5,16 @@ public RenderFragment? WidgetContent { get; set; } public string Title{ get; set; } public DashboardWidgetType WidgetType{ get; set; } + + protected virtual void RowClicked(DataGridRowClickEventArgs args) + { + if (args.Item != null) + { + GoTo(args.Item); + } + } + protected virtual void GoTo(IDirectoryEntryAdapter args) + { + Nav.NavigateTo(args.SearchUri); + } } diff --git a/BLAZAMGui/UI/Settings/Notifications/OUNotificationSubscriptions.razor b/BLAZAMGui/UI/Settings/Notifications/OUNotificationSubscriptions.razor index 3eb3f19d..ec471f73 100644 --- a/BLAZAMGui/UI/Settings/Notifications/OUNotificationSubscriptions.razor +++ b/BLAZAMGui/UI/Settings/Notifications/OUNotificationSubscriptions.razor @@ -262,7 +262,7 @@ { newSubscription = new(); newSubscription.UserId = User.Id; - newSubscription.OU = ou.DN; + newSubscription.OU = OU.DN; SnackBarService.Success(AppLocalization["Saved notification subscription"]); UpdateSubscriptions(); diff --git a/BLAZAMServices/Background/EmailService.cs b/BLAZAMServices/Background/EmailService.cs index 799a5bc1..57415d20 100644 --- a/BLAZAMServices/Background/EmailService.cs +++ b/BLAZAMServices/Background/EmailService.cs @@ -16,6 +16,7 @@ using BLAZAM.Static; using BLAZAM.FileSystem; using BLAZAM.EmailMessage.Email.Base; +using System.Configuration; namespace BLAZAM.Services.Background { @@ -135,9 +136,10 @@ private MimeMessage BuildMessage(string subject, string to, string body, string? { EmailSettings? settings = GetSettings(); - if (settings.UseSMTPAuth && settings.FromAddress.IsNullOrEmpty()) email.From.Add(MailboxAddress.Parse(settings.SMTPUsername)); - else email.From.Add(MailboxAddress.Parse(settings.FromAddress)); - + if (settings.UseSMTPAuth && settings.FromAddress.IsNullOrEmpty()) email.Sender=MailboxAddress.Parse(settings.SMTPUsername); + else email.Sender=MailboxAddress.Parse(settings.FromAddress); + if(!settings.FromName.IsNullOrEmpty()) email.Sender.Name = settings.FromName; + email.From.Add(email.Sender); if (to != null) email.To.Add(MailboxAddress.Parse(to)); if (cc != null) email.Cc.Add(MailboxAddress.Parse(cc)); if (bcc != null) email.Bcc.Add(MailboxAddress.Parse(bcc)); diff --git a/BLAZAMServices/Background/OUNotificationService.cs b/BLAZAMServices/Background/OUNotificationService.cs index 1853a728..1dc895dc 100644 --- a/BLAZAMServices/Background/OUNotificationService.cs +++ b/BLAZAMServices/Background/OUNotificationService.cs @@ -20,12 +20,12 @@ public class OUNotificationService private readonly IStringLocalizer _appLocalization; private readonly EmailService _emailService; - public OUNotificationService(IAppDatabaseFactory databaseFactory,INotificationPublisher notificationPublisher, IStringLocalizerappLocalization,EmailService emailService) + public OUNotificationService(IAppDatabaseFactory databaseFactory, INotificationPublisher notificationPublisher, IStringLocalizer appLocalization, EmailService emailService) { _databaseFactory = databaseFactory; _notificationPublisher = notificationPublisher; _appLocalization = appLocalization; - _emailService=emailService; + _emailService = emailService; } private IDatabaseContext Context => _databaseFactory.CreateDbContext(); public async Task PostAsync(IDirectoryEntryAdapter source, NotificationType notificationType) @@ -36,7 +36,7 @@ public async Task PostAsync(IDirectoryEntryAdapter source, NotificationType noti notificationTitle = _appLocalization[source.ObjectType.ToString()] + " "; string notificationBody; - NotificationTemplateComponent? emailMessage=null; + NotificationTemplateComponent? emailMessage = null; notificationBody = "" + source.CanonicalName + " "; switch (notificationType) @@ -44,33 +44,40 @@ public async Task PostAsync(IDirectoryEntryAdapter source, NotificationType noti case NotificationType.Create: notificationTitle += _appLocalization["Created"]; notificationBody += _appLocalization["was created at"] + source.Created.Value.ToLocalTime(); - emailMessage = NotificationType.Create.ToNotification(); + var createdMessage = NotificationType.Create.ToNotification(); + createdMessage.EntryName = source.CanonicalName; + emailMessage = createdMessage; break; - case NotificationType.Delete: + case NotificationType.Delete: notificationTitle += _appLocalization["Deleted"]; notificationBody += _appLocalization["was deleted at"] + source.LastChanged.Value.ToLocalTime(); - emailMessage = NotificationType.Delete.ToNotification(); - + var deletedMessage = NotificationType.Delete.ToNotification(); + deletedMessage.EntryName = source.CanonicalName; + emailMessage = deletedMessage; break; case NotificationType.Modify: notificationTitle += _appLocalization["Modified"]; notificationBody += _appLocalization["was modified at"] + source.LastChanged.Value.ToLocalTime(); - emailMessage = NotificationType.Modify.ToNotification(); - + var editedMessage = NotificationType.Modify.ToNotification(); + editedMessage.EntryName = source.CanonicalName; + emailMessage = editedMessage; break; case NotificationType.GroupAssignment: notificationTitle += _appLocalization["Group Membership Changed"]; notificationBody += _appLocalization["was modified at"] + source.LastChanged.Value.ToLocalTime(); - emailMessage = NotificationType.GroupAssignment.ToNotification(); - + + var groupMembershipMessage = NotificationType.GroupAssignment.ToNotification(); + groupMembershipMessage.EntryName = source.CanonicalName; + emailMessage = groupMembershipMessage; break; case NotificationType.PasswordChange: notificationTitle += _appLocalization["Password Reset"]; notificationBody += _appLocalization["had a password reset at"] + source.LastChanged.Value.ToLocalTime(); - emailMessage = NotificationType.PasswordChange.ToNotification(); - + var passwordChangeMessage = NotificationType.PasswordChange.ToNotification(); + passwordChangeMessage.EntryName = source.CanonicalName; + emailMessage = passwordChangeMessage; break; - + } var notification = new NotificationMessage(); notification.Title = notificationTitle; @@ -78,18 +85,15 @@ public async Task PostAsync(IDirectoryEntryAdapter source, NotificationType noti notification.Dismissable = true; notification.Created = DateTime.Now; notification.Level = NotificationLevel.Info; - var _emailConfigured = false; - if (_emailService.IsConfigured) - { - _emailConfigured = true; - } - foreach (var user in Context.UserSettings.ToList()) + var _emailConfigured = _emailService.IsConfigured; + + foreach (var user in Context.UserSettings.ToList()) { var effectiveInAppSubscriptions = CalculateEffectiveInAppSubscriptions(user, source); var effectiveEmailSubscriptions = CalculateEffectiveEmailSubscriptions(user, source); if (effectiveInAppSubscriptions.NotificationTypes.Any(x => x.NotificationType == notificationType)) { - _notificationPublisher.PublishNotification(user, notification); + await _notificationPublisher.PublishNotification(user, notification); } if (effectiveEmailSubscriptions.NotificationTypes.Any(x => x.NotificationType == notificationType)) { @@ -104,7 +108,7 @@ public async Task PostAsync(IDirectoryEntryAdapter source, NotificationType noti else { var error = new ApplicationException(); - Loggers.SystemLogger.Error("Email message template was not found! {@Error}",error); + Loggers.SystemLogger.Error("Email message template was not found! {@Error}", error); } } } @@ -159,7 +163,8 @@ public NotificationSubscription CalculateEffectiveEmailSubscriptions(AppUser use } } - }catch (Exception ex) + } + catch (Exception ex) { Loggers.SystemLogger.Error("Error while parsing users for notification broadcast {@Error}", ex); } @@ -179,7 +184,7 @@ public NotificationSubscription CalculateEffectiveInAppSubscriptions(AppUser use effectiveInAppSubscription.OU = ou.DN; effectiveInAppSubscription.User = user; effectiveInAppSubscription.InApp = true; - + var userSubscriptions = context.NotificationSubscriptions.Where(x => x.DeletedAt == null && x.UserId == user.Id).ToList(); userSubscriptions = userSubscriptions.OrderBy(x => x.OU).ToList(); foreach (var sub in userSubscriptions) @@ -195,7 +200,7 @@ public NotificationSubscription CalculateEffectiveInAppSubscriptions(AppUser use effectiveInAppSubscription.NotificationTypes.RemoveAll(x => x.NotificationType == type.NotificationType); } } - + } else { @@ -209,7 +214,7 @@ public NotificationSubscription CalculateEffectiveInAppSubscriptions(AppUser use } } } - + } From c64c24f5a54ea700a9f0de15ae6a5bc87e339d48 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Sat, 27 Jul 2024 15:57:01 -0400 Subject: [PATCH 28/30] Increment minor version --- BLAZAM/BLAZAM.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BLAZAM/BLAZAM.csproj b/BLAZAM/BLAZAM.csproj index 406f4410..977c18f3 100644 --- a/BLAZAM/BLAZAM.csproj +++ b/BLAZAM/BLAZAM.csproj @@ -5,7 +5,7 @@ enable enable false - 0.9.4 + 0.9.5 2024.07.27.1821 false BLAZAM From 5fc4fd8e351f068c61e2892f3d7d9885e79d4234 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Sat, 27 Jul 2024 16:04:35 -0400 Subject: [PATCH 29/30] Update dependencies --- BLAZAM/BLAZAM.csproj | 6 +++--- BLAZAMEmailMessage/BLAZAMEmailMessage.csproj | 2 +- BLAZAMGui/BLAZAMGui.csproj | 4 ++-- BLAZAMJobs/BLAZAMJobs.csproj | 2 +- BLAZAMNotifications/BLAZAMNotifications.csproj | 2 +- BLAZAMThemes/BLAZAMThemes.csproj | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/BLAZAM/BLAZAM.csproj b/BLAZAM/BLAZAM.csproj index 977c18f3..4bc3c025 100644 --- a/BLAZAM/BLAZAM.csproj +++ b/BLAZAM/BLAZAM.csproj @@ -6,7 +6,7 @@ enable false 0.9.5 - 2024.07.27.1821 + 2024.07.27.2003 false BLAZAM False @@ -78,8 +78,8 @@ - - + + diff --git a/BLAZAMEmailMessage/BLAZAMEmailMessage.csproj b/BLAZAMEmailMessage/BLAZAMEmailMessage.csproj index e6af1ffa..84a8390e 100644 --- a/BLAZAMEmailMessage/BLAZAMEmailMessage.csproj +++ b/BLAZAMEmailMessage/BLAZAMEmailMessage.csproj @@ -14,7 +14,7 @@ - + diff --git a/BLAZAMGui/BLAZAMGui.csproj b/BLAZAMGui/BLAZAMGui.csproj index ed4643a2..0222df55 100644 --- a/BLAZAMGui/BLAZAMGui.csproj +++ b/BLAZAMGui/BLAZAMGui.csproj @@ -27,8 +27,8 @@ - - + + diff --git a/BLAZAMJobs/BLAZAMJobs.csproj b/BLAZAMJobs/BLAZAMJobs.csproj index 0981eca5..b7983acf 100644 --- a/BLAZAMJobs/BLAZAMJobs.csproj +++ b/BLAZAMJobs/BLAZAMJobs.csproj @@ -8,7 +8,7 @@ - + diff --git a/BLAZAMNotifications/BLAZAMNotifications.csproj b/BLAZAMNotifications/BLAZAMNotifications.csproj index 44298634..23703469 100644 --- a/BLAZAMNotifications/BLAZAMNotifications.csproj +++ b/BLAZAMNotifications/BLAZAMNotifications.csproj @@ -8,7 +8,7 @@ - + diff --git a/BLAZAMThemes/BLAZAMThemes.csproj b/BLAZAMThemes/BLAZAMThemes.csproj index 2ede2c12..21aee388 100644 --- a/BLAZAMThemes/BLAZAMThemes.csproj +++ b/BLAZAMThemes/BLAZAMThemes.csproj @@ -8,8 +8,8 @@ - - + + From b4fc86b21614b9edd3bad87dace6ea17639f1c82 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Sat, 27 Jul 2024 16:24:24 -0400 Subject: [PATCH 30/30] Remove unused class --- BLAZAM/BLAZAM.csproj | 2 +- BLAZAMUpdate/GithubArtifacts.cs | 32 -------------------------------- 2 files changed, 1 insertion(+), 33 deletions(-) delete mode 100644 BLAZAMUpdate/GithubArtifacts.cs diff --git a/BLAZAM/BLAZAM.csproj b/BLAZAM/BLAZAM.csproj index 4bc3c025..9c7647fa 100644 --- a/BLAZAM/BLAZAM.csproj +++ b/BLAZAM/BLAZAM.csproj @@ -6,7 +6,7 @@ enable false 0.9.5 - 2024.07.27.2003 + 2024.07.27.2017 false BLAZAM False diff --git a/BLAZAMUpdate/GithubArtifacts.cs b/BLAZAMUpdate/GithubArtifacts.cs deleted file mode 100644 index ed3d7f95..00000000 --- a/BLAZAMUpdate/GithubArtifacts.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace BLAZAM.Update -{ - public class WorkflowRun - { - public int id { get; set; } - public int repository_id { get; set; } - public int head_repository_id { get; set; } - public string head_branch { get; set; } - public string head_sha { get; set; } - } - - public class Artifact - { - public int id { get; set; } - public string node_id { get; set; } - public string name { get; set; } - public int size_in_bytes { get; set; } - public string url { get; set; } - public string archive_download_url { get; set; } - public bool expired { get; set; } - public DateTime created_at { get; set; } - public DateTime expires_at { get; set; } - public DateTime updated_at { get; set; } - public WorkflowRun workflow_run { get; set; } - } - - public class ArtifactResponse - { - public int total_count { get; set; } - public List artifacts { get; set; } - } -}