diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index dd84ea78..c35e897f 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -2,7 +2,7 @@ name: Bug report about: Create a report to help us improve title: '' -labels: '' +labels: 'bug' assignees: '' --- @@ -10,29 +10,19 @@ assignees: '' **Describe the bug** A clear and concise description of what the bug is. -**To Reproduce** +**To Reproduce (Required for complex issues)** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error -**Expected behavior** -A clear and concise description of what you expected to happen. - **Screenshots** If applicable, add screenshots to help explain your problem. -**Desktop (please complete the following information):** - - OS: [e.g. iOS] - - Browser [e.g. chrome, safari] - - Version [e.g. 22] - -**Smartphone (please complete the following information):** - - Device: [e.g. iPhone6] - - OS: [e.g. iOS8.1] - - Browser [e.g. stock browser, safari] - - Version [e.g. 22] +**Environment (please complete the following information):** + - Blazam Version + - Running under IIS/Service **Additional context** Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index bbcbbe7d..df81be2b 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -13,8 +13,5 @@ A clear and concise description of what the problem is. Ex. I'm always frustrate **Describe the solution you'd like** A clear and concise description of what you want to happen. -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - **Additional context** Add any other context or screenshots about the feature request here. diff --git a/BLAZAM.Tests/BLAZAM.Tests.csproj b/BLAZAM.Tests/BLAZAM.Tests.csproj index b1da1ddf..b619ce32 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.Tests/Updates/UpdateTests.cs b/BLAZAM.Tests/Updates/UpdateTests.cs index f5d6838a..e3d8bd75 100644 --- a/BLAZAM.Tests/Updates/UpdateTests.cs +++ b/BLAZAM.Tests/Updates/UpdateTests.cs @@ -34,17 +34,17 @@ public async void Update_Returns_ValidDownload() await latest.Download(null); Assert.True(latest?.UpdateFile.Exists); - Update_Stages_OK(latest); - Update_Cleanup_OK(latest); + await Update_Stages_OK(latest); + await Update_Cleanup_OK(latest); } - private async void Update_Stages_OK(ApplicationUpdate latest) + private async Task Update_Stages_OK(ApplicationUpdate latest) { await latest.ExtractFiles(null); Assert.True(latest.UpdateStagingDirectory.Files.Count > 2); } - private async void Update_Cleanup_OK(ApplicationUpdate latest) + private async Task Update_Cleanup_OK(ApplicationUpdate latest) { await latest.CleanStaging(null); diff --git a/BLAZAM/BLAZAM.csproj b/BLAZAM/BLAZAM.csproj index 1b5e37ea..034430a0 100644 --- a/BLAZAM/BLAZAM.csproj +++ b/BLAZAM/BLAZAM.csproj @@ -5,8 +5,8 @@ enable enable false - 0.9.1 - 2024.04.13.2102 + 0.9.2 + 2024.05.01.2331 false BLAZAM False @@ -26,6 +26,7 @@ + @@ -55,35 +56,35 @@ - - + + - - - - - - - - - - + + + + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + - + @@ -108,6 +109,12 @@ + + + PreserveNewest + + + True diff --git a/BLAZAM/GlobalSuppressions.cs b/BLAZAM/GlobalSuppressions.cs new file mode 100644 index 00000000..4b46ad14 --- /dev/null +++ b/BLAZAM/GlobalSuppressions.cs @@ -0,0 +1,8 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:BLAZAM.Server.ProgramHelpers.GetInstallationId~System.Guid")] diff --git a/BLAZAM/Pages/Groups/CreateGroup.razor b/BLAZAM/Pages/Groups/CreateGroup.razor index 8c02e303..d8f07fb8 100644 --- a/BLAZAM/Pages/Groups/CreateGroup.razor +++ b/BLAZAM/Pages/Groups/CreateGroup.razor @@ -11,7 +11,7 @@ + SelectedEntryChanged="OUSelected"> @* @context.Name *@ @@ -73,7 +73,7 @@ int selectedStep; - + @@ -89,17 +89,20 @@ templates = await Context?.DirectoryTemplates.ToListAsync(); await InvokeAsync(StateHasChanged); } - async void OUSelected(IADOrganizationalUnit ou) + async void OUSelected(IDirectoryEntryAdapter entry) { - if (parentOU == null) + if (entry is IADOrganizationalUnit ou) { + if (parentOU == null) + { + parentOU = ou; + return; + } parentOU = ou; - return; - } - parentOU = ou; - await InvokeAsync(StateHasChanged); + await InvokeAsync(StateHasChanged); + } } async void CreateNewGroup() diff --git a/BLAZAM/Pages/Home.razor b/BLAZAM/Pages/Home.razor index 4fe2f0cb..537f80b7 100644 --- a/BLAZAM/Pages/Home.razor +++ b/BLAZAM/Pages/Home.razor @@ -26,14 +26,7 @@ @if (ApplicationInfo.InDebugMode) { - - - - Test Item - Test Item - Test Item - -
+ Run Test Job } diff --git a/BLAZAM/Pages/Install/InstallDatabase.razor b/BLAZAM/Pages/Install/InstallDatabase.razor index cdb32f18..9ee1aff4 100644 --- a/BLAZAM/Pages/Install/InstallDatabase.razor +++ b/BLAZAM/Pages/Install/InstallDatabase.razor @@ -86,7 +86,7 @@ else await InvokeAsync(StateHasChanged); try { - if (await DbFactory.ApplyDatabaseMigrations(true)) + if (await DbFactory.ApplyDatabaseMigrationsAsync(true)) { Completed = true; await InvokeAsync(StepCompleted.InvokeAsync); diff --git a/BLAZAM/Pages/OU/CreateOU.razor b/BLAZAM/Pages/OU/CreateOU.razor index 8dc500cc..4c003f85 100644 --- a/BLAZAM/Pages/OU/CreateOU.razor +++ b/BLAZAM/Pages/OU/CreateOU.razor @@ -11,7 +11,7 @@ + SelectedEntryChanged="OUSelected"> @* @context.Name *@ @@ -84,19 +84,23 @@ return false; } */ - async void OUSelected(IADOrganizationalUnit ou) + async void OUSelected(IDirectoryEntryAdapter entry) { - if (parentOU == null) + if (entry is IADOrganizationalUnit ou) { + if (parentOU == null) + { + parentOU = ou; + return; + } parentOU = ou; - return; - } - parentOU = ou; - await InvokeAsync(StateHasChanged); + await InvokeAsync(StateHasChanged); + } } + async void CreateNewOU() { LoadingData = true; diff --git a/BLAZAM/Pages/Users/CreateUser.razor b/BLAZAM/Pages/Users/CreateUser.razor index d453f05d..3baaa676 100644 --- a/BLAZAM/Pages/Users/CreateUser.razor +++ b/BLAZAM/Pages/Users/CreateUser.razor @@ -122,14 +122,18 @@ @AppLocalization["OU"] - + @* *@ + Back - Next + Next @@ -214,15 +218,17 @@ newUser?.StagePasswordChange(customConfirmPassword.ToSecureString()); await InvokeAsync(StateHasChanged); } - async void OUSelected(IADOrganizationalUnit ou) + async void OUSelected(IDirectoryEntryAdapter entry) { - if (selectedOU == null) + if (entry is IADOrganizationalUnit ou) { - selectedOU = ou; - return; + if(ou.CanCreateUser) + selectedOU = ou; + else + { + SnackBarService.Warning(AppLocalization["You do not have permission to create users in that location"]); + } } - selectedOU = ou; - await InvokeAsync(StateHasChanged); } @@ -264,7 +270,9 @@ newUser?.StagePasswordChange(customConfirmPassword.ToSecureString()); newUser.DisplayName = SelectedTemplate.GenerateDisplayName(newUserName); //newUser.SetPassword(SelectedTemplate.GeneratePassword().ToSecureString(),false); //newUser.CanonicalName = SelectedTemplate.GenerateDisplayName(newUserName); - newUser.StagePasswordChange(SelectedTemplate.GeneratePassword().ToSecureString(), true); + newUser.StagePasswordChange(SelectedTemplate.GeneratePassword().ToSecureString()); + if (SelectedTemplate.EffectiveRequirePasswordChange == true) + newUser.StageRequirePasswordChange(true); if (!newUserName.GivenName.IsNullOrEmpty()) newUser.GivenName = newUserName.GivenName; if (!newUserName.MiddleName.IsNullOrEmpty()) @@ -334,5 +342,13 @@ newUser?.StagePasswordChange(customConfirmPassword.ToSecureString()); SelectedStep = 1; await InvokeAsync(StateHasChanged); } - + bool AdditionalShow(IDirectoryEntryAdapter entry) + { + if(entry is IADOrganizationalUnit ou) + { + if (ou.CanCreateUser) return true; + if (ou.CanCreateUserInSubOUs) return true; + } + return false; + } } diff --git a/BLAZAM/Pages/Users/ViewUser.razor b/BLAZAM/Pages/Users/ViewUser.razor index 73664ee0..073616c6 100644 --- a/BLAZAM/Pages/Users/ViewUser.razor +++ b/BLAZAM/Pages/Users/ViewUser.razor @@ -227,7 +227,7 @@ @bind-Value="@ConfirmPassword" InputType="InputType.Password" /> } - + + } @if (User.CanReadField(ActiveDirectoryFields.ScriptPath)) { diff --git a/BLAZAM/Pages/_Layout.cshtml b/BLAZAM/Pages/_Layout.cshtml index 6876c658..834867ca 100644 --- a/BLAZAM/Pages/_Layout.cshtml +++ b/BLAZAM/Pages/_Layout.cshtml @@ -48,7 +48,7 @@ 🗙 - @if (!!ApplicationInfo.InDemoMode && !ApplicationInfo.InDebugMode && !Debugger.IsAttached) + @if (!!ApplicationInfo.InDemoMode && !ApplicationInfo.InDebugMode && !Debugger.IsAttached && DatabaseCache.ApplicationSettings?.SendDeveloperAnalytics == true) { diff --git a/BLAZAM/Program.cs b/BLAZAM/Program.cs index 24204b67..310eb11d 100644 --- a/BLAZAM/Program.cs +++ b/BLAZAM/Program.cs @@ -81,10 +81,25 @@ public static void Main(string[] args) builder.IntializeProperties(); + //Create and discard a new instance of Encryption to inject the encryption seed string _ = new Encryption(Configuration?.GetValue("EncryptionKey")); + //Assign installation ID + Loggers.InstallationId = ApplicationInfo.installationId.ToString(); + //Setup host logging so it can catch the earliest logs possible + Loggers.SeqServerUri = "http://logs.blazam.org:5341"; + if (Debugger.IsAttached) + { + Loggers.SeqAPIKey = "xE50e1ljqtgLzHcu8pYC"; + + } + else + { + Loggers.SeqAPIKey = "8TeLknA8XBk5ybamT5m9"; + } + Loggers.SetupLoggers(WritablePath + @"logs\", ApplicationInfo.runningVersion.ToString()); builder.Host.UseSerilog(Log.Logger); @@ -106,6 +121,23 @@ public static void Main(string[] args) ApplicationInfo.services = AppInstance.Services; + try + { + var context = AppInstance.Services.GetRequiredService().CreateDbContext(); + if(context!=null && context.AppSettings.FirstOrDefault()?.SendLogsToDeveloper != null) + { + Loggers.SendToSeqServer = context.AppSettings.FirstOrDefault().SendLogsToDeveloper; + + } + + }catch (Exception ex) + { + Loggers.SystemLogger.Error(ex.Message + " {@Error}", ex); + } + Loggers.SetupLoggers(WritablePath + @"logs\", ApplicationInfo.runningVersion.ToString()); + + + // Configure the HTTP request pipeline. diff --git a/BLAZAM/ProgramHelpers.cs b/BLAZAM/ProgramHelpers.cs index 872936c1..93bab51e 100644 --- a/BLAZAM/ProgramHelpers.cs +++ b/BLAZAM/ProgramHelpers.cs @@ -29,6 +29,7 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Mvc.RazorPages; using Org.BouncyCastle.Ocsp; +using System.Management; namespace BLAZAM.Server { @@ -40,8 +41,18 @@ public static WebApplicationBuilder IntializeProperties(this WebApplicationBuild ApplicationInfo ApplicationInfo = new(builder); ApplicationInfo.inDebugMode = builder.Configuration.GetValue("DebugMode"); ApplicationInfo.inDemoMode = builder.Configuration.GetValue("DemoMode"); - + //Set the installation ID + try + { + ApplicationInfo.installationId = GetInstallationId(); + + + }catch (Exception ex) + { + ApplicationInfo.installationId = Environment.MachineName.ToGuid(); + + } //Set application directories //Program.RootDirectory = new SystemDirectory(builder.Environment.ContentRootPath); //Program.TempDirectory = new SystemDirectory(Path.GetTempPath() + "Blazam\\"); @@ -61,6 +72,35 @@ public static WebApplicationBuilder IntializeProperties(this WebApplicationBuild return builder; } + private static Guid GetInstallationId() + { + //Try and get os id + try + { + string ComputerName = "localhost"; + ManagementScope Scope; + Scope = new ManagementScope(String.Format("\\\\{0}\\root\\CIMV2", ComputerName), null); + Scope.Connect(); + ObjectQuery Query = new ObjectQuery("SELECT UUID FROM Win32_ComputerSystemProduct"); + ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, Query); + + foreach (ManagementObject WmiObject in Searcher.Get()) + { + return Guid.Parse(WmiObject["UUID"].ToString()); + + } + throw new ApplicationException("Searched but could not find a CSProduct UUID"); + } + + catch (Exception ex) + { + Console.WriteLine("Failed to get client ID (GUID). Error: " + ex.Message); + throw ex; + } + + + } + public static WebApplicationBuilder InjectServices(this WebApplicationBuilder builder) { diff --git a/BLAZAM/_Imports.razor b/BLAZAM/_Imports.razor index 3bf54606..17a2a059 100644 --- a/BLAZAM/_Imports.razor +++ b/BLAZAM/_Imports.razor @@ -58,6 +58,7 @@ @using BLAZAM.Gui.UI; @using BLAZAM.Gui.UI.Dashboard.Widgets; @using BLAZAM.Gui.UI.Inputs +@using BLAZAM.Gui.UI.Inputs.TreeViews @using BLAZAM.Gui.Layouts; @using BLAZAM.Gui.UI.Settings; @using BLAZAM.Gui.UI.Chat diff --git a/BLAZAM/appsettings.example.json b/BLAZAM/appsettings.example.json index 5569f34a..3d492b00 100644 --- a/BLAZAM/appsettings.example.json +++ b/BLAZAM/appsettings.example.json @@ -9,7 +9,6 @@ }, "EncryptionKey": "supersecretstring", "DebugMode": "false", - "InstallType": "IIS", "ListeningAddress": "*", "HTTPPort": "79", "HTTPSPort": "442", @@ -18,9 +17,6 @@ "ConnectionStrings": { "DBConnectionString": "" - //SQL Example "ConnectionString": "Data Source=localhost;Database=BLAZAM;Persist Security Info=True;Integrated Security=False;Connection Timeout=10;TrustServerCertificate=True;", - //SQLite Example "ConnectionString": "Data Source=%temp%/Blazam/database.db;", - //MySql Example "ConnectionString": "Server=localhost;User=blazam;Password=blazam;Database=blazam;" } } diff --git a/BLAZAM/static/img/default_logo5.png b/BLAZAM/static/img/default_logo5.png new file mode 100644 index 00000000..bbc66206 Binary files /dev/null and b/BLAZAM/static/img/default_logo5.png differ diff --git a/BLAZAM/wwwroot/android-chrome-192x192.png b/BLAZAM/wwwroot/android-chrome-192x192.png new file mode 100644 index 00000000..5d0a5f06 Binary files /dev/null and b/BLAZAM/wwwroot/android-chrome-192x192.png differ diff --git a/BLAZAM/wwwroot/android-chrome-512x512.png b/BLAZAM/wwwroot/android-chrome-512x512.png new file mode 100644 index 00000000..5b62a1c1 Binary files /dev/null and b/BLAZAM/wwwroot/android-chrome-512x512.png differ diff --git a/BLAZAM/wwwroot/apple-touch-icon.png b/BLAZAM/wwwroot/apple-touch-icon.png new file mode 100644 index 00000000..d00d3ae6 Binary files /dev/null and b/BLAZAM/wwwroot/apple-touch-icon.png differ diff --git a/BLAZAM/wwwroot/css/site.css b/BLAZAM/wwwroot/css/site.css index 856d97dc..24ac9b17 100644 --- a/BLAZAM/wwwroot/css/site.css +++ b/BLAZAM/wwwroot/css/site.css @@ -8,6 +8,9 @@ html, body { h1:focus { outline: none; } +.blur-background { + backdrop-filter: blur(10px); +} .app-icon{ margin-left:0.5rem; max-height:2.5rem; diff --git a/BLAZAM/wwwroot/favicon-16x16.png b/BLAZAM/wwwroot/favicon-16x16.png new file mode 100644 index 00000000..c056d234 Binary files /dev/null and b/BLAZAM/wwwroot/favicon-16x16.png differ diff --git a/BLAZAM/wwwroot/favicon-32x32.png b/BLAZAM/wwwroot/favicon-32x32.png new file mode 100644 index 00000000..e4095c2b Binary files /dev/null and b/BLAZAM/wwwroot/favicon-32x32.png differ diff --git a/BLAZAM/wwwroot/favicon.ico b/BLAZAM/wwwroot/favicon.ico index 63e859b4..39f5b507 100644 Binary files a/BLAZAM/wwwroot/favicon.ico and b/BLAZAM/wwwroot/favicon.ico differ diff --git a/BLAZAM/wwwroot/icon-192.png b/BLAZAM/wwwroot/icon-192.png new file mode 100644 index 00000000..166f56da Binary files /dev/null and b/BLAZAM/wwwroot/icon-192.png differ diff --git a/BLAZAM/wwwroot/logo.png b/BLAZAM/wwwroot/logo.png new file mode 100644 index 00000000..f63d53b9 Binary files /dev/null and b/BLAZAM/wwwroot/logo.png differ diff --git a/BLAZAM/wwwroot/mstile-150x150.png b/BLAZAM/wwwroot/mstile-150x150.png new file mode 100644 index 00000000..3b9960b5 Binary files /dev/null and b/BLAZAM/wwwroot/mstile-150x150.png differ diff --git a/BLAZAMActiveDirectory/ActiveDirectoryContext.cs b/BLAZAMActiveDirectory/ActiveDirectoryContext.cs index 6900ff7e..421dd220 100644 --- a/BLAZAMActiveDirectory/ActiveDirectoryContext.cs +++ b/BLAZAMActiveDirectory/ActiveDirectoryContext.cs @@ -290,7 +290,22 @@ private async void KeepAlive(object? state = null) else if (Status == DirectoryConnectionStatus.OK) { //Throw away query used to keep connection alive - _keepAliveUser = Users?.FindUsersByString(ConnectionSettings?.Username, false)?.FirstOrDefault(); + try + { + _keepAliveUser = Users?.FindUsersByString(ConnectionSettings?.Username, false)?.FirstOrDefault(); + + }catch(DirectoryServicesCOMException ex) + { + //not usernam or password is incorrect + if (ex.HResult != -2147023570) + { + Loggers.ActiveDirectryLogger.Error("Unexpected error performing keep alive search.{@Error}", ex); + + } + } + catch (Exception ex) { + Loggers.ActiveDirectryLogger.Error("Unexpected error performing keep alive search.{@Error}", ex); + } } await Task.Delay(30000); } diff --git a/BLAZAMActiveDirectory/Adapters/ADComputerSessions.cs b/BLAZAMActiveDirectory/Adapters/ADComputerSessions.cs index e3152868..dbe03693 100644 --- a/BLAZAMActiveDirectory/Adapters/ADComputerSessions.cs +++ b/BLAZAMActiveDirectory/Adapters/ADComputerSessions.cs @@ -109,7 +109,7 @@ public void Dispose() session.Dispose(); } ConnectedSessions.Clear(); - + } diff --git a/BLAZAMActiveDirectory/Adapters/ADOrganizationalUnit.cs b/BLAZAMActiveDirectory/Adapters/ADOrganizationalUnit.cs index 20d7fb2f..d6440eb1 100644 --- a/BLAZAMActiveDirectory/Adapters/ADOrganizationalUnit.cs +++ b/BLAZAMActiveDirectory/Adapters/ADOrganizationalUnit.cs @@ -4,18 +4,17 @@ using BLAZAM.Logger; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; +using System.Data.SQLite; using System.Diagnostics.Contracts; using System.DirectoryServices; using System.Reflection.PortableExecutable; +using System.Web; namespace BLAZAM.ActiveDirectory.Adapters { public class ADOrganizationalUnit : DirectoryEntryAdapter, IADOrganizationalUnit { private IEnumerable? childOUCache; - //private IQueryable? childUserCache; - //private IQueryable? childComputerCache; - //private IQueryable? childGroupCache; @@ -26,7 +25,7 @@ public async Task HasChildrenAsync() return HasChildren; }); } - public async Task> GetChildrenAsync() + public async Task> GetChildrenAsync() { return await Task.Run(() => { @@ -34,9 +33,9 @@ public async Task> GetChildrenAsync() }); } - public HashSet CachedTreeViewSubOUs { get; private set; } = new(); + public HashSet CachedTreeViewSubOUs { get; private set; } = new(); - public HashSet TreeViewSubOUs + public HashSet TreeViewSubOUs { get { @@ -45,7 +44,7 @@ public HashSet TreeViewSubOUs } } - public IEnumerable SubOUs + public IEnumerable SubOUs { get { @@ -59,7 +58,7 @@ public IEnumerable SubOUs - public override string SearchUri => "/search/" + DN; + public override string SearchUri => "/search/" + HttpUtility.UrlEncode(DN); public override string? CanonicalName { @@ -123,7 +122,7 @@ public IQueryable OffspringPermissionMappings } - public virtual bool CanReadInSubOus + public virtual bool CanReadUsersInSubOus { get { @@ -141,12 +140,126 @@ public virtual bool CanReadInSubOus ); } + } + public virtual bool CanReadNonOUs + { + get + { + if (CanReadUsers) return true; + if (CanReadGroups) return true; + if (CanReadComputers) return true; + if (CanReadPrinters) return true; + return false; + } + } + public virtual bool CanReadPrinters + { + get + { + return HasPermission(p => p.Where(pm => + pm.AccessLevels.Any(al => + al.ObjectMap.Any(om => + om.ObjectType == ActiveDirectoryObjectType.Printer && + om.ObjectAccessLevel.Level > ObjectAccessLevels.Deny.Level + ))), + p => p.Where(pm => + pm.AccessLevels.Any(al => + al.ObjectMap.Any(om => + om.ObjectType == ActiveDirectoryObjectType.Printer && + om.ObjectAccessLevel.Level == ObjectAccessLevels.Deny.Level + ))) + ); + } + + } + public virtual bool CanReadComputers + { + get + { + return HasPermission(p => p.Where(pm => + pm.AccessLevels.Any(al => + al.ObjectMap.Any(om => + om.ObjectType == ActiveDirectoryObjectType.Computer && + om.ObjectAccessLevel.Level > ObjectAccessLevels.Deny.Level + ))), + p => p.Where(pm => + pm.AccessLevels.Any(al => + al.ObjectMap.Any(om => + om.ObjectType == ActiveDirectoryObjectType.Computer && + om.ObjectAccessLevel.Level == ObjectAccessLevels.Deny.Level + ))) + ); + } + + } + public virtual bool CanReadGroups + { + get + { + return HasPermission(p => p.Where(pm => + pm.AccessLevels.Any(al => + al.ObjectMap.Any(om => + om.ObjectType == ActiveDirectoryObjectType.Group && + om.ObjectAccessLevel.Level > ObjectAccessLevels.Deny.Level + ))), + p => p.Where(pm => + pm.AccessLevels.Any(al => + al.ObjectMap.Any(om => + om.ObjectType == ActiveDirectoryObjectType.Group && + om.ObjectAccessLevel.Level == ObjectAccessLevels.Deny.Level + ))) + ); + } + + } + public virtual bool CanReadUsers + { + get + { + return HasPermission(p => p.Where(pm => + pm.AccessLevels.Any(al => + al.ObjectMap.Any(om => + om.ObjectType == ActiveDirectoryObjectType.User && + om.ObjectAccessLevel.Level > ObjectAccessLevels.Deny.Level + ))), + p => p.Where(pm => + pm.AccessLevels.Any(al => + al.ObjectMap.Any(om => + om.ObjectType == ActiveDirectoryObjectType.User && + om.ObjectAccessLevel.Level == ObjectAccessLevels.Deny.Level + ))) + ); + } + } public virtual bool CanCreateUser { get { - return HasActionPermission(ObjectActions.Create,ActiveDirectoryObjectType.User); + return HasActionPermission(ObjectActions.Create, ActiveDirectoryObjectType.User); + } + + } + public virtual bool CanCreateUserInSubOUs + { + get + { + + return HasPermission(p => p.Where(pm => + pm.AccessLevels.Any(al => + al.ActionMap.Any(am=> + am.ObjectType==ActiveDirectoryObjectType.User && + am.ObjectAction.Id==ObjectActions.Create.Id && + am.AllowOrDeny==true))), + p => p.Where(pm => + pm.AccessLevels.Any(al => + al.ActionMap.Any(am => + am.ObjectType == ActiveDirectoryObjectType.User && + am.ObjectAction.Id == ObjectActions.Create.Id && + am.AllowOrDeny == false))), + true + ); + } } diff --git a/BLAZAMActiveDirectory/Adapters/AccountDirectoryAdapter.cs b/BLAZAMActiveDirectory/Adapters/AccountDirectoryAdapter.cs index 2bbfa0c7..dbab5e79 100644 --- a/BLAZAMActiveDirectory/Adapters/AccountDirectoryAdapter.cs +++ b/BLAZAMActiveDirectory/Adapters/AccountDirectoryAdapter.cs @@ -27,6 +27,8 @@ public class AccountDirectoryAdapter : GroupableDirectoryAdapter, IAccountDirect + public virtual bool CanSetPassword { get => HasActionPermission(ObjectActions.SetPassword); } + public virtual bool CanEnable { get => HasActionPermission(ObjectActions.Enable); } public virtual bool CanDisable { get => HasActionPermission(ObjectActions.Disable); } @@ -46,7 +48,6 @@ public bool CanSearchDisabled } } - public virtual DateTime? LockoutTime { get @@ -121,7 +122,7 @@ public virtual bool Disabled } } } - public virtual bool PasswordNotRequired + public virtual bool PasswordNotRequired { get { @@ -154,8 +155,8 @@ protected int UAC { get { - var uacRaw= Convert.ToInt32(GetProperty("userAccountControl")); - if(uacRaw == 0) + var uacRaw = Convert.ToInt32(GetProperty("userAccountControl")); + if (uacRaw == 0) { UAC = ADS_UF_NORMAL_ACCOUNT | ADS_UF_PASSWD_NOTREQD; return ADS_UF_NORMAL_ACCOUNT | ADS_UF_PASSWD_NOTREQD; @@ -164,11 +165,11 @@ protected int UAC } set { - // PostCommitSteps.Add(new("Set UAC", (step) => { - SetProperty("userAccountControl", value); + // PostCommitSteps.Add(new("Set UAC", (step) => { + SetProperty("userAccountControl", value); // return true; - // })); + // })); } } @@ -232,14 +233,69 @@ public bool Enabled SetProperty("accountExpires", value?.ToUniversalTime().ToFileTime().ToString()); } } + public void StageRequirePasswordChange(bool requireChange) + { + PostCommitSteps.Add(new JobStep("Require Password Change", (JobStep? step) => + { + + RequirePasswordChange = requireChange; + return true; + })); + + } + public virtual bool RequirePasswordChange + { + get + { + //var pwdLastSetRaw = GetProperty("pwdLastSet"); + if (PasswordLastSet == null) return true; + return PasswordLastSet == DateTime.MinValue; + } + set + { + if (value) + { + PasswordLastSet = null; + } + else + { + + PasswordLastSet = DateTime.Now; + + } + + } + } public DateTime? PasswordLastSet { get { + var dateTime = GetDateTimeProperty("pwdLastSet")?.AdsValueToDateTime(); + if (dateTime.HasValue) + { + return dateTime.Value; + + } + var rawValue = GetProperty("pwdLastSet"); + if (rawValue == -1) + { + return DateTime.UtcNow; + } + if (rawValue == 0) + { + return null; + } + return null; + } + set + { + if (value == null) + SetProperty("pwdLastSet", 0); + else + SetProperty("pwdLastSet", -1); - return GetDateTimeProperty("pwdLastSet"); } } @@ -265,7 +321,8 @@ public bool SetPassword(SecureString password, bool requireChange = false) { Invoke("SetPassword", new[] { password.ToPlainText() }); return true; - }catch (Exception ex) + } + catch (Exception ex) { Loggers.ActiveDirectryLogger.Warning("Could not set password via Invoke {@Error}", ex); //The following works outside the domain but may have issues with certs @@ -294,7 +351,7 @@ public bool SetPassword(SecureString password, bool requireChange = false) return true; } - + } catch (Exception ex) { @@ -304,7 +361,7 @@ public bool SetPassword(SecureString password, bool requireChange = false) throw new ApplicationException("Unable to set password", ex); else return true; } - + } public void StagePasswordChange(SecureString newPassword, bool requireChange = false) diff --git a/BLAZAMActiveDirectory/Adapters/DirectoryEntryAdapter.cs b/BLAZAMActiveDirectory/Adapters/DirectoryEntryAdapter.cs index 0d7f8393..b25e61fe 100644 --- a/BLAZAMActiveDirectory/Adapters/DirectoryEntryAdapter.cs +++ b/BLAZAMActiveDirectory/Adapters/DirectoryEntryAdapter.cs @@ -32,7 +32,7 @@ public virtual string SearchUri { get { - return "/search/" + HttpUtility.UrlEncode(DN); + return "/search/" + CanonicalName; } } @@ -457,15 +457,19 @@ public virtual void MoveTo(IADOrganizationalUnit parentOUToMoveTo) /// protected virtual bool HasPermission(Func, IEnumerable> allowSelector, Func, IEnumerable>? denySelector = null, bool nestedSearch = false) { - if (CurrentUser == null) return false; - if (DN == null) + try + { + if (CurrentUser == null) return false; + if (DN == null) + { + throw new ApplicationException("The directory object " + ADSPath+ " did not load a distinguished name."); + } + return CurrentUser.HasPermission(DN, allowSelector, denySelector, nestedSearch); + }catch(Exception ex) { - Loggers.ActiveDirectryLogger.Error("The directory object " + ADSPath - + " did not load a distinguished name." + " {@Error}", new ApplicationException()); + Loggers.ActiveDirectryLogger.Error(ex.Message + " {@Error}", ex); return false; } - return CurrentUser.HasPermission(DN,allowSelector, denySelector, nestedSearch); - } public virtual bool CanRead @@ -979,7 +983,6 @@ private void FetchDirectoryEntry() return list; } - protected virtual T? GetProperty(string propertyName) { try diff --git a/BLAZAMActiveDirectory/Adapters/RemoteSession.cs b/BLAZAMActiveDirectory/Adapters/RemoteSession.cs index fbf44b9f..61399633 100644 --- a/BLAZAMActiveDirectory/Adapters/RemoteSession.cs +++ b/BLAZAMActiveDirectory/Adapters/RemoteSession.cs @@ -99,7 +99,7 @@ public class RemoteSession : IRemoteSession public AppEvent OnSessionUpdated { get; set; } Timer t; - public RemoteSession(ITerminalServicesSession session,IADComputer host) + public RemoteSession(ITerminalServicesSession session, IADComputer host) { Host = host; @@ -187,7 +187,7 @@ public void Logoff(bool synchronous = false) { Host.Directory.Impersonation.Run(() => { - if (_session?.Server.IsOpen==false) + if (_session?.Server.IsOpen == false) _session.Server.Open(); _session?.Logoff(synchronous); _session?.Server.Close(); @@ -201,10 +201,10 @@ public void Disconnect(bool synchronous = false) { Host.Directory.Impersonation.Run(() => { - if (!_session.Server.IsOpen) + if (_session?.Server.IsOpen == false) _session.Server.Open(); - _session.Disconnect(synchronous); - _session.Server.Close(); + _session?.Disconnect(synchronous); + _session?.Server.Close(); return true; }); @@ -216,10 +216,10 @@ public void SendMessage(string message) { Host.Directory.Impersonation.Run(() => { - if (!_session.Server.IsOpen) + if (_session?.Server.IsOpen == false) _session.Server.Open(); - _session.MessageBox(message, "Administrator Message"); - _session.Server.Close(); + _session?.MessageBox(message, "Administrator Message"); + _session?.Server.Close(); return true; }); @@ -235,9 +235,9 @@ private void GetNewSessionState() { Host.Directory.Impersonation.Run(() => { - if (!_session.Server.IsOpen) + if (_session?.Server.IsOpen == false) _session.Server.Open(); - if (_session.Server.IsOpen) + if (_session?.Server.IsOpen == true) { int id = _session.SessionId; ITerminalServicesSession updated = _session.Server.GetSession(id); @@ -252,7 +252,8 @@ private void GetNewSessionState() } catch (Win32Exception ex) { - if (ex.Message == "The system cannot find the file specified.") + //The system cannot find the file specified + if (ex.ErrorCode == -2147467259) { OnSessionDown?.Invoke(this); @@ -262,7 +263,8 @@ private void GetNewSessionState() } catch (Exception ex) { - Log.Error("An error occured while refreshing a computer session state.", ex); + Log.Error("An error occurred while refreshing a computer session state.", ex); + this.Dispose(); } } @@ -286,7 +288,7 @@ public override int GetHashCode() public void Dispose() { t?.Dispose(); - if(Session!=null && Session.Server!=null) + if (Session != null && Session.Server != null) Session.Server.Close(); Session = null; } diff --git a/BLAZAMActiveDirectory/GlobalSuppressions.cs b/BLAZAMActiveDirectory/GlobalSuppressions.cs index c30b8cd1..86e0de26 100644 --- a/BLAZAMActiveDirectory/GlobalSuppressions.cs +++ b/BLAZAMActiveDirectory/GlobalSuppressions.cs @@ -61,3 +61,4 @@ [assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:BLAZAM.ActiveDirectory.Adapters.ADOrganizationalUnit.CreatePrinter(BLAZAM.ActiveDirectory.Adapters.SharedPrinter)~BLAZAM.ActiveDirectory.Interfaces.IADPrinter")] [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)")] diff --git a/BLAZAMActiveDirectory/Interfaces/IADOrganizationalUnit.cs b/BLAZAMActiveDirectory/Interfaces/IADOrganizationalUnit.cs index 7e56ae4a..e5773bf6 100644 --- a/BLAZAMActiveDirectory/Interfaces/IADOrganizationalUnit.cs +++ b/BLAZAMActiveDirectory/Interfaces/IADOrganizationalUnit.cs @@ -13,17 +13,23 @@ public interface IADOrganizationalUnit : IDirectoryEntryAdapter IQueryable AppliedPermissionMappings { get; } List DirectPermissionMappings { get; } IQueryable OffspringPermissionMappings { get; } - IEnumerable SubOUs { get; } + IEnumerable SubOUs { get; } - HashSet CachedTreeViewSubOUs { get;} - HashSet TreeViewSubOUs { get; } - bool CanReadInSubOus { get; } + HashSet CachedTreeViewSubOUs { get;} + HashSet TreeViewSubOUs { get; } + bool CanReadUsersInSubOus { get; } bool CanCreateUser { get; } + bool CanCreateUserInSubOUs { get; } + bool CanReadUsers { get; } + bool CanReadNonOUs { get; } + bool CanReadComputers { get; } + bool CanReadGroups { get; } + bool CanReadPrinters { get; } IADGroup CreateGroup(string containerName); IADUser CreateUser(string containerName); IADOrganizationalUnit CreateOU(string containerName); - Task> GetChildrenAsync(); + Task> GetChildrenAsync(); Task HasChildrenAsync(); IADPrinter CreatePrinter(string containerName, string uncPath, string shortServerName); IADPrinter CreatePrinter(SharedPrinter sharedPrinter); diff --git a/BLAZAMActiveDirectory/Interfaces/IAccountDirectoryAdapter.cs b/BLAZAMActiveDirectory/Interfaces/IAccountDirectoryAdapter.cs index 452c8fe8..5d2260a2 100644 --- a/BLAZAMActiveDirectory/Interfaces/IAccountDirectoryAdapter.cs +++ b/BLAZAMActiveDirectory/Interfaces/IAccountDirectoryAdapter.cs @@ -72,6 +72,7 @@ public interface IAccountDirectoryAdapter : IGroupableDirectoryAdapter /// SecureString? NewPassword { get; set; } bool PasswordNotRequired { get; set; } + bool RequirePasswordChange { get; set; } /// /// Changes the password for this entry immediately @@ -84,5 +85,6 @@ public interface IAccountDirectoryAdapter : IGroupableDirectoryAdapter void StagePasswordChange(SecureString newPassword, bool requireChange = false); + void StageRequirePasswordChange(bool requireChange); } } \ No newline at end of file diff --git a/BLAZAMCommon.Tests/BLAZAMCommon.Tests.csproj b/BLAZAMCommon.Tests/BLAZAMCommon.Tests.csproj index 56e2ec6d..4dbba57d 100644 --- a/BLAZAMCommon.Tests/BLAZAMCommon.Tests.csproj +++ b/BLAZAMCommon.Tests/BLAZAMCommon.Tests.csproj @@ -9,15 +9,15 @@ - - - - - + + + + + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/BLAZAMCommon/BLAZAMCommon.csproj b/BLAZAMCommon/BLAZAMCommon.csproj index da970227..537fd770 100644 --- a/BLAZAMCommon/BLAZAMCommon.csproj +++ b/BLAZAMCommon/BLAZAMCommon.csproj @@ -20,20 +20,20 @@ - - - - - - - + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/BLAZAMCommon/Data/ApplicationInfo.cs b/BLAZAMCommon/Data/ApplicationInfo.cs index 8a554da1..934be6c4 100644 --- a/BLAZAMCommon/Data/ApplicationInfo.cs +++ b/BLAZAMCommon/Data/ApplicationInfo.cs @@ -59,6 +59,10 @@ public class ApplicationInfo /// A static access to /// public static bool inDemoMode; + /// + /// A static access to + /// + public static Guid installationId = Guid.Empty; /// /// Indicates whether Blazam is running under IIS or as a service @@ -142,6 +146,7 @@ public static bool installationCompleted { get;set; } + public Guid InstallationId { get => installationId; set => installationId = value; } /// /// Use only for UnitTests diff --git a/BLAZAMCommon/Helpers/StringHelpers.cs b/BLAZAMCommon/Helpers/StringHelpers.cs index b9df466c..2a9447f0 100644 --- a/BLAZAMCommon/Helpers/StringHelpers.cs +++ b/BLAZAMCommon/Helpers/StringHelpers.cs @@ -3,6 +3,7 @@ using System.Net; using System.Runtime.InteropServices; using System.Security; +using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; @@ -53,6 +54,17 @@ public static bool IsUrlLocalToHost(this string url) url[0] == '~' && url[1] == '/'; // "~/" or "~/foo" } + public static Guid ToGuid(this string input) + { + // Use MD5 hash to get a 16-byte hash of the string + using (MD5 md5 = MD5.Create()) + { + byte[] hash = md5.ComputeHash(Encoding.Default.GetBytes(input)); + // Create a new Guid using the hash + return new Guid(hash); + } + } + public static string ToPlainText(this SecureString? secureString) { if (secureString == null) return string.Empty; diff --git a/BLAZAMDatabase/BLAZAMDatabase.csproj b/BLAZAMDatabase/BLAZAMDatabase.csproj index 9ec6f90c..f2285f9a 100644 --- a/BLAZAMDatabase/BLAZAMDatabase.csproj +++ b/BLAZAMDatabase/BLAZAMDatabase.csproj @@ -8,13 +8,13 @@ - - - - - - - + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/BLAZAMDatabase/Context/AppDatabaseFactory.cs b/BLAZAMDatabase/Context/AppDatabaseFactory.cs index 6ceb7f47..328c18e6 100644 --- a/BLAZAMDatabase/Context/AppDatabaseFactory.cs +++ b/BLAZAMDatabase/Context/AppDatabaseFactory.cs @@ -4,7 +4,6 @@ using BLAZAM.Logger; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; -using System.Runtime.CompilerServices; namespace BLAZAM.Database.Context { @@ -141,21 +140,17 @@ public IDatabaseContext CreateDbContext() : databaseContext; } - /// - /// Applies all pending database migrations - /// - /// : If true, the updates will happen - /// even if the database is seeded. If false, no updates will - /// be applied if seeding has already occurred. - /// - /// - /// If true, the updates will happen even if the database is seeded. If false, no updates will be applied if seeding has already occurred. - /// - public async Task ApplyDatabaseMigrations(bool force = false) + public async Task ApplyDatabaseMigrationsAsync(bool force = false) { + return await Task.Run(() => { + return ApplyDatabaseMigrations(force); + }); - return await Task.Run(() => - { + } + public bool ApplyDatabaseMigrations(bool force = false) + { + + try { using (var context = CreateDbContext()) @@ -188,7 +183,7 @@ public async Task ApplyDatabaseMigrations(bool force = false) Loggers.DatabaseLogger.Error("Database Auto-Update Failed!!!! {@Error}", ex); throw ex; } - }); + } diff --git a/BLAZAMDatabase/Context/IAppDatabaseFactory.cs b/BLAZAMDatabase/Context/IAppDatabaseFactory.cs index e75e0ec0..1ad49133 100644 --- a/BLAZAMDatabase/Context/IAppDatabaseFactory.cs +++ b/BLAZAMDatabase/Context/IAppDatabaseFactory.cs @@ -9,6 +9,16 @@ namespace BLAZAM.Database.Context /// public interface IAppDatabaseFactory { + /// + /// Applies any pending database migrations to the database synchronously + /// + /// + /// You must use true for if you want to apply migrations to an empty database + /// + /// Force the update even if the database is empty and has not been seeded yet + /// + bool ApplyDatabaseMigrations(bool force = false); + /// /// Applies any pending database migrations to the database asynchronously /// @@ -17,7 +27,7 @@ public interface IAppDatabaseFactory /// /// Force the update even if the database is empty and has not been seeded yet /// - Task ApplyDatabaseMigrations(bool force = false); + Task ApplyDatabaseMigrationsAsync(bool force = false); /// /// Creates a new connection to this database /// diff --git a/BLAZAMDatabase/Migrations/MySql/20240418222246_Add_Dev_Logging_Opt_OutMySql.Designer.cs b/BLAZAMDatabase/Migrations/MySql/20240418222246_Add_Dev_Logging_Opt_OutMySql.Designer.cs new file mode 100644 index 00000000..f5b34eac --- /dev/null +++ b/BLAZAMDatabase/Migrations/MySql/20240418222246_Add_Dev_Logging_Opt_OutMySql.Designer.cs @@ -0,0 +1,1800 @@ +// +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("20240418222246_Add_Dev_Logging_Opt_OutMySql")] + partial class Add_Dev_Logging_Opt_OutMySql + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.18") + .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 + }); + }); + + 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("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.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("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("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("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/20240418222246_Add_Dev_Logging_Opt_OutMySql.cs b/BLAZAMDatabase/Migrations/MySql/20240418222246_Add_Dev_Logging_Opt_OutMySql.cs new file mode 100644 index 00000000..6088fa03 --- /dev/null +++ b/BLAZAMDatabase/Migrations/MySql/20240418222246_Add_Dev_Logging_Opt_OutMySql.cs @@ -0,0 +1,40 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BLAZAM.Database.Migrations.MySql +{ + /// + public partial class Add_Dev_Logging_Opt_OutMySql : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "SendDeveloperAnalytics", + table: "AppSettings", + type: "tinyint(1)", + nullable: false, + defaultValue: true); + + migrationBuilder.AddColumn( + name: "SendLogsToDeveloper", + table: "AppSettings", + type: "tinyint(1)", + nullable: false, + defaultValue: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "SendDeveloperAnalytics", + table: "AppSettings"); + + migrationBuilder.DropColumn( + name: "SendLogsToDeveloper", + table: "AppSettings"); + } + } +} diff --git a/BLAZAMDatabase/Migrations/MySql/20240501175454_Add_RequirePasswordChange_To_TemplatesMySql.Designer.cs b/BLAZAMDatabase/Migrations/MySql/20240501175454_Add_RequirePasswordChange_To_TemplatesMySql.Designer.cs new file mode 100644 index 00000000..9d07d308 --- /dev/null +++ b/BLAZAMDatabase/Migrations/MySql/20240501175454_Add_RequirePasswordChange_To_TemplatesMySql.Designer.cs @@ -0,0 +1,1803 @@ +// +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("20240501175454_Add_RequirePasswordChange_To_TemplatesMySql")] + partial class Add_RequirePasswordChange_To_TemplatesMySql + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.18") + .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 + }); + }); + + 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("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.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("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("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("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/20240501175454_Add_RequirePasswordChange_To_TemplatesMySql.cs b/BLAZAMDatabase/Migrations/MySql/20240501175454_Add_RequirePasswordChange_To_TemplatesMySql.cs new file mode 100644 index 00000000..896d2569 --- /dev/null +++ b/BLAZAMDatabase/Migrations/MySql/20240501175454_Add_RequirePasswordChange_To_TemplatesMySql.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BLAZAM.Database.Migrations.MySql +{ + /// + public partial class Add_RequirePasswordChange_To_TemplatesMySql : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "RequirePasswordChange", + table: "DirectoryTemplates", + type: "tinyint(1)", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "RequirePasswordChange", + table: "DirectoryTemplates"); + } + } +} diff --git a/BLAZAMDatabase/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs b/BLAZAMDatabase/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs index 83e36076..f6c4bfd5 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.17") + .HasAnnotation("ProductVersion", "7.0.18") .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("AccessLevelFieldAccessMapping", b => @@ -451,6 +451,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("SSLCertificateCipher") .HasColumnType("longtext"); + b.Property("SendDeveloperAnalytics") + .HasColumnType("tinyint(1)"); + + b.Property("SendLogsToDeveloper") + .HasColumnType("tinyint(1)"); + b.Property("UpdateBranch") .IsRequired() .HasColumnType("longtext"); @@ -1215,6 +1221,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PasswordFormula") .HasColumnType("longtext"); + b.Property("RequirePasswordChange") + .HasColumnType("tinyint(1)"); + b.Property("UsernameFormula") .HasColumnType("longtext"); diff --git a/BLAZAMDatabase/Migrations/Sql/20240418222230_Add_Dev_Logging_Opt_OutSql.Designer.cs b/BLAZAMDatabase/Migrations/Sql/20240418222230_Add_Dev_Logging_Opt_OutSql.Designer.cs new file mode 100644 index 00000000..4481e6df --- /dev/null +++ b/BLAZAMDatabase/Migrations/Sql/20240418222230_Add_Dev_Logging_Opt_OutSql.Designer.cs @@ -0,0 +1,1865 @@ +// +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("20240418222230_Add_Dev_Logging_Opt_OutSql")] + partial class Add_Dev_Logging_Opt_OutSql + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.18") + .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("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("nvarchar(max)"); + + b.Property("FQDN") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ServerAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ServerPort") + .HasColumnType("int"); + + b.Property("UseTLS") + .HasColumnType("bit"); + + b.Property("Username") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FieldName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + 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 + }); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.ActiveDirectoryFieldObjectType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + 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("nvarchar(max)"); + + b.Property("AppFQDN") + .HasColumnType("nvarchar(max)"); + + b.Property("AppIcon") + .HasColumnType("varbinary(max)"); + + b.Property("AppName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AutoUpdate") + .HasColumnType("bit"); + + b.Property("AutoUpdateTime") + .HasColumnType("time"); + + b.Property("ForceHTTPS") + .HasColumnType("bit"); + + b.Property("InstallationCompleted") + .HasColumnType("bit"); + + b.Property("LastUpdateCheck") + .HasColumnType("datetime2"); + + b.Property("MOTD") + .HasColumnType("nvarchar(max)"); + + b.Property("MyrtilleURL") + .HasColumnType("nvarchar(max)"); + + b.Property("SSLCertificateCipher") + .HasColumnType("nvarchar(max)"); + + b.Property("SendDeveloperAnalytics") + .HasColumnType("bit"); + + b.Property("SendLogsToDeveloper") + .HasColumnType("bit"); + + b.Property("UpdateBranch") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("UpdateDomain") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatePassword") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdateUsername") + .HasColumnType("nvarchar(max)"); + + b.Property("UseUpdateCredentials") + .HasColumnType("bit"); + + b.Property("UserHelpdeskURL") + .HasColumnType("nvarchar(max)"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Action") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AfterAction") + .HasColumnType("nvarchar(max)"); + + b.Property("BeforeAction") + .HasColumnType("nvarchar(max)"); + + b.Property("IpAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("Sid") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Target") + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .HasColumnType("datetime2"); + + b.Property("Username") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("DirectoryEntryAuditLogs"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.LogonAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Action") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AfterAction") + .HasColumnType("nvarchar(max)"); + + b.Property("BeforeAction") + .HasColumnType("nvarchar(max)"); + + b.Property("IpAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("Target") + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .HasColumnType("datetime2"); + + b.Property("Username") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("LogonAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.PermissionsAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Action") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AfterAction") + .HasColumnType("nvarchar(max)"); + + b.Property("BeforeAction") + .HasColumnType("nvarchar(max)"); + + b.Property("IpAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("Target") + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .HasColumnType("datetime2"); + + b.Property("Username") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("PermissionsAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.RequestAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Action") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AfterAction") + .HasColumnType("nvarchar(max)"); + + b.Property("BeforeAction") + .HasColumnType("nvarchar(max)"); + + b.Property("IpAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("Target") + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .HasColumnType("datetime2"); + + b.Property("Username") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("RequestAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.SettingsAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Action") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AfterAction") + .HasColumnType("nvarchar(max)"); + + b.Property("BeforeAction") + .HasColumnType("nvarchar(max)"); + + b.Property("IpAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("Target") + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .HasColumnType("datetime2"); + + b.Property("Username") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("SettingsAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.SystemAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Action") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AfterAction") + .HasColumnType("nvarchar(max)"); + + b.Property("BeforeAction") + .HasColumnType("nvarchar(max)"); + + b.Property("IpAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("Target") + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .HasColumnType("datetime2"); + + b.Property("Username") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("SystemAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.AuthenticationSettings", b => + { + b.Property("Id") + .HasColumnType("int"); + + b.Property("AdminPassword") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("DuoApiHost") + .HasColumnType("nvarchar(max)"); + + b.Property("DuoClientId") + .HasColumnType("nvarchar(max)"); + + b.Property("DuoClientSecret") + .HasColumnType("nvarchar(max)"); + + b.Property("DuoEnabled") + .HasColumnType("bit"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("IsPublic") + .HasColumnType("bit"); + + b.Property("MembersHash") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("ChatRooms"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Chat.UnreadChatMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FieldName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + 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("nvarchar(max)"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("FromAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("FromName") + .HasColumnType("nvarchar(max)"); + + b.Property("ReplyToAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("ReplyToName") + .HasColumnType("nvarchar(max)"); + + b.Property("SMTPPassword") + .HasColumnType("nvarchar(max)"); + + b.Property("SMTPPort") + .HasColumnType("int"); + + b.Property("SMTPServer") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SMTPUsername") + .HasColumnType("nvarchar(max)"); + + b.Property("UseSMTPAuth") + .HasColumnType("bit"); + + b.Property("UseTLS") + .HasColumnType("bit"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("BCC") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Body") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CC") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TemplateName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("EmailTemplates"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Permissions.AccessLevel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccessLevelId") + .HasColumnType("int"); + + b.Property("AllowOrDeny") + .HasColumnType("bit"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AllowDisabled") + .HasColumnType("bit"); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DelegateSid") + .IsRequired() + .HasColumnType("varbinary(900)"); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("IsSuperAdmin") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.HasIndex("DelegateSid") + .IsUnique(); + + b.ToTable("PermissionDelegate"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Permissions.PermissionMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("OU") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("PermissionMap"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Templates.DirectoryTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AllowCustomGroups") + .HasColumnType("bit"); + + b.Property("Category") + .HasColumnType("nvarchar(max)"); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("DisplayNameFormula") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("ObjectType") + .HasColumnType("int"); + + b.Property("ParentOU") + .HasColumnType("nvarchar(max)"); + + b.Property("ParentTemplateId") + .HasColumnType("int"); + + b.Property("PasswordFormula") + .HasColumnType("nvarchar(max)"); + + b.Property("UsernameFormula") + .HasColumnType("nvarchar(max)"); + + b.Property("Visible") + .HasColumnType("bit"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CustomFieldId") + .HasColumnType("int"); + + b.Property("DirectoryTemplateId") + .HasColumnType("int"); + + b.Property("Editable") + .HasColumnType("bit"); + + b.Property("FieldId") + .HasColumnType("int"); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DirectoryTemplateId") + .HasColumnType("int"); + + b.Property("GroupSid") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("DirectoryTemplateId"); + + b.ToTable("DirectoryTemplateGroups"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.AppUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("APIToken") + .HasColumnType("nvarchar(max)"); + + b.Property("DarkMode") + .HasColumnType("bit"); + + b.Property("Email") + .HasColumnType("nvarchar(max)"); + + b.Property("ProfilePicture") + .HasColumnType("varbinary(max)"); + + b.Property("SearchDisabledComputers") + .HasColumnType("bit"); + + b.Property("SearchDisabledUsers") + .HasColumnType("bit"); + + b.Property("Theme") + .HasColumnType("nvarchar(max)"); + + b.Property("UserGUID") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Username") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("UserGUID") + .IsUnique(); + + b.ToTable("UserSettings"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.NotificationMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("Dismissable") + .HasColumnType("bit"); + + b.Property("Expires") + .HasColumnType("datetime2"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Link") + .HasColumnType("nvarchar(max)"); + + b.Property("Message") + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("NotificationMessages"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.ReadNewsItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("NewsItemId") + .HasColumnType("float"); + + b.Property("NewsItemUpdatedAt") + .HasColumnType("datetime2"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("Slot") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DN") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("IsRead") + .HasColumnType("bit"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ChatRoomId") + .HasColumnType("int"); + + b.Property("Message") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .HasColumnType("datetime2"); + + 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/Sql/20240418222230_Add_Dev_Logging_Opt_OutSql.cs b/BLAZAMDatabase/Migrations/Sql/20240418222230_Add_Dev_Logging_Opt_OutSql.cs new file mode 100644 index 00000000..6c7f3c78 --- /dev/null +++ b/BLAZAMDatabase/Migrations/Sql/20240418222230_Add_Dev_Logging_Opt_OutSql.cs @@ -0,0 +1,40 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BLAZAM.Database.Migrations.Sql +{ + /// + public partial class Add_Dev_Logging_Opt_OutSql : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "SendDeveloperAnalytics", + table: "AppSettings", + type: "bit", + nullable: false, + defaultValue: true); + + migrationBuilder.AddColumn( + name: "SendLogsToDeveloper", + table: "AppSettings", + type: "bit", + nullable: false, + defaultValue: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "SendDeveloperAnalytics", + table: "AppSettings"); + + migrationBuilder.DropColumn( + name: "SendLogsToDeveloper", + table: "AppSettings"); + } + } +} diff --git a/BLAZAMDatabase/Migrations/Sql/20240501175443_Add_RequirePasswordChange_To_TemplatesSql.Designer.cs b/BLAZAMDatabase/Migrations/Sql/20240501175443_Add_RequirePasswordChange_To_TemplatesSql.Designer.cs new file mode 100644 index 00000000..e60e3302 --- /dev/null +++ b/BLAZAMDatabase/Migrations/Sql/20240501175443_Add_RequirePasswordChange_To_TemplatesSql.Designer.cs @@ -0,0 +1,1868 @@ +// +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("20240501175443_Add_RequirePasswordChange_To_TemplatesSql")] + partial class Add_RequirePasswordChange_To_TemplatesSql + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.18") + .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("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("nvarchar(max)"); + + b.Property("FQDN") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ServerAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ServerPort") + .HasColumnType("int"); + + b.Property("UseTLS") + .HasColumnType("bit"); + + b.Property("Username") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FieldName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + 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 + }); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.ActiveDirectoryFieldObjectType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + 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("nvarchar(max)"); + + b.Property("AppFQDN") + .HasColumnType("nvarchar(max)"); + + b.Property("AppIcon") + .HasColumnType("varbinary(max)"); + + b.Property("AppName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AutoUpdate") + .HasColumnType("bit"); + + b.Property("AutoUpdateTime") + .HasColumnType("time"); + + b.Property("ForceHTTPS") + .HasColumnType("bit"); + + b.Property("InstallationCompleted") + .HasColumnType("bit"); + + b.Property("LastUpdateCheck") + .HasColumnType("datetime2"); + + b.Property("MOTD") + .HasColumnType("nvarchar(max)"); + + b.Property("MyrtilleURL") + .HasColumnType("nvarchar(max)"); + + b.Property("SSLCertificateCipher") + .HasColumnType("nvarchar(max)"); + + b.Property("SendDeveloperAnalytics") + .HasColumnType("bit"); + + b.Property("SendLogsToDeveloper") + .HasColumnType("bit"); + + b.Property("UpdateBranch") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("UpdateDomain") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdatePassword") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdateUsername") + .HasColumnType("nvarchar(max)"); + + b.Property("UseUpdateCredentials") + .HasColumnType("bit"); + + b.Property("UserHelpdeskURL") + .HasColumnType("nvarchar(max)"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Action") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AfterAction") + .HasColumnType("nvarchar(max)"); + + b.Property("BeforeAction") + .HasColumnType("nvarchar(max)"); + + b.Property("IpAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("Sid") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Target") + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .HasColumnType("datetime2"); + + b.Property("Username") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("DirectoryEntryAuditLogs"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.LogonAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Action") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AfterAction") + .HasColumnType("nvarchar(max)"); + + b.Property("BeforeAction") + .HasColumnType("nvarchar(max)"); + + b.Property("IpAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("Target") + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .HasColumnType("datetime2"); + + b.Property("Username") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("LogonAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.PermissionsAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Action") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AfterAction") + .HasColumnType("nvarchar(max)"); + + b.Property("BeforeAction") + .HasColumnType("nvarchar(max)"); + + b.Property("IpAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("Target") + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .HasColumnType("datetime2"); + + b.Property("Username") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("PermissionsAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.RequestAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Action") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AfterAction") + .HasColumnType("nvarchar(max)"); + + b.Property("BeforeAction") + .HasColumnType("nvarchar(max)"); + + b.Property("IpAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("Target") + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .HasColumnType("datetime2"); + + b.Property("Username") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("RequestAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.SettingsAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Action") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AfterAction") + .HasColumnType("nvarchar(max)"); + + b.Property("BeforeAction") + .HasColumnType("nvarchar(max)"); + + b.Property("IpAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("Target") + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .HasColumnType("datetime2"); + + b.Property("Username") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("SettingsAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.SystemAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Action") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AfterAction") + .HasColumnType("nvarchar(max)"); + + b.Property("BeforeAction") + .HasColumnType("nvarchar(max)"); + + b.Property("IpAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("Target") + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .HasColumnType("datetime2"); + + b.Property("Username") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("SystemAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.AuthenticationSettings", b => + { + b.Property("Id") + .HasColumnType("int"); + + b.Property("AdminPassword") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("DuoApiHost") + .HasColumnType("nvarchar(max)"); + + b.Property("DuoClientId") + .HasColumnType("nvarchar(max)"); + + b.Property("DuoClientSecret") + .HasColumnType("nvarchar(max)"); + + b.Property("DuoEnabled") + .HasColumnType("bit"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("IsPublic") + .HasColumnType("bit"); + + b.Property("MembersHash") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("ChatRooms"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Chat.UnreadChatMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FieldName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + 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("nvarchar(max)"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("FromAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("FromName") + .HasColumnType("nvarchar(max)"); + + b.Property("ReplyToAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("ReplyToName") + .HasColumnType("nvarchar(max)"); + + b.Property("SMTPPassword") + .HasColumnType("nvarchar(max)"); + + b.Property("SMTPPort") + .HasColumnType("int"); + + b.Property("SMTPServer") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SMTPUsername") + .HasColumnType("nvarchar(max)"); + + b.Property("UseSMTPAuth") + .HasColumnType("bit"); + + b.Property("UseTLS") + .HasColumnType("bit"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("BCC") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Body") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CC") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TemplateName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("EmailTemplates"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Permissions.AccessLevel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccessLevelId") + .HasColumnType("int"); + + b.Property("AllowOrDeny") + .HasColumnType("bit"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AllowDisabled") + .HasColumnType("bit"); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DelegateSid") + .IsRequired() + .HasColumnType("varbinary(900)"); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("IsSuperAdmin") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.HasIndex("DelegateSid") + .IsUnique(); + + b.ToTable("PermissionDelegate"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Permissions.PermissionMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("OU") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("PermissionMap"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Templates.DirectoryTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AllowCustomGroups") + .HasColumnType("bit"); + + b.Property("Category") + .HasColumnType("nvarchar(max)"); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("DisplayNameFormula") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("ObjectType") + .HasColumnType("int"); + + b.Property("ParentOU") + .HasColumnType("nvarchar(max)"); + + b.Property("ParentTemplateId") + .HasColumnType("int"); + + b.Property("PasswordFormula") + .HasColumnType("nvarchar(max)"); + + b.Property("RequirePasswordChange") + .HasColumnType("bit"); + + b.Property("UsernameFormula") + .HasColumnType("nvarchar(max)"); + + b.Property("Visible") + .HasColumnType("bit"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CustomFieldId") + .HasColumnType("int"); + + b.Property("DirectoryTemplateId") + .HasColumnType("int"); + + b.Property("Editable") + .HasColumnType("bit"); + + b.Property("FieldId") + .HasColumnType("int"); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DirectoryTemplateId") + .HasColumnType("int"); + + b.Property("GroupSid") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("DirectoryTemplateId"); + + b.ToTable("DirectoryTemplateGroups"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.AppUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("APIToken") + .HasColumnType("nvarchar(max)"); + + b.Property("DarkMode") + .HasColumnType("bit"); + + b.Property("Email") + .HasColumnType("nvarchar(max)"); + + b.Property("ProfilePicture") + .HasColumnType("varbinary(max)"); + + b.Property("SearchDisabledComputers") + .HasColumnType("bit"); + + b.Property("SearchDisabledUsers") + .HasColumnType("bit"); + + b.Property("Theme") + .HasColumnType("nvarchar(max)"); + + b.Property("UserGUID") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Username") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("UserGUID") + .IsUnique(); + + b.ToTable("UserSettings"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.NotificationMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("Dismissable") + .HasColumnType("bit"); + + b.Property("Expires") + .HasColumnType("datetime2"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Link") + .HasColumnType("nvarchar(max)"); + + b.Property("Message") + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("NotificationMessages"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.ReadNewsItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("NewsItemId") + .HasColumnType("float"); + + b.Property("NewsItemUpdatedAt") + .HasColumnType("datetime2"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("Slot") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DN") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("IsRead") + .HasColumnType("bit"); + + 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"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ChatRoomId") + .HasColumnType("int"); + + b.Property("Message") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .HasColumnType("datetime2"); + + 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/Sql/20240501175443_Add_RequirePasswordChange_To_TemplatesSql.cs b/BLAZAMDatabase/Migrations/Sql/20240501175443_Add_RequirePasswordChange_To_TemplatesSql.cs new file mode 100644 index 00000000..9fbbd830 --- /dev/null +++ b/BLAZAMDatabase/Migrations/Sql/20240501175443_Add_RequirePasswordChange_To_TemplatesSql.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BLAZAM.Database.Migrations.Sql +{ + /// + public partial class Add_RequirePasswordChange_To_TemplatesSql : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "RequirePasswordChange", + table: "DirectoryTemplates", + type: "bit", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "RequirePasswordChange", + table: "DirectoryTemplates"); + } + } +} diff --git a/BLAZAMDatabase/Migrations/Sql/SqlDatabaseContextModelSnapshot.cs b/BLAZAMDatabase/Migrations/Sql/SqlDatabaseContextModelSnapshot.cs index 0a21ea3c..f9e57b4e 100644 --- a/BLAZAMDatabase/Migrations/Sql/SqlDatabaseContextModelSnapshot.cs +++ b/BLAZAMDatabase/Migrations/Sql/SqlDatabaseContextModelSnapshot.cs @@ -17,7 +17,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "7.0.17") + .HasAnnotation("ProductVersion", "7.0.18") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -458,6 +458,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("SSLCertificateCipher") .HasColumnType("nvarchar(max)"); + b.Property("SendDeveloperAnalytics") + .HasColumnType("bit"); + + b.Property("SendLogsToDeveloper") + .HasColumnType("bit"); + b.Property("UpdateBranch") .IsRequired() .HasColumnType("nvarchar(max)"); @@ -1262,6 +1268,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PasswordFormula") .HasColumnType("nvarchar(max)"); + b.Property("RequirePasswordChange") + .HasColumnType("bit"); + b.Property("UsernameFormula") .HasColumnType("nvarchar(max)"); diff --git a/BLAZAMDatabase/Migrations/Sqlite/20240418222213_Add_Dev_Logging_Opt_OutSqlite.Designer.cs b/BLAZAMDatabase/Migrations/Sqlite/20240418222213_Add_Dev_Logging_Opt_OutSqlite.Designer.cs new file mode 100644 index 00000000..a95ed3c7 --- /dev/null +++ b/BLAZAMDatabase/Migrations/Sqlite/20240418222213_Add_Dev_Logging_Opt_OutSqlite.Designer.cs @@ -0,0 +1,1795 @@ +// +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.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20240418222213_Add_Dev_Logging_Opt_OutSqlite")] + partial class Add_Dev_Logging_Opt_OutSqlite + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.18"); + + modelBuilder.Entity("AccessLevelFieldAccessMapping", b => + { + b.Property("AccessLevelsId") + .HasColumnType("INTEGER"); + + b.Property("FieldMapId") + .HasColumnType("INTEGER"); + + b.HasKey("AccessLevelsId", "FieldMapId"); + + b.HasIndex("FieldMapId"); + + b.ToTable("AccessLevelFieldAccessMapping"); + }); + + modelBuilder.Entity("AccessLevelObjectAccessMapping", b => + { + b.Property("AccessLevelsId") + .HasColumnType("INTEGER"); + + b.Property("ObjectMapId") + .HasColumnType("INTEGER"); + + b.HasKey("AccessLevelsId", "ObjectMapId"); + + b.HasIndex("ObjectMapId"); + + b.ToTable("AccessLevelObjectAccessMapping"); + }); + + modelBuilder.Entity("AccessLevelPermissionMapping", b => + { + b.Property("AccessLevelsId") + .HasColumnType("INTEGER"); + + b.Property("PermissionMapsId") + .HasColumnType("INTEGER"); + + b.HasKey("AccessLevelsId", "PermissionMapsId"); + + b.HasIndex("PermissionMapsId"); + + b.ToTable("AccessLevelPermissionMapping"); + }); + + modelBuilder.Entity("AppUserChatRoom", b => + { + b.Property("ChatRoomId") + .HasColumnType("INTEGER"); + + b.Property("MembersId") + .HasColumnType("INTEGER"); + + b.HasKey("ChatRoomId", "MembersId"); + + b.HasIndex("MembersId"); + + b.ToTable("AppUserChatRoom"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.ADSettings", b => + { + b.Property("Id") + .HasColumnType("INTEGER"); + + b.Property("ApplicationBaseDN") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FQDN") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Password") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ServerAddress") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ServerPort") + .HasColumnType("INTEGER"); + + b.Property("UseTLS") + .HasColumnType("INTEGER"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT"); + + 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("INTEGER"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FieldName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FieldType") + .HasColumnType("INTEGER"); + + 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 + }); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.ActiveDirectoryFieldObjectType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ActiveDirectoryFieldId") + .HasColumnType("INTEGER"); + + b.Property("CustomActiveDirectoryFieldId") + .HasColumnType("INTEGER"); + + b.Property("ObjectType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("CustomActiveDirectoryFieldId"); + + b.ToTable("ActiveDirectoryFieldObjectMappings"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.AppSettings", b => + { + b.Property("Id") + .HasColumnType("INTEGER"); + + b.Property("AnalyticsId") + .HasColumnType("TEXT"); + + b.Property("AppFQDN") + .HasColumnType("TEXT"); + + b.Property("AppIcon") + .HasColumnType("BLOB"); + + b.Property("AppName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AutoUpdate") + .HasColumnType("INTEGER"); + + b.Property("AutoUpdateTime") + .HasColumnType("TEXT"); + + b.Property("ForceHTTPS") + .HasColumnType("INTEGER"); + + b.Property("InstallationCompleted") + .HasColumnType("INTEGER"); + + b.Property("LastUpdateCheck") + .HasColumnType("TEXT"); + + b.Property("MOTD") + .HasColumnType("TEXT"); + + b.Property("MyrtilleURL") + .HasColumnType("TEXT"); + + b.Property("SSLCertificateCipher") + .HasColumnType("TEXT"); + + b.Property("SendDeveloperAnalytics") + .HasColumnType("INTEGER"); + + b.Property("SendLogsToDeveloper") + .HasColumnType("INTEGER"); + + b.Property("UpdateBranch") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdateDomain") + .HasColumnType("TEXT"); + + b.Property("UpdatePassword") + .HasColumnType("TEXT"); + + b.Property("UpdateUsername") + .HasColumnType("TEXT"); + + b.Property("UseUpdateCredentials") + .HasColumnType("INTEGER"); + + b.Property("UserHelpdeskURL") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("AppSettings", t => + { + t.HasCheckConstraint("CK_Table_Column", "[Id] = 1"); + }); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.DirectoryEntryAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AfterAction") + .HasColumnType("TEXT"); + + b.Property("BeforeAction") + .HasColumnType("TEXT"); + + b.Property("IpAddress") + .HasColumnType("TEXT"); + + b.Property("Sid") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Target") + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .HasColumnType("TEXT"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("DirectoryEntryAuditLogs"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.LogonAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AfterAction") + .HasColumnType("TEXT"); + + b.Property("BeforeAction") + .HasColumnType("TEXT"); + + b.Property("IpAddress") + .HasColumnType("TEXT"); + + b.Property("Target") + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .HasColumnType("TEXT"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("LogonAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.PermissionsAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AfterAction") + .HasColumnType("TEXT"); + + b.Property("BeforeAction") + .HasColumnType("TEXT"); + + b.Property("IpAddress") + .HasColumnType("TEXT"); + + b.Property("Target") + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .HasColumnType("TEXT"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("PermissionsAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.RequestAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AfterAction") + .HasColumnType("TEXT"); + + b.Property("BeforeAction") + .HasColumnType("TEXT"); + + b.Property("IpAddress") + .HasColumnType("TEXT"); + + b.Property("Target") + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .HasColumnType("TEXT"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("RequestAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.SettingsAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AfterAction") + .HasColumnType("TEXT"); + + b.Property("BeforeAction") + .HasColumnType("TEXT"); + + b.Property("IpAddress") + .HasColumnType("TEXT"); + + b.Property("Target") + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .HasColumnType("TEXT"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("SettingsAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.SystemAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AfterAction") + .HasColumnType("TEXT"); + + b.Property("BeforeAction") + .HasColumnType("TEXT"); + + b.Property("IpAddress") + .HasColumnType("TEXT"); + + b.Property("Target") + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .HasColumnType("TEXT"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("SystemAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.AuthenticationSettings", b => + { + b.Property("Id") + .HasColumnType("INTEGER"); + + b.Property("AdminPassword") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DuoApiHost") + .HasColumnType("TEXT"); + + b.Property("DuoClientId") + .HasColumnType("TEXT"); + + b.Property("DuoClientSecret") + .HasColumnType("TEXT"); + + b.Property("DuoEnabled") + .HasColumnType("INTEGER"); + + b.Property("DuoUnreachableBehavior") + .HasColumnType("INTEGER"); + + b.Property("SessionTimeout") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("AuthenticationSettings", t => + { + t.HasCheckConstraint("CK_Table_Column", "[Id] = 1"); + }); + + 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("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("IsPublic") + .HasColumnType("INTEGER"); + + b.Property("MembersHash") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("ChatRooms"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Chat.UnreadChatMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChatMessageId") + .HasColumnType("INTEGER"); + + b.Property("ChatRoomId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChatMessageId"); + + b.ToTable("UnreadChatMessages"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.CustomActiveDirectoryField", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FieldName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FieldType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("CustomActiveDirectoryFields"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.EmailSettings", b => + { + b.Property("Id") + .HasColumnType("INTEGER"); + + b.Property("AdminBcc") + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("FromAddress") + .HasColumnType("TEXT"); + + b.Property("FromName") + .HasColumnType("TEXT"); + + b.Property("ReplyToAddress") + .HasColumnType("TEXT"); + + b.Property("ReplyToName") + .HasColumnType("TEXT"); + + b.Property("SMTPPassword") + .HasColumnType("TEXT"); + + b.Property("SMTPPort") + .HasColumnType("INTEGER"); + + b.Property("SMTPServer") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SMTPUsername") + .HasColumnType("TEXT"); + + b.Property("UseSMTPAuth") + .HasColumnType("INTEGER"); + + b.Property("UseTLS") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("EmailSettings", t => + { + t.HasCheckConstraint("CK_Table_Column", "[Id] = 1"); + }); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.EmailTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("BCC") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Body") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CC") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TemplateName") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("EmailTemplates"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Permissions.AccessLevel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + 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("INTEGER"); + + b.Property("AccessLevelId") + .HasColumnType("INTEGER"); + + b.Property("AllowOrDeny") + .HasColumnType("INTEGER"); + + b.Property("ObjectActionId") + .HasColumnType("INTEGER"); + + b.Property("ObjectType") + .HasColumnType("INTEGER"); + + 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("INTEGER"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + 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("INTEGER"); + + b.Property("CustomFieldId") + .HasColumnType("INTEGER"); + + b.Property("FieldAccessLevelId") + .HasColumnType("INTEGER"); + + b.Property("FieldId") + .HasColumnType("INTEGER"); + + b.Property("ObjectType") + .HasColumnType("INTEGER"); + + 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("INTEGER"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + 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("INTEGER"); + + b.Property("AllowDisabled") + .HasColumnType("INTEGER"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("ObjectAccessLevelId") + .HasColumnType("INTEGER"); + + b.Property("ObjectType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ObjectAccessLevelId"); + + b.ToTable("AccessLevelObjectMapping"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Permissions.ObjectAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + 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("INTEGER"); + + b.Property("DelegateSid") + .IsRequired() + .HasColumnType("BLOB"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("IsSuperAdmin") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("DelegateSid") + .IsUnique(); + + b.ToTable("PermissionDelegate"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Permissions.PermissionMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("OU") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("PermissionMap"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Templates.DirectoryTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AllowCustomGroups") + .HasColumnType("INTEGER"); + + b.Property("Category") + .HasColumnType("TEXT"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("DisplayNameFormula") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ObjectType") + .HasColumnType("INTEGER"); + + b.Property("ParentOU") + .HasColumnType("TEXT"); + + b.Property("ParentTemplateId") + .HasColumnType("INTEGER"); + + b.Property("PasswordFormula") + .HasColumnType("TEXT"); + + b.Property("UsernameFormula") + .HasColumnType("TEXT"); + + b.Property("Visible") + .HasColumnType("INTEGER"); + + 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("INTEGER"); + + b.Property("CustomFieldId") + .HasColumnType("INTEGER"); + + b.Property("DirectoryTemplateId") + .HasColumnType("INTEGER"); + + b.Property("Editable") + .HasColumnType("INTEGER"); + + b.Property("FieldId") + .HasColumnType("INTEGER"); + + b.Property("Required") + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("TEXT"); + + 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("INTEGER"); + + b.Property("DirectoryTemplateId") + .HasColumnType("INTEGER"); + + b.Property("GroupSid") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DirectoryTemplateId"); + + b.ToTable("DirectoryTemplateGroups"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.AppUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("APIToken") + .HasColumnType("TEXT"); + + b.Property("DarkMode") + .HasColumnType("INTEGER"); + + b.Property("Email") + .HasColumnType("TEXT"); + + b.Property("ProfilePicture") + .HasColumnType("BLOB"); + + b.Property("SearchDisabledComputers") + .HasColumnType("INTEGER"); + + b.Property("SearchDisabledUsers") + .HasColumnType("INTEGER"); + + b.Property("Theme") + .HasColumnType("TEXT"); + + b.Property("UserGUID") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserGUID") + .IsUnique(); + + b.ToTable("UserSettings"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.NotificationMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Dismissable") + .HasColumnType("INTEGER"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Link") + .HasColumnType("TEXT"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("NotificationMessages"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.ReadNewsItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("NewsItemId") + .HasColumnType("REAL"); + + b.Property("NewsItemUpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("ReadNewsItems"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.UserDashboardWidget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Order") + .HasColumnType("INTEGER"); + + b.Property("Slot") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("WidgetType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserDashboardWidgets"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.UserFavoriteEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DN") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserFavoriteEntries"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.UserNotification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("IsRead") + .HasColumnType("INTEGER"); + + b.Property("NotificationId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NotificationId"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotifications"); + }); + + modelBuilder.Entity("BLAZAM.Server.Data.ChatMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChatRoomId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChatRoomId"); + + b.HasIndex("UserId"); + + b.ToTable("ChatMessages"); + }); + + modelBuilder.Entity("PermissionDelegatePermissionMapping", b => + { + b.Property("PermissionDelegatesId") + .HasColumnType("INTEGER"); + + b.Property("PermissionsMapsId") + .HasColumnType("INTEGER"); + + 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/Sqlite/20240418222213_Add_Dev_Logging_Opt_OutSqlite.cs b/BLAZAMDatabase/Migrations/Sqlite/20240418222213_Add_Dev_Logging_Opt_OutSqlite.cs new file mode 100644 index 00000000..2fa7dcf3 --- /dev/null +++ b/BLAZAMDatabase/Migrations/Sqlite/20240418222213_Add_Dev_Logging_Opt_OutSqlite.cs @@ -0,0 +1,40 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BLAZAM.Database.Migrations.Sqlite +{ + /// + public partial class Add_Dev_Logging_Opt_OutSqlite : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "SendDeveloperAnalytics", + table: "AppSettings", + type: "INTEGER", + nullable: false, + defaultValue: true); + + migrationBuilder.AddColumn( + name: "SendLogsToDeveloper", + table: "AppSettings", + type: "INTEGER", + nullable: false, + defaultValue: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "SendDeveloperAnalytics", + table: "AppSettings"); + + migrationBuilder.DropColumn( + name: "SendLogsToDeveloper", + table: "AppSettings"); + } + } +} diff --git a/BLAZAMDatabase/Migrations/Sqlite/20240501175432_Add_RequirePasswordChange_To_TemplatesSqlite.Designer.cs b/BLAZAMDatabase/Migrations/Sqlite/20240501175432_Add_RequirePasswordChange_To_TemplatesSqlite.Designer.cs new file mode 100644 index 00000000..6adbd8ec --- /dev/null +++ b/BLAZAMDatabase/Migrations/Sqlite/20240501175432_Add_RequirePasswordChange_To_TemplatesSqlite.Designer.cs @@ -0,0 +1,1798 @@ +// +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.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20240501175432_Add_RequirePasswordChange_To_TemplatesSqlite")] + partial class Add_RequirePasswordChange_To_TemplatesSqlite + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.18"); + + modelBuilder.Entity("AccessLevelFieldAccessMapping", b => + { + b.Property("AccessLevelsId") + .HasColumnType("INTEGER"); + + b.Property("FieldMapId") + .HasColumnType("INTEGER"); + + b.HasKey("AccessLevelsId", "FieldMapId"); + + b.HasIndex("FieldMapId"); + + b.ToTable("AccessLevelFieldAccessMapping"); + }); + + modelBuilder.Entity("AccessLevelObjectAccessMapping", b => + { + b.Property("AccessLevelsId") + .HasColumnType("INTEGER"); + + b.Property("ObjectMapId") + .HasColumnType("INTEGER"); + + b.HasKey("AccessLevelsId", "ObjectMapId"); + + b.HasIndex("ObjectMapId"); + + b.ToTable("AccessLevelObjectAccessMapping"); + }); + + modelBuilder.Entity("AccessLevelPermissionMapping", b => + { + b.Property("AccessLevelsId") + .HasColumnType("INTEGER"); + + b.Property("PermissionMapsId") + .HasColumnType("INTEGER"); + + b.HasKey("AccessLevelsId", "PermissionMapsId"); + + b.HasIndex("PermissionMapsId"); + + b.ToTable("AccessLevelPermissionMapping"); + }); + + modelBuilder.Entity("AppUserChatRoom", b => + { + b.Property("ChatRoomId") + .HasColumnType("INTEGER"); + + b.Property("MembersId") + .HasColumnType("INTEGER"); + + b.HasKey("ChatRoomId", "MembersId"); + + b.HasIndex("MembersId"); + + b.ToTable("AppUserChatRoom"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.ADSettings", b => + { + b.Property("Id") + .HasColumnType("INTEGER"); + + b.Property("ApplicationBaseDN") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FQDN") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Password") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ServerAddress") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ServerPort") + .HasColumnType("INTEGER"); + + b.Property("UseTLS") + .HasColumnType("INTEGER"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT"); + + 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("INTEGER"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FieldName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FieldType") + .HasColumnType("INTEGER"); + + 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 + }); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.ActiveDirectoryFieldObjectType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ActiveDirectoryFieldId") + .HasColumnType("INTEGER"); + + b.Property("CustomActiveDirectoryFieldId") + .HasColumnType("INTEGER"); + + b.Property("ObjectType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("CustomActiveDirectoryFieldId"); + + b.ToTable("ActiveDirectoryFieldObjectMappings"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.AppSettings", b => + { + b.Property("Id") + .HasColumnType("INTEGER"); + + b.Property("AnalyticsId") + .HasColumnType("TEXT"); + + b.Property("AppFQDN") + .HasColumnType("TEXT"); + + b.Property("AppIcon") + .HasColumnType("BLOB"); + + b.Property("AppName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AutoUpdate") + .HasColumnType("INTEGER"); + + b.Property("AutoUpdateTime") + .HasColumnType("TEXT"); + + b.Property("ForceHTTPS") + .HasColumnType("INTEGER"); + + b.Property("InstallationCompleted") + .HasColumnType("INTEGER"); + + b.Property("LastUpdateCheck") + .HasColumnType("TEXT"); + + b.Property("MOTD") + .HasColumnType("TEXT"); + + b.Property("MyrtilleURL") + .HasColumnType("TEXT"); + + b.Property("SSLCertificateCipher") + .HasColumnType("TEXT"); + + b.Property("SendDeveloperAnalytics") + .HasColumnType("INTEGER"); + + b.Property("SendLogsToDeveloper") + .HasColumnType("INTEGER"); + + b.Property("UpdateBranch") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdateDomain") + .HasColumnType("TEXT"); + + b.Property("UpdatePassword") + .HasColumnType("TEXT"); + + b.Property("UpdateUsername") + .HasColumnType("TEXT"); + + b.Property("UseUpdateCredentials") + .HasColumnType("INTEGER"); + + b.Property("UserHelpdeskURL") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("AppSettings", t => + { + t.HasCheckConstraint("CK_Table_Column", "[Id] = 1"); + }); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.DirectoryEntryAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AfterAction") + .HasColumnType("TEXT"); + + b.Property("BeforeAction") + .HasColumnType("TEXT"); + + b.Property("IpAddress") + .HasColumnType("TEXT"); + + b.Property("Sid") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Target") + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .HasColumnType("TEXT"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("DirectoryEntryAuditLogs"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.LogonAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AfterAction") + .HasColumnType("TEXT"); + + b.Property("BeforeAction") + .HasColumnType("TEXT"); + + b.Property("IpAddress") + .HasColumnType("TEXT"); + + b.Property("Target") + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .HasColumnType("TEXT"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("LogonAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.PermissionsAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AfterAction") + .HasColumnType("TEXT"); + + b.Property("BeforeAction") + .HasColumnType("TEXT"); + + b.Property("IpAddress") + .HasColumnType("TEXT"); + + b.Property("Target") + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .HasColumnType("TEXT"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("PermissionsAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.RequestAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AfterAction") + .HasColumnType("TEXT"); + + b.Property("BeforeAction") + .HasColumnType("TEXT"); + + b.Property("IpAddress") + .HasColumnType("TEXT"); + + b.Property("Target") + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .HasColumnType("TEXT"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("RequestAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.SettingsAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AfterAction") + .HasColumnType("TEXT"); + + b.Property("BeforeAction") + .HasColumnType("TEXT"); + + b.Property("IpAddress") + .HasColumnType("TEXT"); + + b.Property("Target") + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .HasColumnType("TEXT"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("SettingsAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Audit.SystemAuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AfterAction") + .HasColumnType("TEXT"); + + b.Property("BeforeAction") + .HasColumnType("TEXT"); + + b.Property("IpAddress") + .HasColumnType("TEXT"); + + b.Property("Target") + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .HasColumnType("TEXT"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("SystemAuditLog"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.AuthenticationSettings", b => + { + b.Property("Id") + .HasColumnType("INTEGER"); + + b.Property("AdminPassword") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DuoApiHost") + .HasColumnType("TEXT"); + + b.Property("DuoClientId") + .HasColumnType("TEXT"); + + b.Property("DuoClientSecret") + .HasColumnType("TEXT"); + + b.Property("DuoEnabled") + .HasColumnType("INTEGER"); + + b.Property("DuoUnreachableBehavior") + .HasColumnType("INTEGER"); + + b.Property("SessionTimeout") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("AuthenticationSettings", t => + { + t.HasCheckConstraint("CK_Table_Column", "[Id] = 1"); + }); + + 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("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("IsPublic") + .HasColumnType("INTEGER"); + + b.Property("MembersHash") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("ChatRooms"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Chat.UnreadChatMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChatMessageId") + .HasColumnType("INTEGER"); + + b.Property("ChatRoomId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChatMessageId"); + + b.ToTable("UnreadChatMessages"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.CustomActiveDirectoryField", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FieldName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("FieldType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("CustomActiveDirectoryFields"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.EmailSettings", b => + { + b.Property("Id") + .HasColumnType("INTEGER"); + + b.Property("AdminBcc") + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("FromAddress") + .HasColumnType("TEXT"); + + b.Property("FromName") + .HasColumnType("TEXT"); + + b.Property("ReplyToAddress") + .HasColumnType("TEXT"); + + b.Property("ReplyToName") + .HasColumnType("TEXT"); + + b.Property("SMTPPassword") + .HasColumnType("TEXT"); + + b.Property("SMTPPort") + .HasColumnType("INTEGER"); + + b.Property("SMTPServer") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SMTPUsername") + .HasColumnType("TEXT"); + + b.Property("UseSMTPAuth") + .HasColumnType("INTEGER"); + + b.Property("UseTLS") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("EmailSettings", t => + { + t.HasCheckConstraint("CK_Table_Column", "[Id] = 1"); + }); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.EmailTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("BCC") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Body") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CC") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TemplateName") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("EmailTemplates"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Permissions.AccessLevel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + 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("INTEGER"); + + b.Property("AccessLevelId") + .HasColumnType("INTEGER"); + + b.Property("AllowOrDeny") + .HasColumnType("INTEGER"); + + b.Property("ObjectActionId") + .HasColumnType("INTEGER"); + + b.Property("ObjectType") + .HasColumnType("INTEGER"); + + 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("INTEGER"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + 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("INTEGER"); + + b.Property("CustomFieldId") + .HasColumnType("INTEGER"); + + b.Property("FieldAccessLevelId") + .HasColumnType("INTEGER"); + + b.Property("FieldId") + .HasColumnType("INTEGER"); + + b.Property("ObjectType") + .HasColumnType("INTEGER"); + + 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("INTEGER"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + 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("INTEGER"); + + b.Property("AllowDisabled") + .HasColumnType("INTEGER"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("ObjectAccessLevelId") + .HasColumnType("INTEGER"); + + b.Property("ObjectType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ObjectAccessLevelId"); + + b.ToTable("AccessLevelObjectMapping"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Permissions.ObjectAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + 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("INTEGER"); + + b.Property("DelegateSid") + .IsRequired() + .HasColumnType("BLOB"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("IsSuperAdmin") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("DelegateSid") + .IsUnique(); + + b.ToTable("PermissionDelegate"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Permissions.PermissionMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("OU") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("PermissionMap"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Templates.DirectoryTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AllowCustomGroups") + .HasColumnType("INTEGER"); + + b.Property("Category") + .HasColumnType("TEXT"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("DisplayNameFormula") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ObjectType") + .HasColumnType("INTEGER"); + + b.Property("ParentOU") + .HasColumnType("TEXT"); + + b.Property("ParentTemplateId") + .HasColumnType("INTEGER"); + + b.Property("PasswordFormula") + .HasColumnType("TEXT"); + + b.Property("RequirePasswordChange") + .HasColumnType("INTEGER"); + + b.Property("UsernameFormula") + .HasColumnType("TEXT"); + + b.Property("Visible") + .HasColumnType("INTEGER"); + + 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("INTEGER"); + + b.Property("CustomFieldId") + .HasColumnType("INTEGER"); + + b.Property("DirectoryTemplateId") + .HasColumnType("INTEGER"); + + b.Property("Editable") + .HasColumnType("INTEGER"); + + b.Property("FieldId") + .HasColumnType("INTEGER"); + + b.Property("Required") + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("TEXT"); + + 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("INTEGER"); + + b.Property("DirectoryTemplateId") + .HasColumnType("INTEGER"); + + b.Property("GroupSid") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DirectoryTemplateId"); + + b.ToTable("DirectoryTemplateGroups"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.AppUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("APIToken") + .HasColumnType("TEXT"); + + b.Property("DarkMode") + .HasColumnType("INTEGER"); + + b.Property("Email") + .HasColumnType("TEXT"); + + b.Property("ProfilePicture") + .HasColumnType("BLOB"); + + b.Property("SearchDisabledComputers") + .HasColumnType("INTEGER"); + + b.Property("SearchDisabledUsers") + .HasColumnType("INTEGER"); + + b.Property("Theme") + .HasColumnType("TEXT"); + + b.Property("UserGUID") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserGUID") + .IsUnique(); + + b.ToTable("UserSettings"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.NotificationMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Dismissable") + .HasColumnType("INTEGER"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Link") + .HasColumnType("TEXT"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("NotificationMessages"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.ReadNewsItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("NewsItemId") + .HasColumnType("REAL"); + + b.Property("NewsItemUpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("ReadNewsItems"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.UserDashboardWidget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Order") + .HasColumnType("INTEGER"); + + b.Property("Slot") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("WidgetType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserDashboardWidgets"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.UserFavoriteEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DN") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserFavoriteEntries"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.UserNotification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("IsRead") + .HasColumnType("INTEGER"); + + b.Property("NotificationId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NotificationId"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotifications"); + }); + + modelBuilder.Entity("BLAZAM.Server.Data.ChatMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChatRoomId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChatRoomId"); + + b.HasIndex("UserId"); + + b.ToTable("ChatMessages"); + }); + + modelBuilder.Entity("PermissionDelegatePermissionMapping", b => + { + b.Property("PermissionDelegatesId") + .HasColumnType("INTEGER"); + + b.Property("PermissionsMapsId") + .HasColumnType("INTEGER"); + + 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/Sqlite/20240501175432_Add_RequirePasswordChange_To_TemplatesSqlite.cs b/BLAZAMDatabase/Migrations/Sqlite/20240501175432_Add_RequirePasswordChange_To_TemplatesSqlite.cs new file mode 100644 index 00000000..493e36e3 --- /dev/null +++ b/BLAZAMDatabase/Migrations/Sqlite/20240501175432_Add_RequirePasswordChange_To_TemplatesSqlite.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BLAZAM.Database.Migrations.Sqlite +{ + /// + public partial class Add_RequirePasswordChange_To_TemplatesSqlite : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "RequirePasswordChange", + table: "DirectoryTemplates", + type: "INTEGER", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "RequirePasswordChange", + table: "DirectoryTemplates"); + } + } +} diff --git a/BLAZAMDatabase/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs b/BLAZAMDatabase/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs index 12bf6806..24aa299b 100644 --- a/BLAZAMDatabase/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs +++ b/BLAZAMDatabase/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs @@ -15,7 +15,7 @@ partial class SqliteDatabaseContextModelSnapshot : ModelSnapshot protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "7.0.17"); + modelBuilder.HasAnnotation("ProductVersion", "7.0.18"); modelBuilder.Entity("AccessLevelFieldAccessMapping", b => { @@ -449,6 +449,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("SSLCertificateCipher") .HasColumnType("TEXT"); + b.Property("SendDeveloperAnalytics") + .HasColumnType("INTEGER"); + + b.Property("SendLogsToDeveloper") + .HasColumnType("INTEGER"); + b.Property("UpdateBranch") .IsRequired() .HasColumnType("TEXT"); @@ -1210,6 +1216,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PasswordFormula") .HasColumnType("TEXT"); + b.Property("RequirePasswordChange") + .HasColumnType("INTEGER"); + b.Property("UsernameFormula") .HasColumnType("TEXT"); diff --git a/BLAZAMDatabase/Models/AppSettings.cs b/BLAZAMDatabase/Models/AppSettings.cs index af61e8da..e9c18746 100644 --- a/BLAZAMDatabase/Models/AppSettings.cs +++ b/BLAZAMDatabase/Models/AppSettings.cs @@ -45,6 +45,19 @@ public string AppName /// public bool ForceHTTPS { get; set; } + + /// + /// Whether to send error and debug logs to the dev log seq destination + /// + [DefaultValue(true)] + public bool SendLogsToDeveloper { get; set; } = true; + + /// + /// Whether to send usage analytics to the dev gooogle analytics destination + /// + [DefaultValue(true)] + public bool SendDeveloperAnalytics { get; set; } = true; + [ValidFQDN] public string? AppFQDN { get; set; } diff --git a/BLAZAMDatabase/Models/Templates/DirectoryTemplate.cs b/BLAZAMDatabase/Models/Templates/DirectoryTemplate.cs index a1ed725a..6dd09d50 100644 --- a/BLAZAMDatabase/Models/Templates/DirectoryTemplate.cs +++ b/BLAZAMDatabase/Models/Templates/DirectoryTemplate.cs @@ -38,11 +38,11 @@ public class DirectoryTemplate : RecoverableAppDbSetBase [NotMapped] - public string EffectiveDisplayNameFormula + public string? EffectiveDisplayNameFormula { get { - return GetEffectiveValue(t => t.DisplayNameFormula, t => t.EffectiveDisplayNameFormula); + return GetEffectiveValue(t => t.DisplayNameFormula, t => t.EffectiveDisplayNameFormula); } set => DisplayNameFormula = value; @@ -50,23 +50,35 @@ public string EffectiveDisplayNameFormula public string? PasswordFormula { get; set; } [NotMapped] - public string EffectivePasswordFormula + public string? EffectivePasswordFormula { get { - return GetEffectiveValue(t => t.PasswordFormula, t => t.EffectivePasswordFormula); + return GetEffectiveValue(t => t.PasswordFormula, t => t.EffectivePasswordFormula); } set => PasswordFormula = value; } + public bool? RequirePasswordChange { get; set; } + [NotMapped] + public bool? EffectiveRequirePasswordChange + { + get + { + return GetEffectiveValue(t => t.RequirePasswordChange, t => t.EffectiveRequirePasswordChange); + + } + set => RequirePasswordChange = value; + } + public string? UsernameFormula { get; set; } [NotMapped] - public string EffectiveUsernameFormula + public string? EffectiveUsernameFormula { get { - return GetEffectiveValue(t => t.UsernameFormula, t => t.EffectiveUsernameFormula); + return GetEffectiveValue(t => t.UsernameFormula, t => t.EffectiveUsernameFormula); } set => UsernameFormula = value; @@ -74,23 +86,23 @@ public string EffectiveUsernameFormula public string? ParentOU { get; set; } [NotMapped] - public string EffectiveParentOU + public string? EffectiveParentOU { get { - return GetEffectiveValue(t=>t.ParentOU,t=>t.EffectiveParentOU); + return GetEffectiveValue(t=>t.ParentOU,t=>t.EffectiveParentOU); } set => ParentOU = value; } - private string GetEffectiveValue(FunclocalSelector, Func effectiveSelector) + private T? GetEffectiveValue(FunclocalSelector, Func effectiveSelector) { if (localSelector.Invoke(this) == null) { - if (ParentTemplate == null) return ""; + if (ParentTemplate == null) return default(T); var effectiveValue = effectiveSelector.Invoke(ParentTemplate); if (effectiveValue == null) - return ""; + return default(T); else return effectiveValue; } diff --git a/BLAZAMEmail/BLAZAMEmail.csproj b/BLAZAMEmail/BLAZAMEmail.csproj index 6cbc4bf1..7a91a14a 100644 --- a/BLAZAMEmail/BLAZAMEmail.csproj +++ b/BLAZAMEmail/BLAZAMEmail.csproj @@ -9,7 +9,7 @@ - + diff --git a/BLAZAMEmailMessage/BLAZAMEmailMessage.csproj b/BLAZAMEmailMessage/BLAZAMEmailMessage.csproj index a36bd3c4..742cc519 100644 --- a/BLAZAMEmailMessage/BLAZAMEmailMessage.csproj +++ b/BLAZAMEmailMessage/BLAZAMEmailMessage.csproj @@ -13,7 +13,7 @@ - + diff --git a/BLAZAMGui/BLAZAMGui.csproj b/BLAZAMGui/BLAZAMGui.csproj index 7c0c7974..dbfa75d2 100644 --- a/BLAZAMGui/BLAZAMGui.csproj +++ b/BLAZAMGui/BLAZAMGui.csproj @@ -24,13 +24,13 @@ - - - + + + - + diff --git a/BLAZAMGui/Navs/Buttons/NavBrowseButton.razor b/BLAZAMGui/Navs/Buttons/NavBrowseButton.razor index 0a19b9d4..b390a7ca 100644 --- a/BLAZAMGui/Navs/Buttons/NavBrowseButton.razor +++ b/BLAZAMGui/Navs/Buttons/NavBrowseButton.razor @@ -8,8 +8,7 @@ Disabled=@(Monitor.DirectoryConnectionStatus != ServiceConnectionState.Up) Title="@AppLocalization["Browse"]" Icon="@Icons.Material.Filled.ViewList"> - + {if(entry is IADOrganizationalUnit ou) return (ou.CanReadUsersInSubOus || ou.CanReadNonOUs); return false;}) SelectedEntryChanged="@((entry)=>{SelectedEntryChanged.InvokeAsync(entry);})" /> @code { diff --git a/BLAZAMGui/UI/Computers/ComputerSharedPrinters.razor b/BLAZAMGui/UI/Computers/ComputerSharedPrinters.razor index cd06b600..6bd35f5e 100644 --- a/BLAZAMGui/UI/Computers/ComputerSharedPrinters.razor +++ b/BLAZAMGui/UI/Computers/ComputerSharedPrinters.razor @@ -20,7 +20,7 @@ @if (context.Item.ADPrinter != null) { - @context.Item.ShareName + @context.Item.ShareName } else { diff --git a/BLAZAMGui/UI/Computers/RegisterPrintersModalContent.razor b/BLAZAMGui/UI/Computers/RegisterPrintersModalContent.razor index f619e4b5..deddd658 100644 --- a/BLAZAMGui/UI/Computers/RegisterPrintersModalContent.razor +++ b/BLAZAMGui/UI/Computers/RegisterPrintersModalContent.razor @@ -23,7 +23,7 @@ - + @@ -84,23 +84,26 @@ } - private void destinationOUChanged(IADOrganizationalUnit newDestinationOU) + private void destinationOUChanged(IDirectoryEntryAdapter newDst) { - if (destinationOU == newDestinationOU) return; - destinationOU = newDestinationOU; - if (destinationOU != null && selectedPrinters != null && selectedPrinters.Count > 0) + if (newDst is IADOrganizationalUnit newDestinationOU) { - validated = true; - Modal.YesText = AppLocalization["Register"]; - Modal.OnYes = RegisterSelectedPrinters; - Modal.RefreshView(); - } - else - { - Modal.YesText = AppLocalization["Next"]; - Modal.OnYes = (() => { activePanel = 1; InvokeAsync(StateHasChanged); }); - Modal.RefreshView(); + if (destinationOU == newDestinationOU) return; + destinationOU = newDestinationOU; + if (destinationOU != null && selectedPrinters != null && selectedPrinters.Count > 0) + { + validated = true; + Modal.YesText = AppLocalization["Register"]; + Modal.OnYes = RegisterSelectedPrinters; + Modal.RefreshView(); + } + else + { + Modal.YesText = AppLocalization["Next"]; + Modal.OnYes = (() => { activePanel = 1; InvokeAsync(StateHasChanged); }); + Modal.RefreshView(); + } } } // protected override bool ValidateModal() diff --git a/BLAZAMGui/UI/Dashboard/CurrentUserDashboardWidgets.razor b/BLAZAMGui/UI/Dashboard/CurrentUserDashboardWidgets.razor index e5b1b9f4..c812516b 100644 --- a/BLAZAMGui/UI/Dashboard/CurrentUserDashboardWidgets.razor +++ b/BLAZAMGui/UI/Dashboard/CurrentUserDashboardWidgets.razor @@ -10,7 +10,7 @@ T="UserDashboardWidget" Items="CurrentUser.State?.Preferences?.DashboardWidgets.OrderBy(uw => uw.Slot).ThenBy(uw => uw.Order)" ItemsSelector="ItemSelector" ItemDropped="ItemDropped" - Class="d-flex flex-wrap flex-grow-1 mud-width-full "> + Class="d-flex flex-wrap flex-grow-1 mud-width-full mt-5"> @@ -57,12 +57,23 @@ } else { - It's lonely in here. Click the + button to add some widgets... + + + + + + It's lonely in here. Click the + button to add some widgets... + + + + + } - + + - + diff --git a/BLAZAMGui/UI/Dashboard/Widgets/ChangedEntriesWidget.razor b/BLAZAMGui/UI/Dashboard/Widgets/ChangedEntriesWidget.razor index d76eddaf..019aa729 100644 --- a/BLAZAMGui/UI/Dashboard/Widgets/ChangedEntriesWidget.razor +++ b/BLAZAMGui/UI/Dashboard/Widgets/ChangedEntriesWidget.razor @@ -2,7 +2,7 @@ @attribute [Authorize] @code { - List deletedObjects { get; set; } = new(); + List changdEntries { get; set; } = new(); protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); + Task.Run(async () => + + { + var search = new ADSearch(); + search.Fields.Changed = DateTime.Now.AddDays(-1); + changdEntries = (await search.SearchAsync()).Where(x => x.CanRead).ToList(); + LoadingData = false; + await InvokeAsync(StateHasChanged); + + }); + - var search = new ADSearch(); - search.Fields.Changed = DateTime.Now.AddDays(-1); - deletedObjects = await search.SearchAsync(); - LoadingData = false; - await InvokeAsync(StateHasChanged); - } void RowClicked(DataGridRowClickEventArgs args) @@ -69,7 +74,7 @@ GoTo(args.Item); } } - + void GoTo(IDirectoryEntryAdapter args) { Nav.NavigateTo(args.SearchUri); diff --git a/BLAZAMGui/UI/Dashboard/Widgets/ChangedPasswordsWidget.razor b/BLAZAMGui/UI/Dashboard/Widgets/ChangedPasswordsWidget.razor index 4d51ce33..78b06042 100644 --- a/BLAZAMGui/UI/Dashboard/Widgets/ChangedPasswordsWidget.razor +++ b/BLAZAMGui/UI/Dashboard/Widgets/ChangedPasswordsWidget.razor @@ -8,7 +8,7 @@ @foreach (var user in LockedUsers) { - + @user.DisplayName
diff --git a/BLAZAMGui/UI/Dashboard/Widgets/DisabledUsersWidget.razor b/BLAZAMGui/UI/Dashboard/Widgets/DisabledUsersWidget.razor index a3e3e9a0..8ead42a3 100644 --- a/BLAZAMGui/UI/Dashboard/Widgets/DisabledUsersWidget.razor +++ b/BLAZAMGui/UI/Dashboard/Widgets/DisabledUsersWidget.razor @@ -1,6 +1,6 @@ @inherits Widget @attribute [Authorize] -
+

Disabled users changed in the last 90 days

@@ -8,7 +8,7 @@ @foreach (var user in LockedUsers) { - + @user.DisplayName
diff --git a/BLAZAMGui/UI/Groups/AssignToModalContent.razor b/BLAZAMGui/UI/Groups/AssignToModalContent.razor index 5f5925d0..0e7af1c4 100644 --- a/BLAZAMGui/UI/Groups/AssignToModalContent.razor +++ b/BLAZAMGui/UI/Groups/AssignToModalContent.razor @@ -8,7 +8,8 @@ } - @AppLocalization["or"] - + - - @if (CopyFrom != null) + + @if (CopyFrom != null) { @@ -121,7 +122,7 @@ public EventCallback OnGroupMembershipChange { get; set; } /// - /// The directry entry that we are assigning + /// The directory entry that we are assigning /// [Parameter] public IGroupableDirectoryAdapter DirectoryModel { get; set; } diff --git a/BLAZAMGui/UI/Groups/AssignedGroup.razor b/BLAZAMGui/UI/Groups/AssignedGroup.razor index 9b570f66..30ec5b67 100644 --- a/BLAZAMGui/UI/Groups/AssignedGroup.razor +++ b/BLAZAMGui/UI/Groups/AssignedGroup.razor @@ -1,11 +1,10 @@ @inherits DirectoryModelComponent - + @if (Group != null) { - var linkAdd = "/groups/search/" + Group.GroupName; - @@ -14,7 +13,7 @@ @if (AllowUnassign) { - + } } diff --git a/BLAZAMGui/UI/Groups/RenameGroupModalContent.razor b/BLAZAMGui/UI/Groups/RenameGroupModalContent.razor index 79abdcf9..803c18bb 100644 --- a/BLAZAMGui/UI/Groups/RenameGroupModalContent.razor +++ b/BLAZAMGui/UI/Groups/RenameGroupModalContent.razor @@ -3,9 +3,9 @@ @if (Group.CanEditField(ActiveDirectoryFields.SAMAccountName)) { - - + + diff --git a/BLAZAMGui/UI/Inputs/ADAutoComplete.razor b/BLAZAMGui/UI/Inputs/ADAutoComplete.razor index aa3e151a..a833261c 100644 --- a/BLAZAMGui/UI/Inputs/ADAutoComplete.razor +++ b/BLAZAMGui/UI/Inputs/ADAutoComplete.razor @@ -6,9 +6,10 @@ Label="@Label" AnchorOrigin="@AnchorOrigin" TransformOrigin="@TransformOrigin" -@bind-Value="SelectedResult" -@bind-Text=@SearchTerm -@ref=AutoComplete + @bind-Value="SelectedResult" + @bind-Text=@SearchTerm + @ref=AutoComplete + AutoFocus=@AutoFocus SearchFuncWithCancel="@GetResults" DebounceInterval=500 ResetValueOnEmptyText="true" @@ -56,14 +57,14 @@ @AppLocalization["Show more"] - - More results than shown... - - - + + More results than shown... + + + -@code { - #nullable disable warnings + @code { +#nullable disable warnings [Parameter] public Func Validation { get; set; } [Parameter] @@ -84,6 +85,8 @@ [Parameter] public bool Disabled { get; set; } + [Parameter] + public bool AutoFocus { get; set; } /// /// The maximum number of results to show in the autocomplete suggestion list @@ -128,7 +131,7 @@ async Task ShowMoreResults() { MaxResults += 10; - await GetResults(SearchTerm,new()); + await GetResults(SearchTerm, new()); await InvokeAsync(StateHasChanged); } @@ -190,11 +193,11 @@ - private async Task> GetResults(string searchText ,CancellationToken token) + private async Task> GetResults(string searchText, CancellationToken token) { var newSource = new CancellationTokenSource(); token = newSource.Token; - foreach(var source in _cancellationList) + foreach (var source in _cancellationList) { source.Cancel(); } @@ -203,7 +206,7 @@ return await Task.Run(() => { - + if (!token.IsCancellationRequested && searchText != null) { SearchResults = new List(); @@ -213,10 +216,10 @@ search.ObjectTypeFilter = SearchObjectType; search.GeneralSearchTerm = searchText.Replace(" ", "*"); search.EnabledOnly = !SearchDisabled; - search.MaxResults = MaxResults+1; + search.MaxResults = MaxResults + 1; if (!search.GeneralSearchTerm.Equals(String.Empty)) { - + var temp = (search.Search(token)).Where(r => r.CanRead); if (!token.IsCancellationRequested) @@ -235,7 +238,7 @@ temp = filteredResults; } } - if (!token.IsCancellationRequested) + if (!token.IsCancellationRequested) { SearchResults = temp; return SearchResults; diff --git a/BLAZAMGui/UI/Inputs/TreeViews/ADTreeView.razor b/BLAZAMGui/UI/Inputs/TreeViews/ADTreeView.razor new file mode 100644 index 00000000..1fe8047f --- /dev/null +++ b/BLAZAMGui/UI/Inputs/TreeViews/ADTreeView.razor @@ -0,0 +1,40 @@ +@inherits OUTreeViewBase + +@Label + + + + + + + + + + +@if (RootOU == null || !RootOU.Any() || LoadingData) +{ + + +} + + + + diff --git a/BLAZAMGui/UI/Inputs/TreeViews/ADTreeView.razor.cs b/BLAZAMGui/UI/Inputs/TreeViews/ADTreeView.razor.cs new file mode 100644 index 00000000..8a655fed --- /dev/null +++ b/BLAZAMGui/UI/Inputs/TreeViews/ADTreeView.razor.cs @@ -0,0 +1,74 @@ +using BLAZAM.ActiveDirectory.Adapters; +using BLAZAM.ActiveDirectory.Interfaces; +using BLAZAM.Common.Data; +using Microsoft.AspNetCore.Components; +using Microsoft.EntityFrameworkCore; +using MudBlazor; +using Color = MudBlazor.Color; + +namespace BLAZAM.Gui.UI.Inputs.TreeViews +{ + public partial class ADTreeView : OUTreeViewBase + { +#nullable disable warnings + /// + /// If true all directory entry types will be listed. + /// If false, only OU's will be shown. + /// + /// + /// Default value is true + /// + [Parameter] + public bool ShowAllEntries { get; set; } = true; + + + + + + + private HashSet? GetItems(IDirectoryEntryAdapter parent) + { + if (parent.IsExpanded || parent.CachedChildren != null) + { + + var items = parent.Children + .Where(c => (c.ObjectType == ActiveDirectoryObjectType.OU && ShouldShowOU(c)) || c.CanRead) + .MoveToTop(c => c.ObjectType == ActiveDirectoryObjectType.OU); + if (!ShowAllEntries) + { + items = items.Where(i => i.ObjectType == ActiveDirectoryObjectType.OU); + } + var hashst = items.ToHashSet(); + return hashst; + } + return null; + } + protected async Task> GetChildrenAsync(IDirectoryEntryAdapter parentNode) + { + return await Task.Run(() => + { + return GetChildren(parentNode); + + }); + } + protected HashSet GetChildren(IDirectoryEntryAdapter parentNode) + { + + if (ShowAllEntries) + { + var children = parentNode.Children.ToHashSet(); + return children; + + } + else if (parentNode is IADOrganizationalUnit ou) + { + + var children = ou.Children.Where(c => c.ObjectType == ActiveDirectoryObjectType.OU).ToHashSet(); + return children; + } + return new(); + + + } + } +} \ No newline at end of file diff --git a/BLAZAMGui/UI/Inputs/TreeViews/OUTreeView.razor b/BLAZAMGui/UI/Inputs/TreeViews/OUTreeView.razor new file mode 100644 index 00000000..6d7a4775 --- /dev/null +++ b/BLAZAMGui/UI/Inputs/TreeViews/OUTreeView.razor @@ -0,0 +1,66 @@ +@inherits OUTreeViewBase + +@Label + + + + + + @* + @{ + string itemIcon = Icons.Material.Filled.Folder; + } + @if (context.IsExpanded) + { + itemIcon = Icons.Material.Filled.FolderOpen; + } + @if (Badge != null) + { + + + + @context.CanonicalName + + @EndAdornment?.Invoke(context) + + + } + else + { + + + @context.CanonicalName + @EndAdornment?.Invoke(context) + } + *@ + + + + +@if (RootOU == null || !RootOU.Any() || LoadingData) +{ + + +} + + + + diff --git a/BLAZAMGui/UI/Inputs/TreeViews/OUTreeView.razor.cs b/BLAZAMGui/UI/Inputs/TreeViews/OUTreeView.razor.cs new file mode 100644 index 00000000..5ccb5475 --- /dev/null +++ b/BLAZAMGui/UI/Inputs/TreeViews/OUTreeView.razor.cs @@ -0,0 +1,64 @@ +using BLAZAM.ActiveDirectory.Adapters; +using BLAZAM.ActiveDirectory.Interfaces; +using Microsoft.AspNetCore.Components; +using Microsoft.EntityFrameworkCore; +using MudBlazor; + +namespace BLAZAM.Gui.UI.Inputs.TreeViews +{ + public partial class OUTreeView:OUTreeViewBase + { +#nullable disable warnings + + + + + [Parameter] + public RenderFragment? EndAdornment { get; set; } + + HashSet GetChildren(IDirectoryEntryAdapter context) + { + if (context is IADOrganizationalUnit ou) + { + if (ou.IsExpanded) + { + return ou.TreeViewSubOUs.Where(o=>ShouldShowOU(o)).ToHashSet(); + } + else + { + return ou.CachedTreeViewSubOUs.Where(o => ShouldShowOU(o)).ToHashSet(); + } + } + return new HashSet(); + } + async Task> GetChildrenAsync(IDirectoryEntryAdapter parentNode) + { + return await Task.Run(() => + { + return GetChildren(parentNode); + + + }); + } + + + + + + + + + + + + + + + + + + + + + } +} \ No newline at end of file diff --git a/BLAZAMGui/UI/Inputs/TreeViews/OUTreeViewBase.cs b/BLAZAMGui/UI/Inputs/TreeViews/OUTreeViewBase.cs new file mode 100644 index 00000000..30d4192d --- /dev/null +++ b/BLAZAMGui/UI/Inputs/TreeViews/OUTreeViewBase.cs @@ -0,0 +1,193 @@ +using BLAZAM.ActiveDirectory.Adapters; +using Microsoft.EntityFrameworkCore; +using MudBlazor; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Color = MudBlazor.Color; + +namespace BLAZAM.Gui.UI.Inputs.TreeViews +{ + public class OUTreeViewBase : AppComponentBase + { + + protected ADOrganizationalUnit TopLevel; + IADOrganizationalUnit? _startingSelectedNode; + + + IDirectoryEntryAdapter? _selectedEntry; + + [Parameter] + public bool StartRootExpanded { get; set; } = true; + + [Parameter] + public string? Label { get; set; } + + [Parameter] + public HashSet RootOU { get; set; } = new HashSet(); + [Parameter] + public IADOrganizationalUnit? StartingSelectedOU + { + get => _startingSelectedNode; set + { + if (value == _startingSelectedNode) return; + _startingSelectedNode = value; + _selectedEntry = value; + + + StartingSelectedOUChanged.InvokeAsync(value); + } + + } + + [Parameter] + public EventCallback StartingSelectedOUChanged + { + get; set; + } + + [Parameter] + public IDirectoryEntryAdapter? SelectedEntry + { + get => _selectedEntry; set + { + if (value == _selectedEntry) return; + if (value != null) + { + var cache = _selectedEntry; + + _selectedEntry = value; + if (cache == null && RootOU.Count>0 && value == RootOU.First()) return; + + + SelectedEntryChanged.InvokeAsync(value); + + + //if (TopLevel == null) + // OnInitializedAsync(); + + if(RootOU.Count > 0) + OpenToSelected(); + + } + } + + } + + [Parameter] + public EventCallback SelectedEntryChanged { get; set; } + [Parameter] + public Func? EndText { get; set; } + + protected Color GetItemColor(IDirectoryEntryAdapter item) + { + if (item is IAccountDirectoryAdapter account) + { + if (account.Disabled) return Color.Error; + if (account.LockedOut) return Color.Warning; + if (account.Created > DateTime.Now.AddDays(-14)) return Color.Success; + } + return Color.Default; + } + protected async Task InitializeTreeView() + { + //Wait a few milliseconds to trip the async into acutally awaiting + await Task.Delay(500); + + //ApplicationBaseOUs = Directory.OUs.FindSubOusByDN(null); + + + if (RootOU is null || RootOU.Count < 1) + { + TopLevel = new ADOrganizationalUnit(); + TopLevel.Parse(directory: Directory, directoryEntry: Directory.GetDirectoryEntry()); + _ = TopLevel.SubOUs; + RootOU = new HashSet() { TopLevel as IDirectoryEntryAdapter }; + } + if (StartingSelectedOU == null) + { + StartingSelectedOU = TopLevel; + + } + + OpenToSelected(); + LoadingData = false; + await InvokeAsync(StateHasChanged); + } + + + + + + + + + + + + + protected override async Task OnInitializedAsync() + { + await base.OnInitializedAsync(); + + await InitializeTreeView(); + + } + + protected void OpenToSelected() + { + + if (StartRootExpanded) + { + if (!SelectedEntry.Equals(RootOU)) + { + IDirectoryEntryAdapter? firstThing = RootOU.First(); + if (firstThing is IADOrganizationalUnit openThis) + { + openThis.IsExpanded = true; + while (openThis != null) + { + var child = openThis.SubOUs.Where(c => SelectedEntry.DN.Contains(c.DN) && !SelectedEntry.DN.Equals(c.DN)).FirstOrDefault(); + if (child != null) + { + child.IsExpanded = true; + + _ = (child as IADOrganizationalUnit)?.TreeViewSubOUs; + openThis = child as IADOrganizationalUnit; + } + else + { + var matchingOU = openThis.SubOUs.Where(c => SelectedEntry.DN.Equals(c.DN)).FirstOrDefault(); + if (matchingOU != null) + matchingOU.IsSelected = true; + break; + } + + + } + } + } + } + //InvokeAsync(StateHasChanged); + + + } + [Parameter] + public Func? AdditionalVisibilityFilters { get; set; } + protected bool ShouldShowOU(IDirectoryEntryAdapter entry) + { + if (entry is IADOrganizationalUnit ou) + { + if (ou.CanRead) + return true; + if (AdditionalVisibilityFilters != null) + { + if(AdditionalVisibilityFilters(entry)) return true; + } + } + return false; + } + } +} diff --git a/BLAZAMGui/UI/OU/MoveToOUModalContent.razor b/BLAZAMGui/UI/OU/MoveToOUModalContent.razor index e6a8cb3a..f6acbac3 100644 --- a/BLAZAMGui/UI/OU/MoveToOUModalContent.razor +++ b/BLAZAMGui/UI/OU/MoveToOUModalContent.razor @@ -3,11 +3,9 @@ Choose OU -@* + - *@ - @code { @@ -48,7 +46,7 @@ DirectoryModel.MoveTo(ouToMoveTo); - SnackBarService.Warning(DirectoryModel.CanonicalName + " has been moved to " + SelectedOU.CanonicalName + ", but changes need to be saved."); + SnackBarService.Warning(DirectoryModel.CanonicalName + " has been moved to " + ouToMoveTo.CanonicalName + ", but changes need to be saved."); await ModelChanged.InvokeAsync(); Close(); return; diff --git a/BLAZAMGui/UI/OU/OUTreeView.razor b/BLAZAMGui/UI/OU/OUTreeView.razor deleted file mode 100644 index f5e1108e..00000000 --- a/BLAZAMGui/UI/OU/OUTreeView.razor +++ /dev/null @@ -1,256 +0,0 @@ -@inherits AppComponentBase - -@Label - - - - - - @* - @{ - string itemIcon = Icons.Material.Filled.Folder; - } - @if (context.IsExpanded) - { - itemIcon = Icons.Material.Filled.FolderOpen; - } - @if (Badge != null) - { - - - - @context.CanonicalName - - @EndAdornment?.Invoke(context) - - - } - else - { - - - @context.CanonicalName - @EndAdornment?.Invoke(context) - } - *@ - - - - -@if (RootOU == null || !RootOU.Any() || LoadingData) -{ - - -} - - - -@code { - #nullable disable warnings - Dictionary OULoadingStates = new(); - - [Parameter] - public bool StartRootExpanded { get; set; } = true; - - [Parameter] - public string? Label { get; set; } - [Parameter] - public Func? EndText { get; set; } - - - [Parameter] - public object? Badge { get; set; } - - - [Parameter] - public RenderFragment? EndAdornment { get; set; } - - IADOrganizationalUnit? _selectedNode; - - [Parameter] - public HashSet RootOU { get; set; } = new HashSet(); - - - IADOrganizationalUnit? _startingSelectedNode; - [Parameter] - public IADOrganizationalUnit? StartingSelectedOU - { - get => _startingSelectedNode; set - { - if (value == _startingSelectedNode) return; - _startingSelectedNode = value; - _selectedNode = value; - - - StartingSelectedOUChanged.InvokeAsync(value); - } - - } - - [Parameter] - public EventCallback StartingSelectedOUChanged - { - get; set; - } - - [Parameter] - public IADOrganizationalUnit? SelectedOU - { - get => _selectedNode; set - { - if (value == _selectedNode) return; - if (value != null && value.CanRead) - { - _selectedNode = value; - //if (TopLevel == null) - // OnInitializedAsync(); - //OpenToSelected(); - SelectedOUChanged.InvokeAsync(value); - } - } - - } - - [Parameter] - public EventCallback SelectedOUChanged { get; set; } - - ADOrganizationalUnit TopLevel; - - - MudTreeView? OUTree { get; set; } - - - IList ExpandedNodes = new List(); - protected override async Task OnInitializedAsync() - { - await base.OnInitializedAsync(); - - - - //await InvokeAsync(StateHasChanged); - - await InitializeTreeView(); - - } - async Task InitializeTreeView() - { - //Wait a few milliseconds to trip the async into acutally awaiting - await Task.Delay(500); - - //ApplicationBaseOUs = Directory.OUs.FindSubOusByDN(null); - - - if (RootOU is null || RootOU.Count < 1) - { - TopLevel = new ADOrganizationalUnit(); - TopLevel.Parse(directory: Directory, directoryEntry: Directory.GetDirectoryEntry()); - _ = TopLevel.SubOUs; - RootOU = new HashSet() { TopLevel }; - } - if (StartingSelectedOU == null) - { - SelectedOU = TopLevel; - } - else - OpenToSelected(); - LoadingData = false; - await InvokeAsync(StateHasChanged); - } - void OpenToSelected() - { - - if (StartRootExpanded) - { - if (!SelectedOU.Equals(RootOU)) - { - IADOrganizationalUnit? openThis = RootOU.First(); - openThis.IsExpanded = true; - while (openThis != null) - { - var child = openThis.SubOUs.Where(c => SelectedOU.DN.Contains(c.DN) && !SelectedOU.DN.Equals(c.DN)).FirstOrDefault(); - if (child != null) - { - child.IsExpanded = true; - _ = child.TreeViewSubOUs; - openThis = child; - } - else - { - var matchingOU = openThis.SubOUs.Where(c => SelectedOU.DN.Equals(c.DN)).FirstOrDefault(); - if (matchingOU != null) - matchingOU.IsSelected = true; - break; - } - - - } - } - } - //InvokeAsync(StateHasChanged); - - - } - bool CanExpand(IADOrganizationalUnit context) - { - var result = context.HasChildren; - return result; - } - HashSet GetChildren(IADOrganizationalUnit context) - { - if (context.IsExpanded) - { - return context.TreeViewSubOUs; - } - else - { - return context.CachedTreeViewSubOUs; - } - } - async Task> GetChildrenAsync(IADOrganizationalUnit parentNode) - { - return await Task.Run(() => - { - return GetChildren(parentNode); - - - }); - } - - - - - - - - - - - - - - - - - - - - -} diff --git a/BLAZAMGui/UI/OU/RenameOUModalContent.razor b/BLAZAMGui/UI/OU/RenameOUModalContent.razor index 1ff8bd8d..3b58ef14 100644 --- a/BLAZAMGui/UI/OU/RenameOUModalContent.razor +++ b/BLAZAMGui/UI/OU/RenameOUModalContent.razor @@ -5,9 +5,9 @@ @if (OU.CanReadField(ActiveDirectoryFields.CanonicalName)) { - - - + + + diff --git a/BLAZAMGui/UI/Outputs/ADTreeView.razor b/BLAZAMGui/UI/Outputs/ADTreeView.razor deleted file mode 100644 index 66953093..00000000 --- a/BLAZAMGui/UI/Outputs/ADTreeView.razor +++ /dev/null @@ -1,257 +0,0 @@ -@inherits AppComponentBase - -@Label - - - - - - - - - - -@if (RootOU == null || !RootOU.Any() || LoadingData) -{ - - -} - -@code { -#nullable disable warnings - /// - /// If true all directory entry types will be listed. - /// If false, only OU's will bee shown. - /// - [Parameter] - public bool ShowAllEntries { get; set; } = true; - - [Parameter] - public bool StartRootExpanded { get; set; } = true; - - [Parameter] - public string? Label { get; set; } - - [Parameter] - public Color TextColor { get; set; } = Color.Default; - [Parameter] - public Func? EndText { get; set; } - - - IDirectoryEntryAdapter? _selectedNode; - - [Parameter] - public HashSet RootOU { get; set; } = new HashSet(); - - - IADOrganizationalUnit? _startingSelectedNode; - [Parameter] - public IADOrganizationalUnit? StartingSelectedOU - { - get => _startingSelectedNode; set - { - if (value == _startingSelectedNode) return; - _startingSelectedNode = value; - _selectedNode = value; - - - StartingSelectedOUChanged.InvokeAsync(value); - } - - } - - [Parameter] - public EventCallback StartingSelectedOUChanged - { - get; set; - } - - [Parameter] - public IDirectoryEntryAdapter? SelectedEntry - { - get => _selectedNode; set - { - if (value == _selectedNode) return; - if (value != null && value.CanRead) - { - var cache = _selectedNode; - - _selectedNode = value; - if (cache == null && value == RootOU.First()) return; - - - SelectedEntryChanged.InvokeAsync(value); - - - //if (TopLevel == null) - // OnInitializedAsync(); - OpenToSelected(); - - } - } - - } - - [Parameter] - public EventCallback SelectedEntryChanged { get; set; } - - ADOrganizationalUnit TopLevel; - - - - - IList ExpandedNodes = new List(); - protected override async Task OnInitializedAsync() - { - await base.OnInitializedAsync(); - - - - //await InvokeAsync(StateHasChanged); - - await InitializeTreeView(); - - } - async Task InitializeTreeView() - { - //Wait a few milliseconds to trip the async into acutally awaiting - await Task.Delay(50); - - - - if (RootOU is null || RootOU.Count < 1) - { - TopLevel = new ADOrganizationalUnit(); - TopLevel.Parse(directory: Directory, directoryEntry: Directory.GetDirectoryEntry()); - _ = TopLevel.SubOUs; - RootOU = new HashSet() { TopLevel }; - } - if (StartingSelectedOU == null) - { - SelectedEntry = TopLevel; - } - else - OpenToSelected(); - LoadingData = false; - await InvokeAsync(StateHasChanged); - } - void OpenToSelected() - { - //ExpandedNodes.Clear(); - //var newExpandedNodes = new List(ExpandedNodes); - if (StartRootExpanded) - { - //newExpandedNodes.Add(TopLevel); - if (!SelectedEntry.Equals(RootOU)) - { - IDirectoryEntryAdapter? openThis = RootOU.First(); - openThis.IsExpanded = true; - while (openThis != null) - { - var child = openThis.Children.Where(c => SelectedEntry.DN.Contains(c.DN) && !SelectedEntry.DN.Equals(c.DN)).FirstOrDefault(); - if (child != null) - { - child.IsExpanded = true; - openThis = child; - } - else - { - var matchingOU = openThis.Children.Where(c => SelectedEntry.DN.Equals(c.DN)).FirstOrDefault(); - if (matchingOU != null) - matchingOU.IsSelected = true; - break; - } - - - } - } - } - - - } - private Color GetItemColor(IDirectoryEntryAdapter item) - { - if (item is IAccountDirectoryAdapter account) - { - if (account.Disabled) return Color.Error; - if (account.LockedOut) return Color.Warning; - if (account.Created > DateTime.Now.AddDays(-14)) return Color.Success; - } - return Color.Default; - } - private HashSet? GetItems(IDirectoryEntryAdapter parent) - { - if (parent.IsExpanded || parent.CachedChildren != null) - { - - var items = parent.Children.Where(c => c.ObjectType == ActiveDirectoryObjectType.OU && ShouldShowOU(c) || c.CanRead).MoveToTop(c => c.ObjectType == ActiveDirectoryObjectType.OU); - if (!ShowAllEntries) - { - items = items.Where(i => i.ObjectType == ActiveDirectoryObjectType.OU); - } - var hashst = items.ToHashSet(); - return hashst; - } - return null; - } - async Task> GetChildrenAsync(IDirectoryEntryAdapter parentNode) - { - return await Task.Run(() => - { - return GetChildren(parentNode); - - }); - } - - HashSet GetChildren(IDirectoryEntryAdapter parentNode) - { - - if (ShowAllEntries) - { - var children = parentNode.Children.ToHashSet(); - return children; - - } - else if (parentNode is IADOrganizationalUnit ou) - { - - var children = ou.Children.Where(c => c.ObjectType == ActiveDirectoryObjectType.OU).ToHashSet(); - return children; - } - return new(); - - - } - - private bool ShouldShowOU(IDirectoryEntryAdapter entry) - { - if (entry is IADOrganizationalUnit ou) - { - if (ou.CanRead) - return true; - if (ou.CanReadInSubOus) - return true; - } - return false; - } - -} - - diff --git a/BLAZAMGui/UI/Outputs/AppDocumentationButton.razor b/BLAZAMGui/UI/Outputs/AppDocumentationButton.razor index 54b0632b..8ee085cf 100644 --- a/BLAZAMGui/UI/Outputs/AppDocumentationButton.razor +++ b/BLAZAMGui/UI/Outputs/AppDocumentationButton.razor @@ -1,10 +1,11 @@ @inject IStringLocalizer AppLocalization @if (!Page.IsNullOrEmpty()) { - + + - - @foreach (var item in unreadItems.OrderByDescending(x => x.UpdatedAt)) - { - - - - @item.Title - - @if (item.Link != null) - { - @item.Link - } - - - } - @if (showRead) - { - foreach (var item in readItems.OrderByDescending(x => x.UpdatedAt)) + + @if (readItems.Count > 0) + { + + } + @foreach (var item in unreadItems.OrderByDescending(x => x.UpdatedAt)) { - - - @item.Title + @item.Title @if (item.Link != null) { - @item.Link + @item.Link } } - } - else - { - @AppLocalization["There is nothing new to see here"] - } + @if (showRead) + { + foreach (var item in readItems.OrderByDescending(x => x.UpdatedAt)) + { + + + + + + @item.Title + + @if (item.Link != null) + { + @item.Link + } + + + } + } + else + { + if (unreadItems.Count == 0) + { + @AppLocalization["There is nothing new to see here"] + } + } + } diff --git a/BLAZAMGui/UI/Outputs/StatusCheck.razor b/BLAZAMGui/UI/Outputs/StatusCheck.razor index 3cf9ed68..4baad88d 100644 --- a/BLAZAMGui/UI/Outputs/StatusCheck.razor +++ b/BLAZAMGui/UI/Outputs/StatusCheck.razor @@ -8,7 +8,7 @@ } else { - @Text + @Text } diff --git a/BLAZAMGui/UI/Search/SearchControls.razor b/BLAZAMGui/UI/Search/SearchControls.razor new file mode 100644 index 00000000..1dd07bfb --- /dev/null +++ b/BLAZAMGui/UI/Search/SearchControls.razor @@ -0,0 +1,92 @@ +@inherits AppComponentBase + + + + + { SearchService.SeachObjectType=ActiveDirectoryObjectType.All; })>@AppLocalization["All"] + + + { SearchService.SeachObjectType=ActiveDirectoryObjectType.User; })>@AppLocalization["User"] + + + + { SearchService.SeachObjectType=ActiveDirectoryObjectType.Group; })>@AppLocalization["Group"] + + + + { SearchService.SeachObjectType=ActiveDirectoryObjectType.OU; })>@AppLocalization["OU"] + + + + { SearchService.SeachObjectType=ActiveDirectoryObjectType.Computer; })>@AppLocalization["Computer"] + + + + { SearchService.SeachObjectType=ActiveDirectoryObjectType.Printer; })>@AppLocalization["Printer"] + + + + + + + +@if (IsAdmin == true || CurrentUser.State?.CanSearchDisabled(ActiveDirectoryObjectType.User) == true) +{ + var buttonColor = Color.Error; + if (!SearchService.IncludeDisabled) + + { + buttonColor = Color.Success; + } + { + SearchService.IncludeDisabled= !SearchService.IncludeDisabled; + await InvokeAsync(StateHasChanged); + }) Color=buttonColor> + Enabled Only + + + + + + +} +@{ + var adornmentIcon = Icons.Material.Filled.AccountTree; + switch (SearchService.SeachObjectType) + { + case ActiveDirectoryObjectType.User: + adornmentIcon = Icons.Material.Filled.Person; + break; + case ActiveDirectoryObjectType.Group: + adornmentIcon = Icons.Material.Filled.People; + break; + case ActiveDirectoryObjectType.OU: + adornmentIcon = Icons.Material.Filled.Folder; + break; + case ActiveDirectoryObjectType.Computer: + adornmentIcon = Icons.Material.Filled.Computer; + break; + case ActiveDirectoryObjectType.Printer: + adornmentIcon = Icons.Material.Filled.Print; + break; + } +} + + + + +@code { + +} diff --git a/BLAZAMGui/UI/Search/SearchPageHeader.razor b/BLAZAMGui/UI/Search/SearchPageHeader.razor index ef40ddfa..4119c466 100644 --- a/BLAZAMGui/UI/Search/SearchPageHeader.razor +++ b/BLAZAMGui/UI/Search/SearchPageHeader.razor @@ -5,102 +5,34 @@ - - - - - - { SearchService.SeachObjectType=ActiveDirectoryObjectType.All; })>@AppLocalization["All"] - - - { SearchService.SeachObjectType=ActiveDirectoryObjectType.User; })>@AppLocalization["User"] - - - - { SearchService.SeachObjectType=ActiveDirectoryObjectType.Group; })>@AppLocalization["Group"] - - - - { SearchService.SeachObjectType=ActiveDirectoryObjectType.OU; })>@AppLocalization["OU"] - - - - { SearchService.SeachObjectType=ActiveDirectoryObjectType.Computer; })>@AppLocalization["Computer"] - - - - { SearchService.SeachObjectType=ActiveDirectoryObjectType.Printer; })>@AppLocalization["Printer"] - - - - - - - - @if (IsAdmin == true || CurrentUser.State?.CanSearchDisabled(ActiveDirectoryObjectType.User) == true) - { - var buttonColor = Color.Error; - if (!SearchService.IncludeDisabled) - - { - buttonColor = Color.Success; - } - { - SearchService.IncludeDisabled= !SearchService.IncludeDisabled; - await InvokeAsync(StateHasChanged); - }) Color=buttonColor> - Enabled Only - - - - - - - } - @{ - var adornmentIcon = Icons.Material.Filled.AccountTree; - switch (SearchService.SeachObjectType) - { - case ActiveDirectoryObjectType.User: - adornmentIcon = Icons.Material.Filled.Person; - break; - case ActiveDirectoryObjectType.Group: - adornmentIcon = Icons.Material.Filled.People; - break; - case ActiveDirectoryObjectType.OU: - adornmentIcon = Icons.Material.Filled.Folder; - break; - case ActiveDirectoryObjectType.Computer: - adornmentIcon = Icons.Material.Filled.Computer; - break; - case ActiveDirectoryObjectType.Printer: - adornmentIcon = Icons.Material.Filled.Print; - break; - } - } - - - - - - + + + + + + + + + + + Search + + + + + + + + + + @code { + MudDrawer? _searchDrawer; + AppModal? _searchModal; List ObjectTypes = new() { ActiveDirectoryObjectType.All, ActiveDirectoryObjectType.User, diff --git a/BLAZAMGui/UI/SessionExpirationWarningProvider.razor b/BLAZAMGui/UI/SessionExpirationWarningProvider.razor index 8eccaf98..8ba7f367 100644 --- a/BLAZAMGui/UI/SessionExpirationWarningProvider.razor +++ b/BLAZAMGui/UI/SessionExpirationWarningProvider.razor @@ -52,13 +52,18 @@ + OnYes="@(()=>{Refresh();})" + Options=@(new DialogOptions{ + ClassBackground="blur-background", + CloseButton=false, + CloseOnEscapeKey=false, + DisableBackdropClick=true})> @AppLocalization["Your session has expired."] - + @code { private Timer? sessionTimeoutCheckTimer; AppModal? ExpirationWarningModal; diff --git a/BLAZAMGui/UI/Settings/ActiveDirectoryStatusPanel.razor b/BLAZAMGui/UI/Settings/ActiveDirectoryStatusPanel.razor index c6b86a0c..a642d055 100644 --- a/BLAZAMGui/UI/Settings/ActiveDirectoryStatusPanel.razor +++ b/BLAZAMGui/UI/Settings/ActiveDirectoryStatusPanel.razor @@ -2,8 +2,8 @@ @inherits AppComponentBase - Active Directory Connection Status - + @AppLocalization["Active Directory Connection Status"] + @if (showProgress) { @@ -11,68 +11,78 @@ } - - - Server Port Open - - - + + @AppLocalization["Server Port Open"] + - Credentials OK - + + - - - Connected + @AppLocalization["Credentials OK"] + - + + + @AppLocalization["Connected"] - - + + + + + + @AppLocalization["Connection Type"] + + + + + @* @if (_credStatus) { - var firstDC = Directory.DomainControllers.FirstOrDefault(); - if(firstDC!=null){ - - - Domain - @firstDC.Domain.Name - - - - Domain Mode - @firstDC.Domain.DomainMode - - - - Domain Level - @firstDC.Domain.DomainModeLevel - - - - Primary Domain Controller - @firstDC.Domain.PdcRoleOwner - - - - Domain - @Directory.DomainControllers.FirstOrDefault()?.Domain.Forest.RootDomain.Name - - - } - else - { - Could not reach Domain Controllers directly from application server. Please check DNS. - } + var firstDC = Directory.DomainControllers.FirstOrDefault(); + if(firstDC!=null){ + + + Domain + @firstDC.Domain.Name + + + + Domain Mode + @firstDC.Domain.DomainMode + + + + Domain Level + @firstDC.Domain.DomainModeLevel + + + + Primary Domain Controller + @firstDC.Domain.PdcRoleOwner + + + + Domain + @Directory.DomainControllers.FirstOrDefault()?.Domain.Forest.RootDomain.Name + + + } + else + { + Could not reach Domain Controllers directly from application server. Please check DNS. + } } *@ - + @code { - #nullable disable warnings +#nullable disable warnings [Parameter] public EventCallback DirectoryConnected { get; set; } @@ -173,7 +183,7 @@ else { - showProgress =false; + showProgress = false; } await InvokeAsync(StateHasChanged); diff --git a/BLAZAMGui/UI/Settings/ApplicationSettings.razor b/BLAZAMGui/UI/Settings/ApplicationSettings.razor index e5a3ad88..2608c5c8 100644 --- a/BLAZAMGui/UI/Settings/ApplicationSettings.razor +++ b/BLAZAMGui/UI/Settings/ApplicationSettings.razor @@ -24,7 +24,10 @@ - + diff --git a/BLAZAMGui/UI/Settings/AuthenticationSetting.razor b/BLAZAMGui/UI/Settings/AuthenticationSetting.razor index c7a578b6..c1d666f0 100644 --- a/BLAZAMGui/UI/Settings/AuthenticationSetting.razor +++ b/BLAZAMGui/UI/Settings/AuthenticationSetting.razor @@ -108,8 +108,14 @@ { duoHealthCheckResult = null; await InvokeAsync(StateHasChanged); - - duoHealthCheckResult = await Duo.DoHealthCheckAsync(); + try + { + duoHealthCheckResult = await Duo.DoHealthCheckAsync(); + } + catch + { + + } await InvokeAsync(StateHasChanged); } private void UpdateTimeoutDisplay() diff --git a/BLAZAMGui/UI/Settings/EmailSettings.razor b/BLAZAMGui/UI/Settings/EmailSettings.razor index 24c280ce..94b9fe1f 100644 --- a/BLAZAMGui/UI/Settings/EmailSettings.razor +++ b/BLAZAMGui/UI/Settings/EmailSettings.razor @@ -7,7 +7,9 @@ - + @@ -28,13 +30,19 @@ - + - + diff --git a/BLAZAMGui/UI/Settings/Permissions/ImpersonateUser.razor b/BLAZAMGui/UI/Settings/Permissions/ImpersonateUser.razor index 5e7a9f71..866e84ec 100644 --- a/BLAZAMGui/UI/Settings/Permissions/ImpersonateUser.razor +++ b/BLAZAMGui/UI/Settings/Permissions/ImpersonateUser.razor @@ -1,28 +1,35 @@ @using Newtonsoft.Json +@using System.Diagnostics @inherits AppComponentBase @inject IJSRuntime JSRuntime +@if ((CurrentUser.State.IsSuperAdmin && CurrentUser.Username != "Demo") || (CurrentUser.State.IsSuperAdmin|| Debugger.IsAttached)) +{ +
- + - - + Color=Color.Primary + ButtonType="ButtonType.Submit"> Impersonate User - - + -
+ + +} +else +{ + Impersonation is not available in demo mode. +} @code { private LoginRequest imperonationRequest = new(){ Impersonation=true}; public IDirectoryEntryAdapter? User { get; set; } diff --git a/BLAZAMGui/UI/Settings/Permissions/PermissionMapEditor.razor b/BLAZAMGui/UI/Settings/Permissions/PermissionMapEditor.razor index e89b64f1..c7d11eee 100644 --- a/BLAZAMGui/UI/Settings/Permissions/PermissionMapEditor.razor +++ b/BLAZAMGui/UI/Settings/Permissions/PermissionMapEditor.razor @@ -34,7 +34,7 @@ } else { - + @if (selectedPermissionDelegateNames != null) { @foreach (var pd in selectedPermissionDelegateNames.Split(SELECTION_DELIMITER)) diff --git a/BLAZAMGui/UI/Settings/Permissions/PermissionMapper.razor b/BLAZAMGui/UI/Settings/Permissions/PermissionMapper.razor index 4b7c36e8..d85c1b18 100644 --- a/BLAZAMGui/UI/Settings/Permissions/PermissionMapper.razor +++ b/BLAZAMGui/UI/Settings/Permissions/PermissionMapper.razor @@ -1,4 +1,5 @@ -@inherits AppComponentBase + +@inherits AppComponentBase

OU Privilege Mapper

@@ -6,8 +7,22 @@ + @bind-SelectedEntry="SelectedNode"> + + + + + + + +
+ + + + +@* + + EndText="@((context)=>context.DirectPermissionMappings.Any()?context.DirectPermissionMappings.Count().ToString():null)"> @if (@context.DirectPermissionMappings.Count() > 0) { @@ -26,19 +41,13 @@ } -
- - - - - - +*@ @code { -#nullable disable warnings + #nullable disable warnings OUTreeView? OUTree { get; set; } - IADOrganizationalUnit selectedNode; - IADOrganizationalUnit SelectedNode + IDirectoryEntryAdapter selectedNode; + IDirectoryEntryAdapter SelectedNode { get => selectedNode; set { @@ -48,7 +57,7 @@ } } - + IADOrganizationalUnit SelectedOU => SelectedNode as IADOrganizationalUnit; IList ExpandedNodes = new List(); HashSet ApplicationBaseOUs = new HashSet(); protected override async Task OnInitializedAsync() diff --git a/BLAZAMGui/UI/Settings/SystemSettings.razor b/BLAZAMGui/UI/Settings/SystemSettings.razor index bc5e69ea..b4229730 100644 --- a/BLAZAMGui/UI/Settings/SystemSettings.razor +++ b/BLAZAMGui/UI/Settings/SystemSettings.razor @@ -1,48 +1,95 @@ @inherits SettingsComponents @AppLocalization["System Settings"] - - @if (settings != null) + + @if (settings != null) { - + @AppLocalization["Manage Web Application"] + + + @AppLocalization["Restart Web Application"] + + + + Set up a GA4 account and enter your tracking ID here to collect data on the usage of your installation. - - Restart Web Application + + } - - - - Download Logs - + + + @AppLocalization["Data Collection Settings"] + + + + + + + We ask that you allow developer logging so we can quickly and transparently improve Blazam and to aid in our developement efforts. + + + + + + + + We ask that you allow developer analytics so we can understand how our app is used to focus our + efforts on what our users think matters most. + + + + + + + @AppLocalization["Logging"] + + + + + + + + + + + + Download Logs + Log Directory: @Loggers.LogPath - + - + + @AppLocalization["Resource Usage"] - - + + - + - - Save Changes + - - - @code { + Save Changes + + + +@code { #nullable disable warnings AppSettings? settings = new AppSettings(); @@ -66,7 +113,7 @@ [Inject] ApplicationManager applicationManager { get; set; } - + async Task RestartApplication() { if (await MessageService.Confirm("Are you sure you want to restart the application? All connected users will be disconnected.", "Restart Application")) diff --git a/BLAZAMGui/UI/Settings/Templates/EditDirectoryTemplate.razor b/BLAZAMGui/UI/Settings/Templates/EditDirectoryTemplate.razor index be2d5813..0c6e7a56 100644 --- a/BLAZAMGui/UI/Settings/Templates/EditDirectoryTemplate.razor +++ b/BLAZAMGui/UI/Settings/Templates/EditDirectoryTemplate.razor @@ -10,93 +10,94 @@ @AppLocalization["Current Template:"] @originalTemplate.Name - - - - - - - - - - - - + Label=@AppLocalization["Parent Template"] + Values="@dropdownTemplates.OrderBy(t=>t.Name)" + Value="@DirectoryTemplate.ParentTemplate" + ValueChanged="@ParentTemplateChanged" /> + + + + + + + + + + + - - {fn}:First Name
-
- + + {fn}:First Name
+
+ - {fi}:First Initial
-
- - {mn}:Middle Name
-
- - {mi}:Middle Initial
-
- - {ln}:Last Name
-
- - {li}:Last Initial
-
- - {username}:Username
-
- - {AlphaNum[u/l]}:Random letter or number (optional force uppercase/lowercase)
-
- - {Alpha[u/l]}:Random letter (optional force uppercase/lowercase)
-
- - {Num}:Random number
+ {fi}:First Initial
+
+ + {mn}:Middle Name
+
+ + {mi}:Middle Initial
+
+ + {ln}:Last Name
+
+ + {li}:Last Initial
+
+ + {username}:Username
+
+ + {AlphaNum[u/l]}:Random letter or number (optional force uppercase/lowercase)
+
+ + {Alpha[u/l]}:Random letter (optional force uppercase/lowercase)
+
+ + {Num}:Random number
-
-
-
+ + +
- - @{ - var usernameFromTemplate = GetParentOfValue(DirectoryTemplate.EffectiveUsernameFormula, template => template.UsernameFormula); - var displayNameFromTemplateName = GetParentOfValue(DirectoryTemplate.EffectiveDisplayNameFormula, template => template.DisplayNameFormula); - var passwordFromTemplateName = GetParentOfValue(DirectoryTemplate.EffectivePasswordFormula, template => template.PasswordFormula); ; + + @{ + var usernameFromTemplate = GetParentOfValue(DirectoryTemplate.EffectiveUsernameFormula, template => template.UsernameFormula); + var displayNameFromTemplateName = GetParentOfValue(DirectoryTemplate.EffectiveDisplayNameFormula, template => template.DisplayNameFormula); + var passwordFromTemplateName = GetParentOfValue(DirectoryTemplate.EffectivePasswordFormula, template => template.PasswordFormula); ; + var requirePasswordChangeFromTemplateName = GetParentOfValue(DirectoryTemplate.EffectiveRequirePasswordChange, template => template.RequirePasswordChange); ; } - @if (DirectoryTemplate.ParentTemplate != null && DirectoryTemplate.ParentTemplate.EffectiveUsernameFormula != DirectoryTemplate.EffectiveUsernameFormula) @@ -106,7 +107,7 @@ await ParentTemplateChanged(null); - @if (DirectoryTemplate.ParentTemplate != null && DirectoryTemplate.ParentTemplate.EffectiveDisplayNameFormula != DirectoryTemplate.EffectiveDisplayNameFormula) @@ -123,7 +124,7 @@ await ParentTemplateChanged(null); @if (DirectoryTemplate.ParentTemplate != null && DirectoryTemplate.ParentTemplate.EffectivePasswordFormula != DirectoryTemplate.EffectivePasswordFormula) @@ -131,6 +132,18 @@ await ParentTemplateChanged(null); { DirectoryTemplate.PasswordFormula=null;}) /> } + + + + + + + @if (DirectoryTemplate.ParentTemplate != null && DirectoryTemplate.ParentTemplate.EffectiveRequirePasswordChange != DirectoryTemplate.EffectiveRequirePasswordChange) + { + { DirectoryTemplate.RequirePasswordChange=null;}) /> + } + @@ -176,7 +189,7 @@ await ParentTemplateChanged(null); } })> @field.DisplayName - + } @@ -209,38 +222,38 @@ await ParentTemplateChanged(null); @cellContext.Item.FieldDisplayName - - - - - - - - {ValueChanged(newValue,cellContext.Item);}) /> - - - - - - - - - - - - - - - - - - @if (DirectoryTemplate.IsValueOverriden(cellContext.Item)) + + + + + + + + {ValueChanged(newValue,cellContext.Item);}) /> + + + + + + + + + + + + + + + + + + @if (DirectoryTemplate.IsValueOverriden(cellContext.Item)) { {await RemoveField(cellContext.Item);}) /> } @@ -270,8 +283,8 @@ await ParentTemplateChanged(null); @if (!DirectoryTemplate.ParentOU.IsNullOrEmpty() && DirectoryTemplate.ParentTemplateId != null && !DirectoryTemplate.ParentOU.IsNullOrEmpty()) { @@ -330,7 +343,7 @@ await ParentTemplateChanged(null); @buttonText - @if (DirectoryTemplate.Id == 0) + @if (DirectoryTemplate.Id == 0) { Cancel @@ -408,6 +421,8 @@ await ParentTemplateChanged(null); { if (_template == value) return; + if (Context != null) + value = Context?.DirectoryTemplates.First(dt => dt.Id == value.Id); _template = value; originalTemplate = value; DirectoryTemplateChanged.InvokeAsync(value); @@ -644,6 +659,10 @@ await ParentTemplateChanged(null); } else { + if (Context.EntityIsTracked(DirectoryTemplate)) + { + + } var result = await Context.SaveChangesAsync(); if (result > 0) { @@ -662,7 +681,7 @@ await ParentTemplateChanged(null); /// /// Null if the value comes from the current /// template, otherwise the source template - private DirectoryTemplate? GetParentOfValue(string value, Func valueSelector) + private DirectoryTemplate? GetParentOfValue(T? value, Func valueSelector) { var templateCursor = DirectoryTemplate; var templateValue = valueSelector.Invoke(templateCursor); diff --git a/BLAZAMGui/UI/Settings/UpdateSettings.razor b/BLAZAMGui/UI/Settings/UpdateSettings.razor index 8c3dffbe..f3c38494 100644 --- a/BLAZAMGui/UI/Settings/UpdateSettings.razor +++ b/BLAZAMGui/UI/Settings/UpdateSettings.razor @@ -57,7 +57,10 @@ - + @if (settings.UseUpdateCredentials) { Configure custom update credentials. @@ -120,7 +123,10 @@ - + diff --git a/BLAZAMGui/UI/Users/ChangeUserPasswordModalContent.razor b/BLAZAMGui/UI/Users/ChangeUserPasswordModalContent.razor index fe62d7e3..59f860d9 100644 --- a/BLAZAMGui/UI/Users/ChangeUserPasswordModalContent.razor +++ b/BLAZAMGui/UI/Users/ChangeUserPasswordModalContent.razor @@ -1,24 +1,24 @@ @inherits AppModalContent + + - + @* + + *@ -@* - - *@ + - + - - - -@AppLocalization["Require change"] - - + + @AppLocalization["Require change"] + + @code { - #nullable disable warnings +#nullable disable warnings string newPassword = ""; string newPasswordConfirm = ""; MudSwitch? requireChangeSwitch; @@ -38,19 +38,30 @@ //User.CommitChanges(); Modal.LoadingData = true; await InvokeAsync(StateHasChanged); - await Task.Run(async() => - + await Task.Run(async () => + { try { if (User.SetPassword(newPassword.ToSecureString(), requireChangeSwitch.Value)) { + if (requireChangeSwitch.Value) + { + User.RequirePasswordChange = true; + var job = await User.CommitChangesAsync(); + if (job.Result != JobResult.Passed) + { + + Loggers.ActiveDirectryLogger.Error("Could not set password change required when setting password."); + } + } SnackBarService.Success("Changed password for " + User.DisplayName); await AuditLogger.User.PasswordChanged(User, requireChangeSwitch.Value); await InvokeAsync(Close); + } else { @@ -62,9 +73,9 @@ { SnackBarService.Error(ex.Message + " " + ex.InnerException?.Message); } - + }); - + Modal.LoadingData = false; await InvokeAsync(StateHasChanged); } diff --git a/BLAZAMGui/UI/Users/Fields/HomeDriveSelect.razor b/BLAZAMGui/UI/Users/Fields/HomeDriveSelect.razor index 58a3f25e..f90d8cd5 100644 --- a/BLAZAMGui/UI/Users/Fields/HomeDriveSelect.razor +++ b/BLAZAMGui/UI/Users/Fields/HomeDriveSelect.razor @@ -1,7 +1,7 @@ @inherits MudSelect @code { + private string _driveLetter="D:"; + [Parameter] + public string DriveLetter + { + get => _driveLetter; set + { + if (_driveLetter == value) return; + _driveLetter = value; + DriveLetterChanged.InvokeAsync(value); + } + } + [Parameter] + public EventCallback DriveLetterChanged{ get; set; } } diff --git a/BLAZAMGui/UI/Users/NewTemplateUser.razor b/BLAZAMGui/UI/Users/NewTemplateUser.razor index 89c5ca31..26f12622 100644 --- a/BLAZAMGui/UI/Users/NewTemplateUser.razor +++ b/BLAZAMGui/UI/Users/NewTemplateUser.razor @@ -249,7 +249,7 @@ @@ -311,7 +311,7 @@ - Next + Next diff --git a/BLAZAMGui/UI/Users/NewUserNameEntry.razor b/BLAZAMGui/UI/Users/NewUserNameEntry.razor index 4b21cd1e..5c0709e3 100644 --- a/BLAZAMGui/UI/Users/NewUserNameEntry.razor +++ b/BLAZAMGui/UI/Users/NewUserNameEntry.razor @@ -5,7 +5,7 @@ - + diff --git a/BLAZAMGui/UI/Users/RenameUserModalContent.razor b/BLAZAMGui/UI/Users/RenameUserModalContent.razor index 6a9086ae..36e1b208 100644 --- a/BLAZAMGui/UI/Users/RenameUserModalContent.razor +++ b/BLAZAMGui/UI/Users/RenameUserModalContent.razor @@ -3,7 +3,7 @@ { @if (User.CanReadField(ActiveDirectoryFields.GivenName)) { - + diff --git a/BLAZAMGui/_Imports.razor b/BLAZAMGui/_Imports.razor index 7ce42f73..fb6b12fe 100644 --- a/BLAZAMGui/_Imports.razor +++ b/BLAZAMGui/_Imports.razor @@ -50,7 +50,7 @@ @using BLAZAM.Gui.UI.Modals @using BLAZAM.Gui.UI.Dashboard @using BLAZAM.Gui.Helper; - +@using BLAZAM.Gui.UI.Inputs.TreeViews @using BLAZAM.Gui.UI.Users @using BLAZAM.Gui.UI.Users.Fields @using BLAZAM.Gui.UI.OU diff --git a/BLAZAMLoggers/Loggers.cs b/BLAZAMLoggers/Loggers.cs index 7c9e13e4..cbe235e0 100644 --- a/BLAZAMLoggers/Loggers.cs +++ b/BLAZAMLoggers/Loggers.cs @@ -14,18 +14,10 @@ public static class Loggers public static string LogPath => _logPath; private static string _logPath; private static string _applicationVersion; - - private static string _seqAPIKey - { - get - { -#if (DEBUG) - return "xE50e1ljqtgLzHcu8pYC"; -#else - return "8TeLknA8XBk5ybamT5m9"; -#endif - } - } + public static bool SendToSeqServer { get; set; } = true; + public static string SeqServerUri { get; set; } + public static string InstallationId { get; set; } + public static string SeqAPIKey { get; set; } #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. public static ILogger RequestLogger { get; private set; } public static ILogger DatabaseLogger { get; private set; } @@ -34,7 +26,7 @@ private static string _seqAPIKey public static ILogger SystemLogger { get; set; } #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public static void SetupLoggers(string logPath,string applicationVersion="1.0") + public static void SetupLoggers(string logPath, string applicationVersion = "1.0") { _logPath = logPath; _applicationVersion = applicationVersion; @@ -43,15 +35,7 @@ public static void SetupLoggers(string logPath,string applicationVersion="1.0") ActiveDirectryLogger = SetupLogger(logPath + @"activedirectory\activedirectory.txt"); UpdateLogger = SetupLogger(logPath + @"update\update.txt", RollingInterval.Month); - Log.Logger = new LoggerConfiguration() - .Enrich.FromLogContext() - .Enrich.WithMachineName() - .Enrich.WithEnvironmentName() - .Enrich.WithEnvironmentUserName() - .Enrich.WithProperty("Application Name", "Blazam") - - .Enrich.WithProperty("Application Version", _applicationVersion) - + var systemLoggerBuilder = CreateLogBuilder() .WriteTo.File(logPath + @"system\system.txt", rollingInterval: RollingInterval.Hour, outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] {Message}{NewLine}{Exception}", @@ -60,38 +44,48 @@ public static void SetupLoggers(string logPath,string applicationVersion="1.0") { //lc.WriteTo.Console(); lc.Filter.ByExcluding(e => e.Level == LogEventLevel.Information).WriteTo.Console(); - }) - .WriteTo.Seq("http://logs.blazam.org:5341", apiKey: _seqAPIKey, restrictedToMinimumLevel: LogEventLevel.Warning) - .CreateLogger(); + }); + if (SendToSeqServer) + { + systemLoggerBuilder.WriteTo.Seq(SeqServerUri, apiKey: SeqAPIKey, restrictedToMinimumLevel: LogEventLevel.Warning); + } + Log.Logger = systemLoggerBuilder.CreateLogger(); SystemLogger = Log.Logger; //Serilog.Debugging.SelfLog.Enable(Console.Error); } - private static Serilog.ILogger SetupLogger(string logFilePath, RollingInterval rollingInterval = RollingInterval.Hour) + private static LoggerConfiguration CreateLogBuilder() { return new LoggerConfiguration() - .Enrich.FromLogContext() - .Enrich.WithMachineName() - .Enrich.WithEnvironmentName() - .Enrich.WithEnvironmentUserName() - .Enrich.WithProperty("Application Name", "Blazam") + .Enrich.FromLogContext() + .Enrich.WithMachineName() + .Enrich.WithEnvironmentName() + .Enrich.WithEnvironmentUserName() + .Enrich.WithProperty("Application Name", "Blazam") + .Enrich.WithProperty("Installation Id", InstallationId) + .Enrich.WithProperty("Application Version", _applicationVersion); + } - .Enrich.WithProperty("Application Version", _applicationVersion) - //.WriteTo.File(WritablePath+@"\logs\log.txt") - .WriteTo.File(logFilePath, - rollingInterval: rollingInterval, - outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}", - retainedFileTimeLimit: TimeSpan.FromDays(30)) + private static Serilog.ILogger SetupLogger(string logFilePath, RollingInterval rollingInterval = RollingInterval.Hour) + { + var loggerBuilder =CreateLogBuilder() + .WriteTo.File(logFilePath, + rollingInterval: rollingInterval, + outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}", + retainedFileTimeLimit: TimeSpan.FromDays(30)) - .WriteTo.Logger(lc => - { - //lc.WriteTo.Console(); - lc.Filter.ByExcluding(e => e.Level == LogEventLevel.Information).WriteTo.Console(); - }) - .WriteTo.Seq("http://logs.blazam.org:5341", apiKey: _seqAPIKey, restrictedToMinimumLevel: LogEventLevel.Warning) + .WriteTo.Logger(lc => + { + //lc.WriteTo.Console(); + lc.Filter.ByExcluding(e => e.Level == LogEventLevel.Information).WriteTo.Console(); + }); + if (SendToSeqServer) + { + loggerBuilder.WriteTo.Seq(SeqServerUri, apiKey: SeqAPIKey, restrictedToMinimumLevel: LogEventLevel.Warning); + } - .CreateLogger(); + return loggerBuilder.CreateLogger(); } } diff --git a/BLAZAMNav/BLAZAMNav.csproj b/BLAZAMNav/BLAZAMNav.csproj index 22bc2742..5fbe8d28 100644 --- a/BLAZAMNav/BLAZAMNav.csproj +++ b/BLAZAMNav/BLAZAMNav.csproj @@ -8,7 +8,7 @@ - + diff --git a/BLAZAMServices/BLAZAMServices.csproj b/BLAZAMServices/BLAZAMServices.csproj index 15d5f72a..407cb362 100644 --- a/BLAZAMServices/BLAZAMServices.csproj +++ b/BLAZAMServices/BLAZAMServices.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/BLAZAMSession/ApplicationNewsService.cs b/BLAZAMSession/ApplicationNewsService.cs index 1423e660..1f67e8af 100644 --- a/BLAZAMSession/ApplicationNewsService.cs +++ b/BLAZAMSession/ApplicationNewsService.cs @@ -15,20 +15,26 @@ namespace BLAZAM.Session public class ApplicationNewsService : IApplicationNewsService { private HttpClient _httpClient; + private HttpClient _secondaryHttpClient; private Timer? _pollingTimer; private bool _pollCompleted = false; private List _allNewsItems = new List(); - private List activeNewsItems => _allNewsItems.Where(x=>x.DeletedAt==null && x.Published==true && (x.ScheduledAt==null||x.ScheduledAtDateTime.Now)).ToList(); + private List activeNewsItems => _allNewsItems.Where(x => x.DeletedAt == null && x.Published == true && (x.ScheduledAt == null || x.ScheduledAt < DateTime.Now) && (x.ExpiresAt == null || x.ExpiresAt > DateTime.Now)).ToList(); public AppEvent OnNewItemsAvailable { get; set; } public ApplicationNewsService() { _httpClient = new HttpClient + { + BaseAddress = new Uri("https://blazam.org/api/"), + Timeout = TimeSpan.FromSeconds(60) + }; + _secondaryHttpClient = new HttpClient { BaseAddress = new Uri("https://blazam-news.azurewebsites.net/api/"), Timeout = TimeSpan.FromSeconds(60) }; _pollingTimer = new Timer(Tick, null, 10, 1000 * 60 * 15); - // GetAllNewsItems(); + // GetAllNewsItems(); } private async void Tick(object? state) @@ -41,17 +47,36 @@ private async Task GetAllNewsItems() try { _pollCompleted = false; - var apiResponse = await _httpClient.GetAsync("newsItems"); - if (apiResponse != null && apiResponse.IsSuccessStatusCode) + try { - var content = await apiResponse.Content.ReadAsStringAsync(); - var allNewsItems = JsonSerializer.Deserialize>(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); - if (allNewsItems != null) + var apiResponse = await _httpClient.GetAsync("newsItems"); + if (apiResponse != null && apiResponse.IsSuccessStatusCode) { - _allNewsItems = allNewsItems; - _pollCompleted = true; + var content = await apiResponse.Content.ReadAsStringAsync(); + var allNewsItems = JsonSerializer.Deserialize>(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + if (allNewsItems != null) + { + _allNewsItems = allNewsItems; + _pollCompleted = true; - OnNewItemsAvailable?.Invoke(); + OnNewItemsAvailable?.Invoke(); + } + } + } + catch + { + var apiResponse = await _secondaryHttpClient.GetAsync("newsItems"); + if (apiResponse != null && apiResponse.IsSuccessStatusCode) + { + var content = await apiResponse.Content.ReadAsStringAsync(); + var allNewsItems = JsonSerializer.Deserialize>(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + if (allNewsItems != null) + { + _allNewsItems = allNewsItems; + _pollCompleted = true; + + OnNewItemsAvailable?.Invoke(); + } } } } @@ -93,7 +118,8 @@ public List GetUnreadNewsItems(IApplicationUserState user) } } return unreadItems; - }catch (Exception ex) + } + catch (Exception ex) { Loggers.SystemLogger.Error("Error while trying to get unread news items for user. {@Error}", ex); return new(); @@ -116,7 +142,9 @@ public List GetReadNewsItems(IApplicationUserState user) return new(); - }catch (Exception ex) { + } + catch (Exception ex) + { Loggers.SystemLogger.Error("Error while trying to get read news items for user. {@Error}", ex); return new(); } diff --git a/BLAZAMSession/ApplicationUserState.cs b/BLAZAMSession/ApplicationUserState.cs index 350c308e..133a2c55 100644 --- a/BLAZAMSession/ApplicationUserState.cs +++ b/BLAZAMSession/ApplicationUserState.cs @@ -507,7 +507,7 @@ public bool HasPermission(string dnTarget, Func, } return false; } - + public bool HasActionPermission(string dnTarget, ObjectAction action, ActiveDirectoryObjectType objectType) { return HasPermission(dnTarget, p => p.Where(pm => diff --git a/BLAZAMSession/ApplicationUserStateService.cs b/BLAZAMSession/ApplicationUserStateService.cs index 086f3b9f..3a2ed11d 100644 --- a/BLAZAMSession/ApplicationUserStateService.cs +++ b/BLAZAMSession/ApplicationUserStateService.cs @@ -197,7 +197,7 @@ private void AddUserState(IApplicationUserState state) public void SetMFAUserState(string mfaToken,IApplicationUserState state) { _mfaLoginQueue.Add(mfaToken, state); - Task.Delay(60000).ContinueWith((val) => { + Task.Delay(900000).ContinueWith((val) => { _mfaLoginQueue.Remove(mfaToken); }); SetUserState(state); diff --git a/BLAZAMStatic/StaticAssets.cs b/BLAZAMStatic/StaticAssets.cs index 7af899e6..27087051 100644 --- a/BLAZAMStatic/StaticAssets.cs +++ b/BLAZAMStatic/StaticAssets.cs @@ -40,7 +40,7 @@ public class StaticAssets private static byte[]? GetDefaultIcon() { - var defaultIconFilePath = Path.GetFullPath(ApplicationInfo.applicationRoot + @"static\img\default_logo4.png"); + var defaultIconFilePath = Path.GetFullPath(ApplicationInfo.applicationRoot + @"static\img\default_logo5.png"); if (File.Exists(defaultIconFilePath)) return File.ReadAllBytes(defaultIconFilePath); return null; diff --git a/BLAZAMThemes/OrangeTheme.cs b/BLAZAMThemes/OrangeTheme.cs index 84a81439..31e38634 100644 --- a/BLAZAMThemes/OrangeTheme.cs +++ b/BLAZAMThemes/OrangeTheme.cs @@ -29,11 +29,13 @@ public OrangeTheme() darkPalette.ActionDefault = "#B19A7B"; darkPalette.Dark = "#1E180F"; - darkPalette.Primary = "#402D13"; + + darkPalette.Primary = "#AB8966"; darkPalette.AppbarBackground = "#403313"; darkPalette.DrawerBackground = "#1E1A0F"; darkPalette.DrawerText = "#c7c7c7"; - darkPalette.Secondary = "#765B2B"; + + darkPalette.Secondary = "#D49C51"; diff --git a/BLAZAMThemes/RedTheme.cs b/BLAZAMThemes/RedTheme.cs index 04cc310b..e42df941 100644 --- a/BLAZAMThemes/RedTheme.cs +++ b/BLAZAMThemes/RedTheme.cs @@ -23,10 +23,13 @@ public RedTheme() darkPalette.TextSecondary = "#A77E86"; darkPalette.ActionDefault = "#B17B7E"; darkPalette.Dark = "#1E110F"; + darkPalette.Primary = "#AB6666"; + darkPalette.Primary = "#401313"; darkPalette.AppbarBackground = "#401313"; darkPalette.DrawerBackground = "#1E0F0F"; - darkPalette.Secondary = "#421818"; + darkPalette.Secondary = "#D45151"; + } diff --git a/BLAZAMUpdate/ApplicationUpdate.cs b/BLAZAMUpdate/ApplicationUpdate.cs index e9ed0051..599dd43a 100644 --- a/BLAZAMUpdate/ApplicationUpdate.cs +++ b/BLAZAMUpdate/ApplicationUpdate.cs @@ -195,9 +195,9 @@ private async Task InitiateFileCopy(JobStep? step) //Update the updater first - Loggers.UpdateLogger.Debug("Copying updater script"); - Loggers.UpdateLogger.Debug("Source: " + UpdateStagingDirectory + "\\updater\\*"); - Loggers.UpdateLogger.Debug("Dest: " + _applicationRootDirectory + "updater\\"); + Loggers.UpdateLogger?.Debug("Copying updater script"); + Loggers.UpdateLogger?.Debug("Source: " + UpdateStagingDirectory + "\\updater\\*"); + Loggers.UpdateLogger?.Debug("Dest: " + _applicationRootDirectory + "updater\\"); using var context = await _dbFactory.CreateDbContextAsync(); @@ -205,14 +205,14 @@ private async Task InitiateFileCopy(JobStep? step) if (_applicationRootDirectory.Writable) { - Loggers.UpdateLogger.Warning("The application user has write permission to the application directory!"); + Loggers.UpdateLogger?.Warning("The application user has write permission to the application directory!"); try { return ApplyFiles(); } catch (Exception ex) { - Loggers.UpdateLogger.Error("Error applying update: {@Error}", ex); + Loggers.UpdateLogger?.Error("Error applying update: {@Error}", ex); } return false; @@ -236,7 +236,7 @@ private async Task InitiateFileCopy(JobStep? step) } catch (Exception ex) { - Loggers.UpdateLogger.Error("Error applying update: {@Error}", ex); + Loggers.UpdateLogger?.Error("Error applying update: {@Error}", ex); } return false; @@ -246,7 +246,7 @@ private async Task InitiateFileCopy(JobStep? step) } catch (ApplicationException ex) { - Loggers.UpdateLogger.Error("Unable to apply files {@Error}", ex); + Loggers.UpdateLogger?.Error("Unable to apply files {@Error}", ex); return false; } @@ -259,8 +259,8 @@ private async Task InitiateFileCopy(JobStep? step) private bool ApplyFiles() { - Loggers.UpdateLogger.Information("Running update as: " + WindowsIdentity.GetCurrent().Name); - Loggers.UpdateLogger.Information("Updating updater"); + Loggers.UpdateLogger?.Information("Running update as: " + WindowsIdentity.GetCurrent().Name); + Loggers.UpdateLogger?.Information("Updating updater"); @@ -268,13 +268,13 @@ private bool ApplyFiles() SystemDirectory updaterDir = new SystemDirectory(_applicationRootDirectory.Path + "updater\\"); updaterDirFromStagedUpdate.CopyTo(updaterDir); //File.Copy(UpdateStagingDirectory + "\\updater\\", _applicationRootDirectory + "updater\\", true); - Loggers.UpdateLogger.Information("Updater updated"); + Loggers.UpdateLogger?.Information("Updater updated"); //If the updater updated we can run the updater var updaterRan = InvokeUpdateExecutable(); if (updaterRan) { - Loggers.UpdateLogger.Information("Update process started"); + Loggers.UpdateLogger?.Information("Update process started"); return true; } @@ -313,18 +313,18 @@ private bool InvokeUpdateExecutable() public async Task Backup(JobStep? step) { - Loggers.UpdateLogger.Information("Attempting backup of current version to: " + BackupPath); + Loggers.UpdateLogger?.Information("Attempting backup of current version to: " + BackupPath); try { var result = await Task.Run(() => { return _applicationRootDirectory.CopyTo(BackupDirectory); }); - Loggers.UpdateLogger.Debug("Backup result: " + result.ToString()); + Loggers.UpdateLogger?.Debug("Backup result: " + result.ToString()); return result; } catch (Exception ex) { - Loggers.UpdateLogger.Error("Backup of current version failed: " + ex.Message); + Loggers.UpdateLogger?.Error("Backup of current version failed: " + ex.Message); return false; } } @@ -334,7 +334,7 @@ public async Task CleanDownload(IJobStep? step) { return await Task.Run(() => { - Loggers.UpdateLogger.Information("Attempting cleaning of download folder: " + UpdateFile); + Loggers.UpdateLogger?.Information("Attempting cleaning of download folder: " + UpdateFile); try { @@ -345,7 +345,7 @@ public async Task CleanDownload(IJobStep? step) } catch (Exception ex) { - Loggers.UpdateLogger.Error("Error while cleaning of download folder: " + UpdateFile + " {@Error}", ex); + Loggers.UpdateLogger?.Error("Error while cleaning of download folder: " + UpdateFile + " {@Error}", ex); return false; } @@ -363,7 +363,7 @@ public async Task CleanStaging(IJobStep? step) } catch (Exception ex) { - Loggers.UpdateLogger.Error("Error while cleaning staging directory. {@Error}", ex); + Loggers.UpdateLogger?.Error("Error while cleaning staging directory. {@Error}", ex); return true; } }); @@ -375,7 +375,7 @@ public async Task ExtractFiles(JobStep? step) if (!UpdateFile.Exists) return false; - Loggers.UpdateLogger.Debug("Attempting unzip of " + UpdateFile); + Loggers.UpdateLogger?.Debug("Attempting unzip of " + UpdateFile); UpdateStagingDirectory.EnsureCreated(); @@ -385,14 +385,13 @@ public async Task ExtractFiles(JobStep? step) { var zip = new ZipArchive(streamToReadFrom); zip.ExtractToDirectory(UpdateStagingDirectory.Path, true); - - Loggers.UpdateLogger.Debug(UpdateFile + " unzipped successfully to " + UpdateStagingDirectory); + Loggers.UpdateLogger?.Debug(UpdateFile + " unzipped successfully to " + UpdateStagingDirectory); return true; } catch (Exception ex) { - Loggers.UpdateLogger.Error("Error while extracting update zip {@Error}", ex); + Loggers.UpdateLogger?.Error("Error while extracting update zip {@Error}", ex); return false; } diff --git a/BLAZAMUpdate/BLAZAMUpdate.csproj b/BLAZAMUpdate/BLAZAMUpdate.csproj index d4754fb0..256054c5 100644 --- a/BLAZAMUpdate/BLAZAMUpdate.csproj +++ b/BLAZAMUpdate/BLAZAMUpdate.csproj @@ -10,7 +10,7 @@ - + diff --git a/BlazamUpdate/BLAZAMUpdate.csproj b/BlazamUpdate/BLAZAMUpdate.csproj index d4754fb0..256054c5 100644 --- a/BlazamUpdate/BLAZAMUpdate.csproj +++ b/BlazamUpdate/BLAZAMUpdate.csproj @@ -10,7 +10,7 @@ - + diff --git a/PlaywrightTests/PlaywrightTests.csproj b/PlaywrightTests/PlaywrightTests.csproj index 3d8d7033..c8f03435 100644 --- a/PlaywrightTests/PlaywrightTests.csproj +++ b/PlaywrightTests/PlaywrightTests.csproj @@ -13,11 +13,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/README.md b/README.md index 52fa6d42..065100cc 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # BLAZAM +## Introducing Blazam's new Logo + + ## Website [blazam.org](https://blazam.org) diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..3e581a6d --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,12 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| ------- | ------------------ | +| 0.x.x | :white_check_mark: | + + +## Reporting a Vulnerability + +Please report security vulnerability issues by email to support@blazam.org