diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml
index b5a7f727..8e6bfb8f 100644
--- a/.github/workflows/build-dev.yml
+++ b/.github/workflows/build-dev.yml
@@ -10,18 +10,11 @@ on:
jobs:
build:
runs-on: windows-latest
-
+ permissions: write-all
steps:
- name: Checkout code
uses: actions/checkout@v2
- - name: Cache Nuget Packages
- uses: actions/cache@v1
- with:
- path: ~/.nuget/packages
- key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
- restore-keys: |
- ${{ runner.os }}-nuget-
- name: Setup .NET Core SDK 6
uses: actions/setup-dotnet@v1
with:
@@ -72,9 +65,9 @@ jobs:
- name: Update dev release
uses: andelf/nightly-release@main
env:
- GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
- tag_name: Dev
+ tag_name: 'Dev'
name: 'Dev'
prerelease: true
body: This release is highly unstable. Expect bugs and crashes on this branch. Developers Only!
diff --git a/.github/workflows/build-nightly.yml b/.github/workflows/build-nightly.yml
index 0d28ef34..91f03565 100644
--- a/.github/workflows/build-nightly.yml
+++ b/.github/workflows/build-nightly.yml
@@ -10,18 +10,12 @@ on:
jobs:
build:
runs-on: windows-latest
+ permissions: write-all
steps:
- name: Checkout code
uses: actions/checkout@v2
- - name: Cache Nuget Packages
- uses: actions/cache@v1
- with:
- path: ~/.nuget/packages
- key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
- restore-keys: |
- ${{ runner.os }}-nuget-
- name: Setup .NET Core SDK 6
uses: actions/setup-dotnet@v1
with:
@@ -70,9 +64,9 @@ jobs:
- name: Update nightly release
uses: andelf/nightly-release@main
env:
- GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
- tag_name: Nightly
+ tag_name: 'Nightly'
name: 'Nightly'
prerelease: true
body: This release is always the latest nightly release. These versions are unstable and may break your application. You've been warned.
diff --git a/.github/workflows/deploy-demo.yml b/.github/workflows/deploy-demo.yml
index 25907e11..ed442e95 100644
--- a/.github/workflows/deploy-demo.yml
+++ b/.github/workflows/deploy-demo.yml
@@ -13,6 +13,7 @@ on:
jobs:
build:
runs-on: windows-latest
+ permissions: write-all
steps:
- uses: actions/checkout@v2
diff --git a/.github/workflows/mark-stale.yml b/.github/workflows/mark-stale.yml
new file mode 100644
index 00000000..86900852
--- /dev/null
+++ b/.github/workflows/mark-stale.yml
@@ -0,0 +1,23 @@
+name: Close inactive issues
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: "30 1 * * *"
+
+jobs:
+ close-issues:
+ runs-on: ubuntu-latest
+ permissions:
+ issues: write
+ pull-requests: write
+ steps:
+ - uses: actions/stale@v5
+ with:
+ days-before-issue-stale: 14
+ days-before-issue-close: 14
+ stale-issue-label: "stale"
+ stale-issue-message: "This issue is stale because it has been open for 14 days with no activity."
+ close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale."
+ days-before-pr-stale: -1
+ days-before-pr-close: -1
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/release-stable.yml b/.github/workflows/release-stable.yml
index 43a617ae..8d8bf973 100644
--- a/.github/workflows/release-stable.yml
+++ b/.github/workflows/release-stable.yml
@@ -10,6 +10,7 @@ on:
jobs:
build:
runs-on: windows-latest
+ permissions: write-all
steps:
@@ -52,7 +53,7 @@ jobs:
id: create_release
uses: actions/create-release@v1
env:
- GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: Stable-v${{ env.ASSEMBLY_VERSION }}
@@ -64,7 +65,7 @@ jobs:
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
- GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: blazam-stable-v${{ env.ASSEMBLY_VERSION }}.zip
diff --git a/BLAZAM.Tests/Updates/UpdateTests.cs b/BLAZAM.Tests/Updates/UpdateTests.cs
index e3d8bd75..f56444d1 100644
--- a/BLAZAM.Tests/Updates/UpdateTests.cs
+++ b/BLAZAM.Tests/Updates/UpdateTests.cs
@@ -13,44 +13,44 @@ namespace BLAZAM.Tests.Updates
public class UpdateTests
{
readonly Mock_UpdateService _updateService = new();
- [Fact]
- public async void Update_Returns_Data()
- {
- var latest = await _updateService.GetUpdates();
- Assert.NotNull(latest);
- }
- [Fact]
- public async void Updat_Returns_ValidVersion()
- {
- var latest = await _updateService.GetUpdates();
+ //[Fact]
+ //public async void Update_Returns_Data()
+ //{
+ // var latest = await _updateService.GetUpdates();
+ // Assert.NotNull(latest);
+ //}
+ //[Fact]
+ //public async void Updat_Returns_ValidVersion()
+ //{
+ // var latest = await _updateService.GetUpdates();
- Assert.NotNull(latest?.Version);
- }
- [Fact]
- public async void Update_Returns_ValidDownload()
- {
- var latest = await _updateService.GetUpdates();
- if (latest != null)
- await latest.Download(null);
+ // Assert.NotNull(latest?.Version);
+ //}
+ //[Fact]
+ //public async void Update_Returns_ValidDownload()
+ //{
+ // var latest = await _updateService.GetUpdates();
+ // if (latest != null)
+ // await latest.Download(null);
- Assert.True(latest?.UpdateFile.Exists);
- await Update_Stages_OK(latest);
- await Update_Cleanup_OK(latest);
- }
- private async Task Update_Stages_OK(ApplicationUpdate latest)
- {
+ // Assert.True(latest?.UpdateFile.Exists);
+ // await Update_Stages_OK(latest);
+ // await Update_Cleanup_OK(latest);
+ //}
+ //private async Task Update_Stages_OK(ApplicationUpdate latest)
+ //{
- await latest.ExtractFiles(null);
- Assert.True(latest.UpdateStagingDirectory.Files.Count > 2);
+ // await latest.ExtractFiles(null);
+ // Assert.True(latest.UpdateStagingDirectory.Files.Count > 2);
- }
- private async Task Update_Cleanup_OK(ApplicationUpdate latest)
- {
+ //}
+ //private async Task Update_Cleanup_OK(ApplicationUpdate latest)
+ //{
- await latest.CleanStaging(null);
- latest.UpdateFile.Delete();
- Assert.True(!latest.UpdateFile.Exists);
- Assert.True(latest.UpdateStagingDirectory.Files.Count == 0);
- }
+ // await latest.CleanStaging(null);
+ // latest.UpdateFile.Delete();
+ // Assert.True(!latest.UpdateFile.Exists);
+ // Assert.True(latest.UpdateStagingDirectory.Files.Count == 0);
+ //}
}
}
diff --git a/BLAZAM/BLAZAM.csproj b/BLAZAM/BLAZAM.csproj
index 2402f8b7..11c5811c 100644
--- a/BLAZAM/BLAZAM.csproj
+++ b/BLAZAM/BLAZAM.csproj
@@ -6,7 +6,7 @@
enable
false
0.9.3
- 2024.06.09.1748
+ 2024.07.06.2008
false
BLAZAM
False
@@ -29,7 +29,7 @@
-
+
@@ -56,19 +56,19 @@
-
+
-
-
-
-
-
-
+
+
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
@@ -110,9 +110,9 @@
-
- PreserveNewest
-
+
+ PreserveNewest
+
diff --git a/BLAZAM/Pages/Browse/ViewDirectoryEntry.razor b/BLAZAM/Pages/Browse/ViewDirectoryEntry.razor
index 34919d0c..b88f4f0a 100644
--- a/BLAZAM/Pages/Browse/ViewDirectoryEntry.razor
+++ b/BLAZAM/Pages/Browse/ViewDirectoryEntry.razor
@@ -17,6 +17,9 @@
case ActiveDirectoryObjectType.Printer:
break;
+ case ActiveDirectoryObjectType.BitLocker:
+
+ break;
}
diff --git a/BLAZAM/Pages/Computers/BitLockerViewer.razor b/BLAZAM/Pages/Computers/BitLockerViewer.razor
new file mode 100644
index 00000000..337e45cd
--- /dev/null
+++ b/BLAZAM/Pages/Computers/BitLockerViewer.razor
@@ -0,0 +1,40 @@
+@inherits AppComponentBase
+
+
+@code{
+ [Parameter]
+ public string Class{ get; set; }
+
+ private IADComputer _computer;
+ [Parameter]
+ public IADComputer Computer{ get=>_computer; set
+ {
+ if (_computer == value) return;
+ _computer = value;
+ GetRecoveries();
+
+ } }
+
+ List _recoveries = new();
+
+ protected override async Task OnInitializedAsync(){
+ await base.OnInitializedAsync();
+
+
+ }
+ private async void GetRecoveries(){
+ _recoveries = await Computer.GetBitLockerRecoveryAsync();
+ await InvokeAsync(StateHasChanged);
+ }
+}
\ No newline at end of file
diff --git a/BLAZAM/Pages/Computers/ViewBitLocker.razor b/BLAZAM/Pages/Computers/ViewBitLocker.razor
new file mode 100644
index 00000000..7017a736
--- /dev/null
+++ b/BLAZAM/Pages/Computers/ViewBitLocker.razor
@@ -0,0 +1,40 @@
+@using BLAZAM.Gui.UI.Computers
+@inherits DirectoryEntryViewBase
+@{
+ string _fieldMudStackClasses = "flex-wrap gap-10";
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+@code {
+ IADBitLockerRecovery? BitLocker=> DirectoryEntry as IADBitLockerRecovery;
+ List _recoveries = new();
+ IADComputer _computer;
+ protected override async Task OnInitializedAsync()
+ {
+
+ await base.OnInitializedAsync();
+ await InvokeAsync(StateHasChanged);
+
+
+ _computer = (IADComputer)BitLocker.GetParent();
+
+ LoadingData = false;
+ await RefreshEntryComponents();
+ }
+
+
+
+}
diff --git a/BLAZAM/Pages/Computers/ViewComputer.razor b/BLAZAM/Pages/Computers/ViewComputer.razor
index f79c1ac0..66edb550 100644
--- a/BLAZAM/Pages/Computers/ViewComputer.razor
+++ b/BLAZAM/Pages/Computers/ViewComputer.razor
@@ -4,7 +4,7 @@
string _fieldMudStackClasses = "flex-wrap gap-10";
}
@Computer?.CanonicalName
- @if (Computer != null)
+@if (Computer != null)
{
@@ -22,7 +22,7 @@
OnResetPassword="@(()=>{ChangePasswordModal?.Show();})"
OnToggleEditMode="ToggleEditMode"
OnUnlock="@Unlock"
- OnShowHistory="@(()=>{ChangeHistoryModal?.Show();})"/>
+ OnShowHistory="@(()=>{ChangeHistoryModal?.Show();})" />
@@ -113,7 +113,10 @@
-
+ @if (Computer.CanReadBitLocker)
+ {
+
+ }
@@ -155,7 +158,10 @@
@if (Computer.IsOnline == true)
{
-
+ if (CurrentUser.State.IsSuperAdmin)
+ {
+
+ }
}
else
{
@@ -252,7 +258,7 @@
async Task Unlock()
{
- if (Computer!=null && await MessageService.Confirm("Are you sure you want to unlock " + Computer?.CanonicalName + "?", "Unlock Computer"))
+ if (Computer != null && await MessageService.Confirm("Are you sure you want to unlock " + Computer?.CanonicalName + "?", "Unlock Computer"))
{
Computer.LockedOut = false;
}
diff --git a/BLAZAM/Pages/Configure/Audit.razor b/BLAZAM/Pages/Configure/Audit.razor
index 0be093b3..6100aa18 100644
--- a/BLAZAM/Pages/Configure/Audit.razor
+++ b/BLAZAM/Pages/Configure/Audit.razor
@@ -35,7 +35,7 @@
- @context.Item.Target
+ @context.Item.Target
diff --git a/BLAZAM/Pages/Configure/Fields.razor b/BLAZAM/Pages/Configure/Fields.razor
index 331d0073..e7f4d1e5 100644
--- a/BLAZAM/Pages/Configure/Fields.razor
+++ b/BLAZAM/Pages/Configure/Fields.razor
@@ -127,10 +127,14 @@
{
foreach (var field in ADFields)
{
- for (int x=0; x < field.ObjectTypes.Count;x++)
+
+ for (int x = 0; x < field.ObjectTypes.Count; x++)
{
- var trackedObjType = Context.ActiveDirectoryFieldObjectMappings.First(x => x.Id == field.Id);
- field.ObjectTypes[x] = trackedObjType;
+ var trackedObjType = Context.ActiveDirectoryFieldObjectMappings.FirstOrDefault(oType => oType.ObjectType == field.ObjectTypes[x].ObjectType);
+ if (trackedObjType != null)
+ {
+ field.ObjectTypes[x] = trackedObjType;
+ }
}
}
if (await Context.SaveChangesAsync() > 0)
diff --git a/BLAZAM/Pages/OU/ViewOU.razor b/BLAZAM/Pages/OU/ViewOU.razor
index 7cad7cfa..523bc970 100644
--- a/BLAZAM/Pages/OU/ViewOU.razor
+++ b/BLAZAM/Pages/OU/ViewOU.razor
@@ -78,7 +78,7 @@
await AuditLogger.Searched(OU);
if (OU != null)
{
- parentOU = OU.GetParent();
+ parentOU = (IADOrganizationalUnit)OU.GetParent();
}
LoadingData = false;
await RefreshEntryComponents();
diff --git a/BLAZAM/Pages/View.razor b/BLAZAM/Pages/View.razor
new file mode 100644
index 00000000..8b255b32
--- /dev/null
+++ b/BLAZAM/Pages/View.razor
@@ -0,0 +1,218 @@
+@page "/view"
+@page "/view/{SearchTermParameter}"
+@using System.Web
+
+@inherits AppComponentBase
+@attribute [Authorize(Roles = (UserRoles.SearchOUs + "," + UserRoles.SearchComputers + "," + UserRoles.SearchGroups + "," + UserRoles.SearchUsers + "," + UserRoles.SuperAdmin))]
+
+
+
+ @if (ApplicationInfo.InDemoMode)
+ {
+
+ Try searching Moore, Howard, Evans, Manny...
+
+ }
+
+
+
+ @if (Searcher.Results.Count > 1)
+ {
+
+ Results found: @Searcher.Results.Count
+ Time elapsed: @Searcher.SearchTime
+
+
+
+
+ @if (u.CanRead)
+ {
+ {
+ Searcher.Results.Clear();Searcher.Results.Add(u);
+ }) />
+
+
+ }
+
+
+ Loading...
+
+
+
+
+ }
+ else if (Searcher.Results.Count == 1)
+ {
+
+ var result = Searcher.Results[0];
+ if (result.CanRead)
+ {
+ result.OnModelDeleted = (() => { InvokeAsync(StateHasChanged); });
+
+ @if (result.IsDeleted)
+ {
+ Deleted
+ }
+ else
+ {
+
+ }
+ }
+ @* else
+ {
+
+
+ }
+ *@
+ }
+
+ else if (LoadingData)
+ {
+
+ }
+ else if (Searcher.Results.Count == 0)
+ {
+
+ No results were found.
+
+ }
+
+
+@code {
+
+ [CascadingParameter]
+ public SearchService SearchParameters { get; set; }
+
+ string ModelsTypeName = "Search";
+ protected string SearchIcon { get; set; } = "";
+ string? _searchTermParameter;
+ ///
+ /// The search term that comes from the URI
+ ///
+ [Parameter]
+ public virtual string? SearchTermParameter
+ {
+ get => _searchTermParameter; set
+ {
+ if (_searchTermParameter == HttpUtility.UrlDecode(value)) return;
+ LoadingData = true;
+ Searcher?.Cancel();
+ _searchTermParameter = HttpUtility.UrlDecode(value);
+ Task.Run(async () =>
+ {
+ await PerformSearch();
+ if (_searchTermParameter.IsNullOrEmpty())
+ LoadingData = false;
+ });
+
+
+ }
+ }
+
+
+ public ADSearch Searcher { get; set; } = new ADSearch();
+
+
+ [CascadingParameter]
+ public MainLayout? MainLayout { get; set; }
+
+ ///
+ /// The search term that comes from the search text box
+ ///
+ [CascadingParameter]
+ public string? SearchTerm { get; set; }
+
+ ///
+ /// Standard search page initializer that copies the url search term to the
+ /// text search term if it is set.
+ ///
+ ///
+ protected override async Task OnInitializedAsync()
+ {
+ await base.OnInitializedAsync();
+ Searcher = new ADSearch();
+ SearchService.SearchTerm = SearchTermParameter;
+ Searcher.GeneralSearchTerm = SearchTermParameter;
+
+ await base.OnInitializedAsync();
+
+
+
+ Searcher.OnSearchStarted += (() =>
+ {
+ InvokeAsync(StateHasChanged);
+ });
+ Searcher.OnSearchCompleted += (() =>
+ {
+ InvokeAsync(StateHasChanged);
+ });
+ Searcher.ResultsCollected += ((batch) =>
+ {
+ results.AddRange(batch.Where(r=>r.CanRead));
+ });
+ }
+ ///
+ /// Filter for searching objects of only this type
+ ///
+ [CascadingParameter]
+ public ActiveDirectoryObjectType? SearchObjectType { get; set; }
+
+ protected virtual List results { get; set; } = new List();
+
+
+ ///
+ /// Called internally to start a search
+ ///
+ ///
+ /// This method in turn calls
+ /// if the is not
+ /// null or empty.
+ ///
+ ///
+ protected async Task PerformSearch()
+ {
+ results.Clear();
+
+ LoadingData = true;
+ await InvokeAsync(StateHasChanged);
+ if (!SearchTermParameter.IsNullOrEmpty() && SearchTermParameter?.Length > 0)
+ await InvokeSearch();
+ else
+ Searcher.Results.Clear();
+ LoadingData = false;
+
+ await InvokeAsync(StateHasChanged);
+
+
+
+ }
+
+ ///
+ /// Invokes the actual search function
+ /// that processes the current
+ /// settings.
+ ///
+ ///
+ protected async Task InvokeSearch()
+ {
+ if (Searcher == null)
+ Searcher = new ADSearch();
+ else
+ Searcher.Cancel();
+ SearchService.SearchTerm = SearchTermParameter;
+ //Searcher.EnabledOnly = !SearchService.IncludeDisabled;
+ Searcher.GeneralSearchTerm = SearchService.SearchTerm;
+ //Searcher.ObjectTypeFilter = SearchService.SeachObjectType;
+ Searcher.ExactMatch = true;
+
+ //Try exact match search first
+ await Searcher.SearchAsync();
+ if (Searcher.Results.Count < 1)
+ {
+ Searcher.ExactMatch = false;
+ results = await Searcher.SearchAsync();
+
+ }
+ }
+
+}
diff --git a/BLAZAMActiveDirectory/ActiveDirectoryContext.cs b/BLAZAMActiveDirectory/ActiveDirectoryContext.cs
index 421dd220..d1a22f51 100644
--- a/BLAZAMActiveDirectory/ActiveDirectoryContext.cs
+++ b/BLAZAMActiveDirectory/ActiveDirectoryContext.cs
@@ -138,28 +138,19 @@ public List GetDeletedObjects()
}
- ///
- ///
public IADUserSearcher Users { get; }
- ///
-
- ///
public IADGroupSearcher Groups { get; }
- ///
-
- ///
public IADOUSearcher OUs { get; }
- ///
- public IADPrinterSearcher Printers { get; }
- ///
+ public IADPrinterSearcher Printers { get; }
- ///
public IADComputerSearcher Computers { get; }
+ public IADBitLockerSearcher BitLocker { get; }
+
public IDatabaseContext? Context { get; private set; }
///
@@ -238,6 +229,7 @@ INotificationPublisher notificationPublisher
Groups = new ADGroupSearcher(this);
OUs = new ADOUSearcher(this);
Printers = new ADPrinterSearcher(this);
+ BitLocker = new ADBitLockerSearcher(this);
Computers = new ADComputerSearcher(this, _wmiFactory);
}
///
@@ -265,7 +257,7 @@ public ActiveDirectoryContext(ActiveDirectoryContext activeDirectoryContextSeed)
Groups = new ADGroupSearcher(this);
OUs = new ADOUSearcher(this);
Printers = new ADPrinterSearcher(this);
-
+ BitLocker = new ADBitLockerSearcher(this);
Computers = new ADComputerSearcher(this, activeDirectoryContextSeed._wmiFactory);
}
private DirectoryContext DirectoryContext => new DirectoryContext(
diff --git a/BLAZAMActiveDirectory/Adapters/ADBitLockerRecovery.cs b/BLAZAMActiveDirectory/Adapters/ADBitLockerRecovery.cs
new file mode 100644
index 00000000..23fa4927
--- /dev/null
+++ b/BLAZAMActiveDirectory/Adapters/ADBitLockerRecovery.cs
@@ -0,0 +1,38 @@
+
+using System.Net.NetworkInformation;
+using System.Net;
+using BLAZAM.Logger;
+using BLAZAM.ActiveDirectory.Interfaces;
+using BLAZAM.Database.Models;
+using System.Net.Sockets;
+using BLAZAM.Common.Data;
+
+namespace BLAZAM.ActiveDirectory.Adapters
+{
+ public class ADBitLockerRecovery : DirectoryEntryAdapter, IADBitLockerRecovery
+ {
+
+
+ public Guid? RecoveryId
+ {
+ get
+ {
+ var rawData = GetProperty("msFVE-RecoveryGuid");
+ var id = new Guid(rawData);
+ return id;
+ }
+
+
+ }
+
+ public string? RecoveryPassword
+ {
+ get
+ {
+ return GetStringProperty("msFVE-RecoveryPassword");
+ }
+ }
+
+ // public override ActiveDirectoryObjectType ObjectType => ActiveDirectoryObjectType.BitLocker;
+ }
+}
diff --git a/BLAZAMActiveDirectory/Adapters/ADComputer.cs b/BLAZAMActiveDirectory/Adapters/ADComputer.cs
index a02ede4e..075b6134 100644
--- a/BLAZAMActiveDirectory/Adapters/ADComputer.cs
+++ b/BLAZAMActiveDirectory/Adapters/ADComputer.cs
@@ -5,6 +5,8 @@
using BLAZAM.ActiveDirectory.Interfaces;
using BLAZAM.Database.Models;
using System.Net.Sockets;
+using BLAZAM.Database.Models.Permissions;
+using BLAZAM.Common.Data;
namespace BLAZAM.ActiveDirectory.Adapters
{
@@ -17,7 +19,7 @@ private WmiConnection? wmiConnection
get
{
if (CanonicalName == null) return null;
- return new WmiConnection(Directory.Computers.WmiFactory.CreateWmiConnection(CanonicalName),this);
+ return new WmiConnection(Directory.Computers.WmiFactory.CreateWmiConnection(CanonicalName), this);
}
}
private CancellationTokenSource cts;
@@ -27,6 +29,12 @@ public ADComputer()
}
+ public async Task?> GetBitLockerRecoveryAsync()
+ {
+ var recovery = await Directory.BitLocker.FindByComputerAsync(this);
+ return recovery;
+ }
+
public string? OperatingSystem
{
get
@@ -56,10 +64,10 @@ public virtual bool? IsOnline
OnOnlineChanged?.Invoke((bool)value);
}
}
- public List Services => wmiConnection?.Services?? new ();
+ public List Services => wmiConnection?.Services ?? new();
public ComputerMemory Memory => wmiConnection?.Memory ?? new();
public int Processor => wmiConnection?.Processor ?? 0;
- public double MemoryUsedPercent => wmiConnection?.Memory.PercentUsed ?? 0 ;
+ public double MemoryUsedPercent => wmiConnection?.Memory.PercentUsed ?? 0;
public List GetDrives()
{
if (wmiConnection == null) return new();
@@ -92,11 +100,32 @@ public List SharedPrinters
{
get
{
- return wmiConnection?.SharePrinters ?? new ();
+ return wmiConnection?.SharePrinters ?? new();
}
}
+ public bool CanReadBitLocker
+ {
+ get
+ {
+ return HasPermission(p => p.Where(pm =>
+ pm.AccessLevels.Any(al =>
+ al.ObjectMap.Any(om =>
+ om.ObjectType == ActiveDirectoryObjectType.BitLocker &&
+ om.ObjectAccessLevel.Level > ObjectAccessLevels.Deny.Level
+ ))),
+ p => p.Where(pm =>
+ pm.AccessLevels.Any(al =>
+ al.ObjectMap.Any(om =>
+ om.ObjectType == ActiveDirectoryObjectType.BitLocker &&
+ om.ObjectAccessLevel.Level == ObjectAccessLevels.Deny.Level
+ )))
+ );
+ }
+
+ }
+
///
/// Rename this computer
@@ -113,7 +142,7 @@ public List SharedPrinters
}
catch (Exception ex)
{
- Loggers.ActiveDirectryLogger.Error(ex.Message + " {@Error}",ex);
+ Loggers.ActiveDirectryLogger.Error(ex.Message + " {@Error}", ex);
}
return false;
@@ -155,7 +184,7 @@ private void Ping(int timeout = 5000)
{
try
{
- if (IPHostEntry == null && !cts.IsCancellationRequested && CanonicalName!=null)
+ if (IPHostEntry == null && !cts.IsCancellationRequested && CanonicalName != null)
{
IPHostEntry = Dns.GetHostEntry(CanonicalName);
Task.Delay(60000).ContinueWith((s) =>
@@ -170,7 +199,7 @@ private void Ping(int timeout = 5000)
{
try
{
- if (cts.IsCancellationRequested || CanonicalName ==null) return;
+ if (cts.IsCancellationRequested || CanonicalName == null) return;
PingReply response = ping.Send(CanonicalName, timeout);
if (response != null)
@@ -202,11 +231,11 @@ private void Ping(int timeout = 5000)
}
catch (Exception ex)
{
- Loggers.ActiveDirectryLogger.Error(ex.Message + " {@Error}", ex );
+ Loggers.ActiveDirectryLogger.Error(ex.Message + " {@Error}", ex);
}
}
-
+
public override void Dispose()
{
base.Dispose();
diff --git a/BLAZAMActiveDirectory/Adapters/ADOrganizationalUnit.cs b/BLAZAMActiveDirectory/Adapters/ADOrganizationalUnit.cs
index d6440eb1..62b8f171 100644
--- a/BLAZAMActiveDirectory/Adapters/ADOrganizationalUnit.cs
+++ b/BLAZAMActiveDirectory/Adapters/ADOrganizationalUnit.cs
@@ -58,7 +58,7 @@ public IEnumerable SubOUs
- public override string SearchUri => "/search/" + HttpUtility.UrlEncode(DN);
+ public override string SearchUri => "/view/" + HttpUtility.UrlEncode(DN);
public override string? CanonicalName
{
diff --git a/BLAZAMActiveDirectory/Adapters/DirectoryEntryAdapter.cs b/BLAZAMActiveDirectory/Adapters/DirectoryEntryAdapter.cs
index b25e61fe..66d48649 100644
--- a/BLAZAMActiveDirectory/Adapters/DirectoryEntryAdapter.cs
+++ b/BLAZAMActiveDirectory/Adapters/DirectoryEntryAdapter.cs
@@ -32,7 +32,7 @@ public virtual string SearchUri
{
get
{
- return "/search/" + CanonicalName;
+ return "/view/" + CanonicalName;
}
}
@@ -166,7 +166,7 @@ public void EnsureDirectoryEntry()
}
}
- public ActiveDirectoryObjectType ObjectType
+ public virtual ActiveDirectoryObjectType ObjectType
{
get
{
@@ -192,6 +192,11 @@ public ActiveDirectoryObjectType ObjectType
{
return ActiveDirectoryObjectType.Printer;
}
+ if (Classes.Contains("msFVE-RecoveryInformation"))
+ {
+ return ActiveDirectoryObjectType.BitLocker;
+
+ }
}
return ActiveDirectoryObjectType.OU;
@@ -434,13 +439,12 @@ public virtual void MoveTo(IADOrganizationalUnit parentOUToMoveTo)
public virtual string? OU { get => DirectoryTools.DnToOu(DN) ?? DirectoryTools.DnToOu(ADSPath); }
- public IADOrganizationalUnit? GetParent()
+ public IDirectoryEntryAdapter? GetParent()
{
if (DirectoryEntry == null || DirectoryEntry.Parent == null) return null;
- var parent = new ADOrganizationalUnit();
+ var parent = DirectoryEntry.Parent.Encapsulate();
- parent.Parse(Directory, DirectoryEntry.Parent);
return parent;
@@ -577,26 +581,32 @@ public virtual IEnumerable Children
if (child.Properties["objectClass"].Contains("top"))
{
- if (child.Properties["objectClass"].Contains("computer"))
+ var objectClass = child.Properties["objectClass"];
+ if (objectClass.Contains("computer"))
{
thisObject = new ADComputer();
}
- else if (child.Properties["objectClass"].Contains("user"))
+ else if (objectClass.Contains("user"))
{
thisObject = new ADUser();
}
- else if (child.Properties["objectClass"].Contains("organizationalUnit"))
+ else if (objectClass.Contains("organizationalUnit"))
{
thisObject = new ADOrganizationalUnit();
}
- else if (child.Properties["objectClass"].Contains("group"))
+ else if (objectClass.Contains("group"))
{
thisObject = new ADGroup();
}
- else if (child.Properties["objectClass"].Contains("printQueue"))
+ else if (objectClass.Contains("printQueue"))
{
thisObject = new ADPrinter();
}
+
+ else if (objectClass.Contains("msFVE-RecoveryInformation"))
+ {
+ thisObject = new ADBitLockerRecovery();
+ }
if (thisObject != null)
{
thisObject.Parse(directory: Directory, directoryEntry: child);
@@ -608,6 +618,7 @@ public virtual IEnumerable Children
thisObject = null;
}
+ directoryEntries.OrderBy(x=>x.CanonicalName).OrderBy(x=>x.ObjectType);
CachedChildren = directoryEntries;
}
return CachedChildren;
diff --git a/BLAZAMActiveDirectory/GlobalSuppressions.cs b/BLAZAMActiveDirectory/GlobalSuppressions.cs
index 86e0de26..8f6f8842 100644
--- a/BLAZAMActiveDirectory/GlobalSuppressions.cs
+++ b/BLAZAMActiveDirectory/GlobalSuppressions.cs
@@ -62,3 +62,4 @@
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:BLAZAM.Helpers.ActiveDirectoryHelpers.Encapsulate(System.DirectoryServices.SearchResultCollection)~System.Collections.Generic.List{BLAZAM.ActiveDirectory.Interfaces.IDirectoryEntryAdapter}")]
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:BLAZAM.Helpers.ActiveDirectoryHelpers.Encapsulate(System.DirectoryServices.DirectoryEntries)~System.Collections.Generic.List{BLAZAM.ActiveDirectory.Interfaces.IDirectoryEntryAdapter}")]
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:BLAZAM.ActiveDirectory.ActiveDirectoryContext.KeepAlive(System.Object)")]
+[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:BLAZAM.Helpers.ActiveDirectoryHelpers.Encapsulate(System.DirectoryServices.DirectoryEntry)~BLAZAM.ActiveDirectory.Interfaces.IDirectoryEntryAdapter")]
diff --git a/BLAZAMActiveDirectory/Helpers/ActiveDirectoryHelpers.cs b/BLAZAMActiveDirectory/Helpers/ActiveDirectoryHelpers.cs
index f5ce5226..cd7dd547 100644
--- a/BLAZAMActiveDirectory/Helpers/ActiveDirectoryHelpers.cs
+++ b/BLAZAMActiveDirectory/Helpers/ActiveDirectoryHelpers.cs
@@ -2,6 +2,7 @@
using BLAZAM.ActiveDirectory.Adapters;
using BLAZAM.ActiveDirectory.Interfaces;
using BLAZAM.Common.Data;
+using BLAZAM.Logger;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
@@ -164,6 +165,10 @@ public static List Encapsulate(this SearchResultCollecti
{
thisObject = new ADPrinter();
}
+ else if (sr.Properties["objectClass"].Contains("msFVE-RecoveryInformation"))
+ {
+ thisObject = new ADBitLockerRecovery();
+ }
if (thisObject != null)
{
thisObject.Parse(directory: ActiveDirectoryContext.Instance, searchResult: sr);
@@ -180,14 +185,65 @@ public static List Encapsulate(this SearchResultCollecti
return objects;
}
///
- /// Encapsulates a raw DirectoryEntry search's within a of the appropriate entry type
+ /// Encapsulates a raw DirectoryEntry within a of the appropriate entry type
///
- ///
- /// This is used when getting child ojects from a OU
- ///
///
- /// A list of whose types correspond the directory object type they encapsulate
- public static List Encapsulate(this DirectoryEntries r)
+ /// A whose types correspond the directory object type they encapsulate
+
+ public static IDirectoryEntryAdapter? Encapsulate(this DirectoryEntry sr)
+ {
+ IDirectoryEntryAdapter? thisObject = null;
+
+ if (sr.Properties["objectClass"].Contains("top"))
+ {
+ if (sr.Properties["objectClass"].Contains("computer"))
+ {
+ thisObject = new ADComputer();
+ }
+ else if (sr.Properties["objectClass"].Contains("user"))
+ {
+ thisObject = new ADUser();
+ }
+ else if (sr.Properties["objectClass"].Contains("organizationalUnit"))
+ {
+ thisObject = new ADOrganizationalUnit();
+ }
+ else if (sr.Properties["objectClass"].Contains("group"))
+ {
+ thisObject = new ADGroup();
+ }
+ else if (sr.Properties["objectClass"].Contains("printQueue"))
+ {
+ thisObject = new ADPrinter();
+ }
+ else if (sr.Properties["objectClass"].Contains("msFVE-RecoveryInformation"))
+ {
+ thisObject = new ADBitLockerRecovery();
+ }
+ if (thisObject != null)
+ {
+ thisObject.Parse(directory: ActiveDirectoryContext.Instance, directoryEntry: sr);
+
+ return thisObject;
+
+ }
+ else
+ {
+ Loggers.ActiveDirectryLogger.Warning("Unable to match ad object type. {Object}", sr);
+
+ }
+ }
+ return null;
+ }
+ ///
+ /// Encapsulates a raw DirectoryEntry search's within a of the appropriate entry type
+ ///
+ ///
+ /// This is used when getting child ojects from a OU
+ ///
+ ///
+ /// A list of whose types correspond the directory object type they encapsulate
+ public static List Encapsulate(this DirectoryEntries r)
{
List objects = new();
@@ -195,40 +251,11 @@ public static List Encapsulate(this DirectoryEntries r)
if (r != null)
{
- IDirectoryEntryAdapter? thisObject = null;
foreach (DirectoryEntry sr in r)
{
- if (sr.Properties["objectClass"].Contains("top"))
- {
- if (sr.Properties["objectClass"].Contains("computer"))
- {
- thisObject = new ADComputer();
- }
- else if (sr.Properties["objectClass"].Contains("user"))
- {
- thisObject = new ADUser();
- }
- else if (sr.Properties["objectClass"].Contains("organizationalUnit"))
- {
- thisObject = new ADOrganizationalUnit();
- }
- else if (sr.Properties["objectClass"].Contains("group"))
- {
- thisObject = new ADGroup();
- }
- else if (sr.Properties["objectClass"].Contains("printQueue"))
- {
- thisObject = new ADPrinter();
- }
- if (thisObject != null)
- {
- thisObject.Parse(directory: ActiveDirectoryContext.Instance, directoryEntry: sr);
-
- objects.Add(thisObject);
-
- }
- }
- thisObject = null;
+ var encapsulated = Encapsulate(sr);
+ if(encapsulated != null)
+ objects.Add(encapsulated);
}
}
diff --git a/BLAZAMActiveDirectory/Interfaces/IADBitLockerRecovery.cs b/BLAZAMActiveDirectory/Interfaces/IADBitLockerRecovery.cs
new file mode 100644
index 00000000..092dc043
--- /dev/null
+++ b/BLAZAMActiveDirectory/Interfaces/IADBitLockerRecovery.cs
@@ -0,0 +1,9 @@
+
+namespace BLAZAM.ActiveDirectory.Interfaces
+{
+ public interface IADBitLockerRecovery:IDirectoryEntryAdapter
+ {
+ Guid? RecoveryId { get; }
+ string? RecoveryPassword { get; }
+ }
+}
\ No newline at end of file
diff --git a/BLAZAMActiveDirectory/Interfaces/IADBitLockerSearcher.cs b/BLAZAMActiveDirectory/Interfaces/IADBitLockerSearcher.cs
new file mode 100644
index 00000000..dc9b1688
--- /dev/null
+++ b/BLAZAMActiveDirectory/Interfaces/IADBitLockerSearcher.cs
@@ -0,0 +1,16 @@
+using BLAZAM.Common.Data.Services;
+
+namespace BLAZAM.ActiveDirectory.Interfaces
+{
+ ///
+ /// A searcher class for BitLocker objects in an
+ ///
+ public interface IADBitLockerSearcher
+ {
+
+ List FindByRecoveryId(string searchTerm);
+ Task> FindByRecoveryIdAsync(string searchTerm);
+ List FindByComputer(IADComputer computer);
+ Task> FindByComputerAsync(IADComputer computer);
+ }
+}
\ No newline at end of file
diff --git a/BLAZAMActiveDirectory/Interfaces/IADComputer.cs b/BLAZAMActiveDirectory/Interfaces/IADComputer.cs
index 50845d97..a7ad1d06 100644
--- a/BLAZAMActiveDirectory/Interfaces/IADComputer.cs
+++ b/BLAZAMActiveDirectory/Interfaces/IADComputer.cs
@@ -20,6 +20,7 @@ public interface IADComputer : IAccountDirectoryAdapter
/// Null indicates that the check has not yet completed.
///
bool? IsOnline { get; }
+ bool CanReadBitLocker { get; }
///
/// If this computer is online, this is the resolved IP address from the server.
/// Otherwise, this is null
@@ -49,6 +50,8 @@ public interface IADComputer : IAccountDirectoryAdapter
///
List SharedPrinters { get; }
+ Task?> GetBitLockerRecoveryAsync();
+
///
/// Gets the drive details from this computer
///
diff --git a/BLAZAMActiveDirectory/Interfaces/IActiveDirectory.cs b/BLAZAMActiveDirectory/Interfaces/IActiveDirectory.cs
index ce151b15..0cebb76e 100644
--- a/BLAZAMActiveDirectory/Interfaces/IActiveDirectory.cs
+++ b/BLAZAMActiveDirectory/Interfaces/IActiveDirectory.cs
@@ -62,6 +62,10 @@ public interface IActiveDirectoryContext:IDisposable
/// Provides Computer search functions
///
IADComputerSearcher Computers { get; }
+ ///
+ /// Provides Computer search functions
+ ///
+ IADBitLockerSearcher BitLocker { get; }
///
/// Called when the connection state of the Active Directory server has
diff --git a/BLAZAMActiveDirectory/Interfaces/IDirectoryEntryAdapter.cs b/BLAZAMActiveDirectory/Interfaces/IDirectoryEntryAdapter.cs
index 7e80980a..5de65d5d 100644
--- a/BLAZAMActiveDirectory/Interfaces/IDirectoryEntryAdapter.cs
+++ b/BLAZAMActiveDirectory/Interfaces/IDirectoryEntryAdapter.cs
@@ -309,7 +309,7 @@ public interface IDirectoryEntryAdapter : IDisposable
/// Get's the parent of this entry
///
///
- IADOrganizationalUnit? GetParent();
+ IDirectoryEntryAdapter? GetParent();
///
/// Wrapper method for the base
diff --git a/BLAZAMActiveDirectory/Searchers/ADBitLockerSearcher.cs b/BLAZAMActiveDirectory/Searchers/ADBitLockerSearcher.cs
new file mode 100644
index 00000000..90f3a72d
--- /dev/null
+++ b/BLAZAMActiveDirectory/Searchers/ADBitLockerSearcher.cs
@@ -0,0 +1,61 @@
+using BLAZAM.ActiveDirectory;
+using BLAZAM.ActiveDirectory.Adapters;
+using BLAZAM.ActiveDirectory.Interfaces;
+using BLAZAM.Common.Data;
+using BLAZAM.Common.Data.Services;
+
+namespace BLAZAM.ActiveDirectory.Searchers
+{
+ public class ADBitLockerSearcher : ADSearcher, IADBitLockerSearcher
+ {
+
+ public ADBitLockerSearcher(IActiveDirectoryContext directory) : base(directory)
+ {
+ }
+
+
+ public List FindByRecoveryId(string searchTerm)
+ {
+ var searchFields = new ADSearchFields();
+ searchFields.BitLockerRecoveryId = searchTerm;
+ return new ADSearch()
+ {
+ ObjectTypeFilter = ActiveDirectoryObjectType.BitLocker,
+ EnabledOnly = false,
+ Fields = searchFields
+
+ }.Search();
+ }
+
+ public async Task> FindByRecoveryIdAsync(string searchTerm)
+ {
+ return await Task.Run(() =>
+ {
+ return FindByRecoveryId(searchTerm);
+ });
+ }
+
+ public List FindByComputer(IADComputer computer)
+ {
+ var children = computer.Children;
+ return children.Where(c => c is IADBitLockerRecovery).Cast().ToList();
+ var searchFields = new ADSearchFields();
+ searchFields.CN = "*"+computer.DN;
+ return new ADSearch()
+ {
+ ObjectTypeFilter = ActiveDirectoryObjectType.BitLocker,
+ EnabledOnly = false,
+ Fields = searchFields
+
+ }.Search();
+ }
+
+ public async Task> FindByComputerAsync(IADComputer computer)
+ {
+ return await Task.Run(() =>
+ {
+ return FindByComputer(computer);
+ });
+ }
+ }
+}
diff --git a/BLAZAMActiveDirectory/Searchers/ADGroupSearcher.cs b/BLAZAMActiveDirectory/Searchers/ADGroupSearcher.cs
index 53efd152..d102d24d 100644
--- a/BLAZAMActiveDirectory/Searchers/ADGroupSearcher.cs
+++ b/BLAZAMActiveDirectory/Searchers/ADGroupSearcher.cs
@@ -193,9 +193,18 @@ public List GetGroupMembers(IADGroup group)
}
- public bool IsAMemberOf(IADGroup? group, IGroupableDirectoryAdapter? userOrGroup, bool v, bool ignoreDisabledUsers = true)
+ public bool IsAMemberOf(IADGroup group, IGroupableDirectoryAdapter? userOrGroup, bool v, bool ignoreDisabledUsers = true)
{
+ return new ADSearch()
+ {
+ Fields = new()
+ {
+ DN = userOrGroup.DN,
+ NestedMemberOf = group
+ },
+ ExactMatch = false
+ }.Search().Count>0;
string UserSearchFieldsQuery = "(&(memberOf:1.2.840.113556.1.4.1941:=" + group.DN + ")(distinguishedName=" + userOrGroup.DN + "))";
return SearchObjects(UserSearchFieldsQuery, userOrGroup.ObjectType, 50, ignoreDisabledUsers)?.Count > 0;
diff --git a/BLAZAMActiveDirectory/Searchers/ADSearch.cs b/BLAZAMActiveDirectory/Searchers/ADSearch.cs
index 469136d1..19477354 100644
--- a/BLAZAMActiveDirectory/Searchers/ADSearch.cs
+++ b/BLAZAMActiveDirectory/Searchers/ADSearch.cs
@@ -97,7 +97,7 @@ public List Search()
{
return Search();
}
-
+
public async Task> SearchAsync()
{
return await SearchAsync();
@@ -178,6 +178,13 @@ public async Task> SearchAsync()
if (GeneralSearchTerm != null)
FilterQuery = "(|(samaccountname=*" + GeneralSearchTerm + "*)(anr=*" + GeneralSearchTerm + "*)(distinguishedName=*" + GeneralSearchTerm + "*))";
+ break;
+ case ActiveDirectoryObjectType.BitLocker:
+ searcher.Filter = "(&(objectCategory=*msFVE-RecoveryInformation*))";
+ if (GeneralSearchTerm != null)
+
+ searcher.Filter = $"(name=*{GeneralSearchTerm}*)";
+
break;
case ActiveDirectoryObjectType.OU:
searcher.VirtualListView = null;
@@ -214,7 +221,8 @@ public async Task> SearchAsync()
FilterQuery += $"(objectSid={Fields.SID})";
if (Fields.NestedMemberOf != null)
FilterQuery += $"(memberOf:1.2.840.113556.1.4.1941:={Fields.NestedMemberOf.DN})";
-
+ if (Fields.BitLockerRecoveryId != null)
+ FilterQuery += $"(name=*{Fields.BitLockerRecoveryId}*)";
diff --git a/BLAZAMActiveDirectory/Searchers/ADSearchFields.cs b/BLAZAMActiveDirectory/Searchers/ADSearchFields.cs
index dd6274e4..98b47430 100644
--- a/BLAZAMActiveDirectory/Searchers/ADSearchFields.cs
+++ b/BLAZAMActiveDirectory/Searchers/ADSearchFields.cs
@@ -1,4 +1,4 @@
-using BLAZAM.ActiveDirectory.Adapters;
+using BLAZAM.ActiveDirectory.Interfaces;
namespace BLAZAM.ActiveDirectory.Searchers
{
@@ -27,6 +27,7 @@ public class ADSearchFields
public string? CN { get; set; }
public string? MemberOf { get; set; }
- public ADGroup? NestedMemberOf { get; internal set; }
+ public IADGroup? NestedMemberOf { get; internal set; }
+ public string BitLockerRecoveryId { get; internal set; }
}
}
\ No newline at end of file
diff --git a/BLAZAMCommon.Tests/BLAZAMCommon.Tests.csproj b/BLAZAMCommon.Tests/BLAZAMCommon.Tests.csproj
index 821c8aa7..6bbe6bfe 100644
--- a/BLAZAMCommon.Tests/BLAZAMCommon.Tests.csproj
+++ b/BLAZAMCommon.Tests/BLAZAMCommon.Tests.csproj
@@ -1,34 +1,34 @@
-
- net6.0
- enable
- enable
+
+ net6.0
+ enable
+ enable
- false
-
+ false
+
-
-
-
-
-
-
-
-
-
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
-
+
+
+
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
-
-
-
+
+
+
diff --git a/BLAZAMCommon/BLAZAMCommon.csproj b/BLAZAMCommon/BLAZAMCommon.csproj
index 3a215e67..8c1d33f6 100644
--- a/BLAZAMCommon/BLAZAMCommon.csproj
+++ b/BLAZAMCommon/BLAZAMCommon.csproj
@@ -18,26 +18,26 @@
-
-
-
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
diff --git a/BLAZAMCommon/Data/ActiveDirectoryObjectType.cs b/BLAZAMCommon/Data/ActiveDirectoryObjectType.cs
index 38b8c1e9..86e1869d 100644
--- a/BLAZAMCommon/Data/ActiveDirectoryObjectType.cs
+++ b/BLAZAMCommon/Data/ActiveDirectoryObjectType.cs
@@ -1,7 +1,9 @@
namespace BLAZAM.Common.Data
{
- public enum ActiveDirectoryObjectType { All, User, Group, Computer, OU, Printer }
+ public enum ActiveDirectoryObjectType { All, User, Group, Computer, OU, Printer,
+ BitLocker
+ }
}
diff --git a/BLAZAMDatabase/Add-AppMigration.ps1 b/BLAZAMDatabase/Add-AppMigration.ps1
index 2b7b6456..c61b68ef 100644
--- a/BLAZAMDatabase/Add-AppMigration.ps1
+++ b/BLAZAMDatabase/Add-AppMigration.ps1
@@ -6,20 +6,20 @@ $sqlName = $Name + "Sql";
$mysqlName = $Name + "MySql";
$sqliteName = $Name + "Sqlite";
try {
- Add-Migration $sqliteName -OutputDir Migrations/Sqlite -Context SqliteDatabaseContext
+ Add-Migration -Name $sqliteName -OutputDir Migrations/Sqlite -Context SqliteDatabaseContext
} catch {
exit
}
try {
- Add-Migration $sqlName -OutputDir Migrations/Sql -Context SqlDatabaseContext
+ Add-Migration -Name $sqlName -OutputDir Migrations/Sql -Context SqlDatabaseContext
} catch {
Remove-Migration -Context SqliteDatabaseContext
exit
}
try {
- Add-Migration $mysqlName -OutputDir Migrations/MySql -Context MySqlDatabaseContext
+ Add-Migration -Name $mysqlName -OutputDir Migrations/MySql -Context MySqlDatabaseContext
} catch {
Remove-Migration -Context SqliteDatabaseContext
diff --git a/BLAZAMDatabase/BLAZAMDatabase.csproj b/BLAZAMDatabase/BLAZAMDatabase.csproj
index e8c174ae..5663a9ab 100644
--- a/BLAZAMDatabase/BLAZAMDatabase.csproj
+++ b/BLAZAMDatabase/BLAZAMDatabase.csproj
@@ -8,19 +8,19 @@
-
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
diff --git a/BLAZAMDatabase/Context/AppDatabaseFactory.cs b/BLAZAMDatabase/Context/AppDatabaseFactory.cs
index 9505af48..4ae78ef5 100644
--- a/BLAZAMDatabase/Context/AppDatabaseFactory.cs
+++ b/BLAZAMDatabase/Context/AppDatabaseFactory.cs
@@ -3,6 +3,7 @@
using BLAZAM.Database.Exceptions;
using BLAZAM.Database.Models.Permissions;
using BLAZAM.Logger;
+using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using System.Net.WebSockets;
@@ -65,41 +66,57 @@ private void SeedData()
private void SetupDenyAll(IDatabaseContext seedContext)
{
- bool saveRequired = false;
- var denyAll = seedContext.AccessLevels.First(x => x.Id == 1);
- if (denyAll != null)
- {
- foreach (var adObjectType in Enum.GetValues(typeof(ActiveDirectoryObjectType)))
+ Task.Run(() => {
+ bool saveRequired = false;
+ try
{
- if ((ActiveDirectoryObjectType)adObjectType != ActiveDirectoryObjectType.All)
+ var denyAll = seedContext.AccessLevels.First(x => x.Id == 1);
+ if (denyAll != null)
{
- if (denyAll.ObjectMap.Any(x => x.ObjectType == (ActiveDirectoryObjectType)adObjectType))
+ foreach (var adObjectType in Enum.GetValues(typeof(ActiveDirectoryObjectType)))
{
- var eexisingObjectMap = denyAll.ObjectMap.First(x => x.ObjectType == (ActiveDirectoryObjectType)adObjectType);
- if (eexisingObjectMap.ObjectAccessLevelId != ObjectAccessLevels.Deny.Id)
+ if ((ActiveDirectoryObjectType)adObjectType != ActiveDirectoryObjectType.All)
{
- denyAll.ObjectMap.Remove(eexisingObjectMap);
- saveRequired = true;
+ if (denyAll.ObjectMap.Any(x => x.ObjectType == (ActiveDirectoryObjectType)adObjectType))
+ {
+ var eexisingObjectMap = denyAll.ObjectMap.First(x => x.ObjectType == (ActiveDirectoryObjectType)adObjectType);
+ if (eexisingObjectMap.ObjectAccessLevelId != ObjectAccessLevels.Deny.Id)
+ {
+ denyAll.ObjectMap.Remove(eexisingObjectMap);
+ saveRequired = true;
+ }
+ }
+ if (!denyAll.ObjectMap.Any(x => x.ObjectType == (ActiveDirectoryObjectType)adObjectType && x.ObjectAccessLevel.Id == ObjectAccessLevels.Deny.Id))
+ {
+ denyAll.ObjectMap.Add(new()
+ {
+ ObjectType = (ActiveDirectoryObjectType)adObjectType,
+ ObjectAccessLevelId = ObjectAccessLevels.Deny.Id,
+ });
+ saveRequired = true;
+
+ }
}
}
- if (!denyAll.ObjectMap.Any(x => x.ObjectType == (ActiveDirectoryObjectType)adObjectType && x.ObjectAccessLevel.Id == ObjectAccessLevels.Deny.Id))
- {
- denyAll.ObjectMap.Add(new()
- {
- ObjectType = (ActiveDirectoryObjectType)adObjectType,
- ObjectAccessLevelId = ObjectAccessLevels.Deny.Id,
- });
- saveRequired = true;
- }
}
+
+ }
+ catch (SqlException ex)
+ {
+ Loggers.DatabaseLogger.Warning("Error attempting to seed denyAll {@Error}", ex);
}
+ catch (Exception ex)
+ {
+ Loggers.DatabaseLogger.Error("Unexpected error attempting to seed denyAll {@Error}", ex);
- }
- if (saveRequired)
- {
- seedContext.SaveChanges();
- }
+ }
+ if (saveRequired)
+ {
+ seedContext.SaveChanges();
+ }
+ });
+
}
private void StartDatabaseCache()
diff --git a/BLAZAMDatabase/Migrations/MySql/20240704204619_Add_DelegateName_And_EmailTemplateChanges_MySql.Designer.cs b/BLAZAMDatabase/Migrations/MySql/20240704204619_Add_DelegateName_And_EmailTemplateChanges_MySql.Designer.cs
new file mode 100644
index 00000000..aa2dc06a
--- /dev/null
+++ b/BLAZAMDatabase/Migrations/MySql/20240704204619_Add_DelegateName_And_EmailTemplateChanges_MySql.Designer.cs
@@ -0,0 +1,1817 @@
+//
+using System;
+using BLAZAM.Database.Context;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace BLAZAM.Database.Migrations.MySql
+{
+ [DbContext(typeof(MySqlDatabaseContext))]
+ [Migration("20240704204619_Add_DelegateName_And_EmailTemplateChanges_MySql")]
+ partial class Add_DelegateName_And_EmailTemplateChanges_MySql
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "7.0.20")
+ .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+ modelBuilder.Entity("AccessLevelFieldAccessMapping", b =>
+ {
+ b.Property("AccessLevelsId")
+ .HasColumnType("int");
+
+ b.Property("FieldMapId")
+ .HasColumnType("int");
+
+ b.HasKey("AccessLevelsId", "FieldMapId");
+
+ b.HasIndex("FieldMapId");
+
+ b.ToTable("AccessLevelFieldAccessMapping");
+ });
+
+ modelBuilder.Entity("AccessLevelObjectAccessMapping", b =>
+ {
+ b.Property("AccessLevelsId")
+ .HasColumnType("int");
+
+ b.Property("ObjectMapId")
+ .HasColumnType("int");
+
+ b.HasKey("AccessLevelsId", "ObjectMapId");
+
+ b.HasIndex("ObjectMapId");
+
+ b.ToTable("AccessLevelObjectAccessMapping");
+ });
+
+ modelBuilder.Entity("AccessLevelPermissionMapping", b =>
+ {
+ b.Property("AccessLevelsId")
+ .HasColumnType("int");
+
+ b.Property("PermissionMapsId")
+ .HasColumnType("int");
+
+ b.HasKey("AccessLevelsId", "PermissionMapsId");
+
+ b.HasIndex("PermissionMapsId");
+
+ b.ToTable("AccessLevelPermissionMapping");
+ });
+
+ modelBuilder.Entity("AppUserChatRoom", b =>
+ {
+ b.Property("ChatRoomId")
+ .HasColumnType("int");
+
+ b.Property("MembersId")
+ .HasColumnType("int");
+
+ b.HasKey("ChatRoomId", "MembersId");
+
+ b.HasIndex("MembersId");
+
+ b.ToTable("AppUserChatRoom");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.ADSettings", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("int");
+
+ b.Property("ApplicationBaseDN")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("FQDN")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("Password")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("ServerAddress")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("ServerPort")
+ .HasColumnType("int");
+
+ b.Property("UseTLS")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Username")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("ActiveDirectorySettings", t =>
+ {
+ t.HasCheckConstraint("CK_Table_Column", "Id = 1");
+ });
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.ActiveDirectoryField", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("DisplayName")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("FieldName")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("FieldType")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.ToTable("ActiveDirectoryFields");
+
+ b.HasData(
+ new
+ {
+ Id = 1,
+ DisplayName = "Last Name",
+ FieldName = "sn",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 2,
+ DisplayName = "First Name",
+ FieldName = "givenname",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 3,
+ DisplayName = "Office",
+ FieldName = "physicalDeliveryOfficeName",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 4,
+ DisplayName = "Employee ID",
+ FieldName = "employeeId",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 5,
+ DisplayName = "Home Directory",
+ FieldName = "homeDirectory",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 6,
+ DisplayName = "Logon Script Path",
+ FieldName = "scriptPath",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 7,
+ DisplayName = "Profile Path",
+ FieldName = "profilePath",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 8,
+ DisplayName = "Home Phone Number",
+ FieldName = "homePhone",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 9,
+ DisplayName = "Street Address",
+ FieldName = "streetAddress",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 10,
+ DisplayName = "City",
+ FieldName = "l",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 11,
+ DisplayName = "State",
+ FieldName = "st",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 12,
+ DisplayName = "Zip Code",
+ FieldName = "postalCode",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 13,
+ DisplayName = "Site",
+ FieldName = "site",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 14,
+ DisplayName = "Name",
+ FieldName = "name",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 15,
+ DisplayName = "Username",
+ FieldName = "samaccountname",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 16,
+ DisplayName = "SID",
+ FieldName = "objectSID",
+ FieldType = 2
+ },
+ new
+ {
+ Id = 17,
+ DisplayName = "E-Mail Address",
+ FieldName = "mail",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 18,
+ DisplayName = "Description",
+ FieldName = "description",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 19,
+ DisplayName = "Display Name",
+ FieldName = "displayName",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 20,
+ DisplayName = "Distinguished Name",
+ FieldName = "distinguishedName",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 21,
+ DisplayName = "Member Of",
+ FieldName = "memberOf",
+ FieldType = 4
+ },
+ new
+ {
+ Id = 22,
+ DisplayName = "Company",
+ FieldName = "company",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 23,
+ DisplayName = "Title",
+ FieldName = "title",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 24,
+ DisplayName = "User Principal Name",
+ FieldName = "userPrincipalName",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 25,
+ DisplayName = "Telephone Number",
+ FieldName = "telephoneNumber",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 26,
+ DisplayName = "PO Box",
+ FieldName = "postOfficeBox",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 27,
+ DisplayName = "Canonical Name",
+ FieldName = "cn",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 28,
+ DisplayName = "Home Drive",
+ FieldName = "homeDrive",
+ FieldType = 3
+ },
+ new
+ {
+ Id = 29,
+ DisplayName = "Department",
+ FieldName = "department",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 30,
+ DisplayName = "Middle Name",
+ FieldName = "middleName",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 31,
+ DisplayName = "Pager",
+ FieldName = "pager",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 32,
+ DisplayName = "OS",
+ FieldName = "operatingSystemVersion",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 33,
+ DisplayName = "Account Expiration",
+ FieldName = "accountExpires",
+ FieldType = 1
+ },
+ new
+ {
+ Id = 34,
+ DisplayName = "Manager",
+ FieldName = "manager",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 35,
+ DisplayName = "Photo",
+ FieldName = "thumbnail",
+ FieldType = 2
+ },
+ new
+ {
+ Id = 36,
+ DisplayName = "Log On To",
+ FieldName = "userWorkstations",
+ FieldType = 0
+ },
+ new
+ {
+ Id = 37,
+ DisplayName = "Logon Hours",
+ FieldName = "logonHours",
+ FieldType = 2
+ });
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.ActiveDirectoryFieldObjectType", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("ActiveDirectoryFieldId")
+ .HasColumnType("int");
+
+ b.Property("CustomActiveDirectoryFieldId")
+ .HasColumnType("int");
+
+ b.Property("ObjectType")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CustomActiveDirectoryFieldId");
+
+ b.ToTable("ActiveDirectoryFieldObjectMappings");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.AppSettings", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("int");
+
+ b.Property("AnalyticsId")
+ .HasColumnType("longtext");
+
+ b.Property("AppFQDN")
+ .HasColumnType("longtext");
+
+ b.Property("AppIcon")
+ .HasColumnType("longblob");
+
+ b.Property("AppName")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("AutoUpdate")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("AutoUpdateTime")
+ .HasColumnType("time(6)");
+
+ b.Property("ForceHTTPS")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("InstallationCompleted")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LastUpdateCheck")
+ .HasColumnType("datetime(6)");
+
+ b.Property("MOTD")
+ .HasColumnType("longtext");
+
+ b.Property("MyrtilleURL")
+ .HasColumnType("longtext");
+
+ b.Property("SSLCertificateCipher")
+ .HasColumnType("longtext");
+
+ b.Property("SendDeveloperAnalytics")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("SendLogsToDeveloper")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UpdateBranch")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("UpdateDomain")
+ .HasColumnType("longtext");
+
+ b.Property("UpdatePassword")
+ .HasColumnType("longtext");
+
+ b.Property("UpdateUsername")
+ .HasColumnType("longtext");
+
+ b.Property("UseUpdateCredentials")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UserHelpdeskURL")
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("AppSettings", t =>
+ {
+ t.HasCheckConstraint("CK_Table_Column", "Id = 1")
+ .HasName("CK_Table_Column1");
+ });
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Audit.DirectoryEntryAuditLog", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Action")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("AfterAction")
+ .HasColumnType("longtext");
+
+ b.Property("BeforeAction")
+ .HasColumnType("longtext");
+
+ b.Property("IpAddress")
+ .HasColumnType("longtext");
+
+ b.Property("Sid")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("Target")
+ .HasColumnType("longtext");
+
+ b.Property("Timestamp")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Username")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("DirectoryEntryAuditLogs");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Audit.LogonAuditLog", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Action")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("AfterAction")
+ .HasColumnType("longtext");
+
+ b.Property("BeforeAction")
+ .HasColumnType("longtext");
+
+ b.Property("IpAddress")
+ .HasColumnType("longtext");
+
+ b.Property("Target")
+ .HasColumnType("longtext");
+
+ b.Property("Timestamp")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Username")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("LogonAuditLog");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Audit.PermissionsAuditLog", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Action")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("AfterAction")
+ .HasColumnType("longtext");
+
+ b.Property("BeforeAction")
+ .HasColumnType("longtext");
+
+ b.Property("IpAddress")
+ .HasColumnType("longtext");
+
+ b.Property("Target")
+ .HasColumnType("longtext");
+
+ b.Property("Timestamp")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Username")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("PermissionsAuditLog");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Audit.RequestAuditLog", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Action")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("AfterAction")
+ .HasColumnType("longtext");
+
+ b.Property("BeforeAction")
+ .HasColumnType("longtext");
+
+ b.Property("IpAddress")
+ .HasColumnType("longtext");
+
+ b.Property("Target")
+ .HasColumnType("longtext");
+
+ b.Property("Timestamp")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Username")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("RequestAuditLog");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Audit.SettingsAuditLog", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Action")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("AfterAction")
+ .HasColumnType("longtext");
+
+ b.Property("BeforeAction")
+ .HasColumnType("longtext");
+
+ b.Property("IpAddress")
+ .HasColumnType("longtext");
+
+ b.Property("Target")
+ .HasColumnType("longtext");
+
+ b.Property("Timestamp")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Username")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("SettingsAuditLog");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Audit.SystemAuditLog", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Action")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("AfterAction")
+ .HasColumnType("longtext");
+
+ b.Property("BeforeAction")
+ .HasColumnType("longtext");
+
+ b.Property("IpAddress")
+ .HasColumnType("longtext");
+
+ b.Property("Target")
+ .HasColumnType("longtext");
+
+ b.Property("Timestamp")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Username")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("SystemAuditLog");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.AuthenticationSettings", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("int");
+
+ b.Property("AdminPassword")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("DuoApiHost")
+ .HasColumnType("longtext");
+
+ b.Property("DuoClientId")
+ .HasColumnType("longtext");
+
+ b.Property("DuoClientSecret")
+ .HasColumnType("longtext");
+
+ b.Property("DuoEnabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("DuoUnreachableBehavior")
+ .HasColumnType("int");
+
+ b.Property("SessionTimeout")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.ToTable("AuthenticationSettings", t =>
+ {
+ t.HasCheckConstraint("CK_Table_Column", "Id = 1")
+ .HasName("CK_Table_Column2");
+ });
+
+ b.HasData(
+ new
+ {
+ Id = 1,
+ AdminPassword = "password",
+ DuoEnabled = false,
+ DuoUnreachableBehavior = 0,
+ SessionTimeout = 15
+ });
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Chat.ChatRoom", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("CreatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("DeletedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("IsPublic")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("MembersHash")
+ .HasColumnType("bigint");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("ChatRooms");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Chat.UnreadChatMessage", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("ChatMessageId")
+ .HasColumnType("int");
+
+ b.Property("ChatRoomId")
+ .HasColumnType("int");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ChatMessageId");
+
+ b.ToTable("UnreadChatMessages");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.CustomActiveDirectoryField", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("DeletedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("DisplayName")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("FieldName")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("FieldType")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.ToTable("CustomActiveDirectoryFields");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.EmailSettings", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("int");
+
+ b.Property("AdminBcc")
+ .HasColumnType("longtext");
+
+ b.Property("Enabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("FromAddress")
+ .HasColumnType("longtext");
+
+ b.Property("FromName")
+ .HasColumnType("longtext");
+
+ b.Property("ReplyToAddress")
+ .HasColumnType("longtext");
+
+ b.Property("ReplyToName")
+ .HasColumnType("longtext");
+
+ b.Property("SMTPPassword")
+ .HasColumnType("longtext");
+
+ b.Property("SMTPPort")
+ .HasColumnType("int");
+
+ b.Property("SMTPServer")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("SMTPUsername")
+ .HasColumnType("longtext");
+
+ b.Property("UseSMTPAuth")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UseTLS")
+ .HasColumnType("tinyint(1)");
+
+ b.HasKey("Id");
+
+ b.ToTable("EmailSettings", t =>
+ {
+ t.HasCheckConstraint("CK_Table_Column", "Id = 1")
+ .HasName("CK_Table_Column3");
+ });
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.EmailTemplate", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Body")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("Subject")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("TemplateType")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.ToTable("EmailTemplates");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Permissions.AccessLevel", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("DeletedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("AccessLevels");
+
+ b.HasData(
+ new
+ {
+ Id = 1,
+ Name = "Deny All"
+ });
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Permissions.ActionAccessMapping", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("AccessLevelId")
+ .HasColumnType("int");
+
+ b.Property("AllowOrDeny")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("ObjectActionId")
+ .HasColumnType("int");
+
+ b.Property("ObjectType")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AccessLevelId");
+
+ b.HasIndex("ObjectActionId");
+
+ b.ToTable("ActionAccessMapping");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Permissions.FieldAccessLevel", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Level")
+ .HasColumnType("int");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("FieldAccessLevel");
+
+ b.HasData(
+ new
+ {
+ Id = 1,
+ Level = 10,
+ Name = "Deny"
+ },
+ new
+ {
+ Id = 2,
+ Level = 100,
+ Name = "Read"
+ },
+ new
+ {
+ Id = 3,
+ Level = 1000,
+ Name = "Edit"
+ });
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Permissions.FieldAccessMapping", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("CustomFieldId")
+ .HasColumnType("int");
+
+ b.Property("FieldAccessLevelId")
+ .HasColumnType("int");
+
+ b.Property("FieldId")
+ .HasColumnType("int");
+
+ b.Property("ObjectType")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CustomFieldId");
+
+ b.HasIndex("FieldAccessLevelId");
+
+ b.HasIndex("FieldId");
+
+ b.ToTable("AccessLevelFieldMapping");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Permissions.ObjectAccessLevel", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Level")
+ .HasColumnType("int");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("ObjectAccessLevel");
+
+ b.HasData(
+ new
+ {
+ Id = 1,
+ Level = 10,
+ Name = "Deny"
+ },
+ new
+ {
+ Id = 2,
+ Level = 1000,
+ Name = "Read"
+ });
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Permissions.ObjectAccessMapping", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("AllowDisabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("DeletedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("ObjectAccessLevelId")
+ .HasColumnType("int");
+
+ b.Property("ObjectType")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ObjectAccessLevelId");
+
+ b.ToTable("AccessLevelObjectMapping");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Permissions.ObjectAction", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Action")
+ .HasColumnType("int");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("ObjectActionFlag");
+
+ b.HasData(
+ new
+ {
+ Id = 1,
+ Action = 4,
+ Name = "Assign"
+ },
+ new
+ {
+ Id = 2,
+ Action = 3,
+ Name = "UnAssign"
+ },
+ new
+ {
+ Id = 3,
+ Action = 8,
+ Name = "Unlock"
+ },
+ new
+ {
+ Id = 4,
+ Action = 5,
+ Name = "Enable"
+ },
+ new
+ {
+ Id = 5,
+ Action = 6,
+ Name = "Disable"
+ },
+ new
+ {
+ Id = 6,
+ Action = 7,
+ Name = "Rename"
+ },
+ new
+ {
+ Id = 7,
+ Action = 0,
+ Name = "Move"
+ },
+ new
+ {
+ Id = 8,
+ Action = 2,
+ Name = "Create"
+ },
+ new
+ {
+ Id = 9,
+ Action = 1,
+ Name = "Delete"
+ });
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Permissions.PermissionDelegate", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("DelegateName")
+ .HasColumnType("longtext");
+
+ b.Property("DelegateSid")
+ .IsRequired()
+ .HasColumnType("varbinary(3072)");
+
+ b.Property("DeletedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("IsSuperAdmin")
+ .HasColumnType("tinyint(1)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DelegateSid")
+ .IsUnique();
+
+ b.ToTable("PermissionDelegate");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Permissions.PermissionMapping", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("DeletedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("OU")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("PermissionMap");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Templates.DirectoryTemplate", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("AllowCustomGroups")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("AskForAlternateEmail")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Category")
+ .HasColumnType("longtext");
+
+ b.Property("DeletedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("DisplayNameFormula")
+ .HasColumnType("longtext");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("varchar(255)");
+
+ b.Property("ObjectType")
+ .HasColumnType("int");
+
+ b.Property("ParentOU")
+ .HasColumnType("longtext");
+
+ b.Property("ParentTemplateId")
+ .HasColumnType("int");
+
+ b.Property("PasswordFormula")
+ .HasColumnType("longtext");
+
+ b.Property("RequirePasswordChange")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("SendWelcomeEmail")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UsernameFormula")
+ .HasColumnType("longtext");
+
+ b.Property("Visible")
+ .HasColumnType("tinyint(1)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Name")
+ .IsUnique();
+
+ b.HasIndex("ParentTemplateId");
+
+ b.ToTable("DirectoryTemplates");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Templates.DirectoryTemplateFieldValue", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("CustomFieldId")
+ .HasColumnType("int");
+
+ b.Property("DirectoryTemplateId")
+ .HasColumnType("int");
+
+ b.Property("Editable")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("FieldId")
+ .HasColumnType("int");
+
+ b.Property("Required")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Value")
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CustomFieldId");
+
+ b.HasIndex("DirectoryTemplateId");
+
+ b.HasIndex("FieldId");
+
+ b.ToTable("DirectoryTemplateFieldValues");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Templates.DirectoryTemplateGroup", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("DirectoryTemplateId")
+ .HasColumnType("int");
+
+ b.Property("GroupSid")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DirectoryTemplateId");
+
+ b.ToTable("DirectoryTemplateGroups");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.User.AppUser", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("APIToken")
+ .HasColumnType("longtext");
+
+ b.Property("DarkMode")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Email")
+ .HasColumnType("longtext");
+
+ b.Property("ProfilePicture")
+ .HasColumnType("longblob");
+
+ b.Property("SearchDisabledComputers")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("SearchDisabledUsers")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Theme")
+ .HasColumnType("longtext");
+
+ b.Property("UserGUID")
+ .IsRequired()
+ .HasColumnType("varchar(255)");
+
+ b.Property("Username")
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserGUID")
+ .IsUnique();
+
+ b.ToTable("UserSettings");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.User.NotificationMessage", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Created")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Dismissable")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Expires")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Level")
+ .HasColumnType("int");
+
+ b.Property("Link")
+ .HasColumnType("longtext");
+
+ b.Property("Message")
+ .HasColumnType("longtext");
+
+ b.Property("Title")
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("NotificationMessages");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.User.ReadNewsItem", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("NewsItemId")
+ .HasColumnType("double");
+
+ b.Property("NewsItemUpdatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("ReadNewsItems");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.User.UserDashboardWidget", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("Order")
+ .HasColumnType("int");
+
+ b.Property("Slot")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.Property("WidgetType")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("UserDashboardWidgets");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.User.UserFavoriteEntry", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("DN")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("UserFavoriteEntries");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.User.UserNotification", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("IsRead")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("NotificationId")
+ .HasColumnType("int");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("NotificationId");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("UserNotifications");
+ });
+
+ modelBuilder.Entity("BLAZAM.Server.Data.ChatMessage", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ b.Property("ChatRoomId")
+ .HasColumnType("int");
+
+ b.Property("Message")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("Timestamp")
+ .HasColumnType("datetime(6)");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ChatRoomId");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("ChatMessages");
+ });
+
+ modelBuilder.Entity("PermissionDelegatePermissionMapping", b =>
+ {
+ b.Property("PermissionDelegatesId")
+ .HasColumnType("int");
+
+ b.Property("PermissionsMapsId")
+ .HasColumnType("int");
+
+ b.HasKey("PermissionDelegatesId", "PermissionsMapsId");
+
+ b.HasIndex("PermissionsMapsId");
+
+ b.ToTable("PermissionDelegatePermissionMapping");
+ });
+
+ modelBuilder.Entity("AccessLevelFieldAccessMapping", b =>
+ {
+ b.HasOne("BLAZAM.Database.Models.Permissions.AccessLevel", null)
+ .WithMany()
+ .HasForeignKey("AccessLevelsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("BLAZAM.Database.Models.Permissions.FieldAccessMapping", null)
+ .WithMany()
+ .HasForeignKey("FieldMapId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("AccessLevelObjectAccessMapping", b =>
+ {
+ b.HasOne("BLAZAM.Database.Models.Permissions.AccessLevel", null)
+ .WithMany()
+ .HasForeignKey("AccessLevelsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("BLAZAM.Database.Models.Permissions.ObjectAccessMapping", null)
+ .WithMany()
+ .HasForeignKey("ObjectMapId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("AccessLevelPermissionMapping", b =>
+ {
+ b.HasOne("BLAZAM.Database.Models.Permissions.AccessLevel", null)
+ .WithMany()
+ .HasForeignKey("AccessLevelsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("BLAZAM.Database.Models.Permissions.PermissionMapping", null)
+ .WithMany()
+ .HasForeignKey("PermissionMapsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("AppUserChatRoom", b =>
+ {
+ b.HasOne("BLAZAM.Database.Models.Chat.ChatRoom", null)
+ .WithMany()
+ .HasForeignKey("ChatRoomId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("BLAZAM.Database.Models.User.AppUser", null)
+ .WithMany()
+ .HasForeignKey("MembersId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.ActiveDirectoryFieldObjectType", b =>
+ {
+ b.HasOne("BLAZAM.Database.Models.CustomActiveDirectoryField", null)
+ .WithMany("ObjectTypes")
+ .HasForeignKey("CustomActiveDirectoryFieldId");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Chat.UnreadChatMessage", b =>
+ {
+ b.HasOne("BLAZAM.Server.Data.ChatMessage", "ChatMessage")
+ .WithMany("NotReadBy")
+ .HasForeignKey("ChatMessageId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("ChatMessage");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Permissions.ActionAccessMapping", b =>
+ {
+ b.HasOne("BLAZAM.Database.Models.Permissions.AccessLevel", null)
+ .WithMany("ActionMap")
+ .HasForeignKey("AccessLevelId");
+
+ b.HasOne("BLAZAM.Database.Models.Permissions.ObjectAction", "ObjectAction")
+ .WithMany()
+ .HasForeignKey("ObjectActionId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("ObjectAction");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Permissions.FieldAccessMapping", b =>
+ {
+ b.HasOne("BLAZAM.Database.Models.CustomActiveDirectoryField", "CustomField")
+ .WithMany()
+ .HasForeignKey("CustomFieldId");
+
+ b.HasOne("BLAZAM.Database.Models.Permissions.FieldAccessLevel", "FieldAccessLevel")
+ .WithMany()
+ .HasForeignKey("FieldAccessLevelId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("BLAZAM.Database.Models.ActiveDirectoryField", "Field")
+ .WithMany()
+ .HasForeignKey("FieldId");
+
+ b.Navigation("CustomField");
+
+ b.Navigation("Field");
+
+ b.Navigation("FieldAccessLevel");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Permissions.ObjectAccessMapping", b =>
+ {
+ b.HasOne("BLAZAM.Database.Models.Permissions.ObjectAccessLevel", "ObjectAccessLevel")
+ .WithMany("ObjectAccessMappings")
+ .HasForeignKey("ObjectAccessLevelId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("ObjectAccessLevel");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Templates.DirectoryTemplate", b =>
+ {
+ b.HasOne("BLAZAM.Database.Models.Templates.DirectoryTemplate", "ParentTemplate")
+ .WithMany()
+ .HasForeignKey("ParentTemplateId");
+
+ b.Navigation("ParentTemplate");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Templates.DirectoryTemplateFieldValue", b =>
+ {
+ b.HasOne("BLAZAM.Database.Models.CustomActiveDirectoryField", "CustomField")
+ .WithMany()
+ .HasForeignKey("CustomFieldId");
+
+ b.HasOne("BLAZAM.Database.Models.Templates.DirectoryTemplate", null)
+ .WithMany("FieldValues")
+ .HasForeignKey("DirectoryTemplateId");
+
+ b.HasOne("BLAZAM.Database.Models.ActiveDirectoryField", "Field")
+ .WithMany()
+ .HasForeignKey("FieldId");
+
+ b.Navigation("CustomField");
+
+ b.Navigation("Field");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Templates.DirectoryTemplateGroup", b =>
+ {
+ b.HasOne("BLAZAM.Database.Models.Templates.DirectoryTemplate", null)
+ .WithMany("AssignedGroupSids")
+ .HasForeignKey("DirectoryTemplateId");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.User.ReadNewsItem", b =>
+ {
+ b.HasOne("BLAZAM.Database.Models.User.AppUser", "User")
+ .WithMany("ReadNewsItems")
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.User.UserDashboardWidget", b =>
+ {
+ b.HasOne("BLAZAM.Database.Models.User.AppUser", "User")
+ .WithMany("DashboardWidgets")
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.User.UserFavoriteEntry", b =>
+ {
+ b.HasOne("BLAZAM.Database.Models.User.AppUser", "User")
+ .WithMany("FavoriteEntries")
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.User.UserNotification", b =>
+ {
+ b.HasOne("BLAZAM.Database.Models.User.NotificationMessage", "Notification")
+ .WithMany()
+ .HasForeignKey("NotificationId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("BLAZAM.Database.Models.User.AppUser", "User")
+ .WithMany("Messages")
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Notification");
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("BLAZAM.Server.Data.ChatMessage", b =>
+ {
+ b.HasOne("BLAZAM.Database.Models.Chat.ChatRoom", "ChatRoom")
+ .WithMany("Messages")
+ .HasForeignKey("ChatRoomId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("BLAZAM.Database.Models.User.AppUser", "User")
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("ChatRoom");
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("PermissionDelegatePermissionMapping", b =>
+ {
+ b.HasOne("BLAZAM.Database.Models.Permissions.PermissionDelegate", null)
+ .WithMany()
+ .HasForeignKey("PermissionDelegatesId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("BLAZAM.Database.Models.Permissions.PermissionMapping", null)
+ .WithMany()
+ .HasForeignKey("PermissionsMapsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Chat.ChatRoom", b =>
+ {
+ b.Navigation("Messages");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.CustomActiveDirectoryField", b =>
+ {
+ b.Navigation("ObjectTypes");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Permissions.AccessLevel", b =>
+ {
+ b.Navigation("ActionMap");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Permissions.ObjectAccessLevel", b =>
+ {
+ b.Navigation("ObjectAccessMappings");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.Templates.DirectoryTemplate", b =>
+ {
+ b.Navigation("AssignedGroupSids");
+
+ b.Navigation("FieldValues");
+ });
+
+ modelBuilder.Entity("BLAZAM.Database.Models.User.AppUser", b =>
+ {
+ b.Navigation("DashboardWidgets");
+
+ b.Navigation("FavoriteEntries");
+
+ b.Navigation("Messages");
+
+ b.Navigation("ReadNewsItems");
+ });
+
+ modelBuilder.Entity("BLAZAM.Server.Data.ChatMessage", b =>
+ {
+ b.Navigation("NotReadBy");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/BLAZAMDatabase/Migrations/MySql/20240704204619_Add_DelegateName_And_EmailTemplateChanges_MySql.cs b/BLAZAMDatabase/Migrations/MySql/20240704204619_Add_DelegateName_And_EmailTemplateChanges_MySql.cs
new file mode 100644
index 00000000..62be5ac0
--- /dev/null
+++ b/BLAZAMDatabase/Migrations/MySql/20240704204619_Add_DelegateName_And_EmailTemplateChanges_MySql.cs
@@ -0,0 +1,73 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace BLAZAM.Database.Migrations.MySql
+{
+ ///
+ public partial class Add_DelegateName_And_EmailTemplateChanges_MySql : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "BCC",
+ table: "EmailTemplates");
+
+ migrationBuilder.DropColumn(
+ name: "CC",
+ table: "EmailTemplates");
+
+ migrationBuilder.DropColumn(
+ name: "TemplateName",
+ table: "EmailTemplates");
+
+ migrationBuilder.AddColumn(
+ name: "DelegateName",
+ table: "PermissionDelegate",
+ type: "longtext",
+ nullable: true)
+ .Annotation("MySql:CharSet", "utf8mb4");
+
+ migrationBuilder.AddColumn(
+ name: "TemplateType",
+ table: "EmailTemplates",
+ type: "int",
+ nullable: false,
+ defaultValue: 0);
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "DelegateName",
+ table: "PermissionDelegate");
+
+ migrationBuilder.DropColumn(
+ name: "TemplateType",
+ table: "EmailTemplates");
+
+ migrationBuilder.AddColumn(
+ name: "BCC",
+ table: "EmailTemplates",
+ type: "longtext",
+ nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4");
+
+ migrationBuilder.AddColumn(
+ name: "CC",
+ table: "EmailTemplates",
+ type: "longtext",
+ nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4");
+
+ migrationBuilder.AddColumn(
+ name: "TemplateName",
+ table: "EmailTemplates",
+ type: "longtext",
+ nullable: false)
+ .Annotation("MySql:CharSet", "utf8mb4");
+ }
+ }
+}
diff --git a/BLAZAMDatabase/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs b/BLAZAMDatabase/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs
index 36895730..cdfba259 100644
--- a/BLAZAMDatabase/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs
+++ b/BLAZAMDatabase/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs
@@ -16,7 +16,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
- .HasAnnotation("ProductVersion", "7.0.19")
+ .HasAnnotation("ProductVersion", "7.0.20")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("AccessLevelFieldAccessMapping", b =>
@@ -884,25 +884,16 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.ValueGeneratedOnAdd()
.HasColumnType("int");
- b.Property("BCC")
- .IsRequired()
- .HasColumnType("longtext");
-
b.Property("Body")
.IsRequired()
.HasColumnType("longtext");
- b.Property("CC")
- .IsRequired()
- .HasColumnType("longtext");
-
b.Property("Subject")
.IsRequired()
.HasColumnType("longtext");
- b.Property("TemplateName")
- .IsRequired()
- .HasColumnType("longtext");
+ b.Property("TemplateType")
+ .HasColumnType("int");
b.HasKey("Id");
@@ -1165,6 +1156,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.ValueGeneratedOnAdd()
.HasColumnType("int");
+ b.Property("DelegateName")
+ .HasColumnType("longtext");
+
b.Property("DelegateSid")
.IsRequired()
.HasColumnType("varbinary(3072)");
diff --git a/BLAZAMDatabase/Migrations/Sql/20240704204540_Add_DelegateName_And_EmailTemplateChanges_Sql.Designer.cs b/BLAZAMDatabase/Migrations/Sql/20240704204540_Add_DelegateName_And_EmailTemplateChanges_Sql.Designer.cs
new file mode 100644
index 00000000..e5891d48
--- /dev/null
+++ b/BLAZAMDatabase/Migrations/Sql/20240704204540_Add_DelegateName_And_EmailTemplateChanges_Sql.Designer.cs
@@ -0,0 +1,1882 @@
+//
+using System;
+using BLAZAM.Database.Context;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace BLAZAM.Database.Migrations.Sql
+{
+ [DbContext(typeof(SqlDatabaseContext))]
+ [Migration("20240704204540_Add_DelegateName_And_EmailTemplateChanges_Sql")]
+ partial class Add_DelegateName_And_EmailTemplateChanges_Sql
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "7.0.20")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("AccessLevelFieldAccessMapping", b =>
+ {
+ b.Property("AccessLevelsId")
+ .HasColumnType("int");
+
+ b.Property("FieldMapId")
+ .HasColumnType("int");
+
+ b.HasKey("AccessLevelsId", "FieldMapId");
+
+ b.HasIndex("FieldMapId");
+
+ b.ToTable("AccessLevelFieldAccessMapping");
+ });
+
+ modelBuilder.Entity("AccessLevelObjectAccessMapping", b =>
+ {
+ b.Property("AccessLevelsId")
+ .HasColumnType("int");
+
+ b.Property("ObjectMapId")
+ .HasColumnType("int");
+
+ b.HasKey("AccessLevelsId", "ObjectMapId");
+
+ b.HasIndex("ObjectMapId");
+
+ b.ToTable("AccessLevelObjectAccessMapping");
+ });
+
+ modelBuilder.Entity("AccessLevelPermissionMapping", b =>
+ {
+ b.Property