From 95277e60ea8a613570d25eb112a6c71db3e3e100 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Sat, 28 Dec 2024 17:06:19 -0500 Subject: [PATCH 1/3] Implement Lockout Alerting --- BLAZAM/BLAZAM.csproj | 2 +- BLAZAM/ProgramHelpers.cs | 250 +- BLAZAMDatabase/Context/DatabaseContextBase.cs | 3 + BLAZAMDatabase/Context/IDatabaseContext.cs | 1 + ...Add_LockedOutUsers_Table_MySql.Designer.cs | 2270 +++++++++++++++++ ...28173828_Add_LockedOutUsers_Table_MySql.cs | 39 + .../MySqlDatabaseContextModelSnapshot.cs | 20 + ...6_Add_LockedOutUsers_Table_Sql.Designer.cs | 2270 +++++++++++++++++ ...1228173806_Add_LockedOutUsers_Table_Sql.cs | 36 + .../Sql/SqlDatabaseContextModelSnapshot.cs | 20 + ...dd_LockedOutUsers_Table_Sqlite.Designer.cs | 2182 ++++++++++++++++ ...8173741_Add_LockedOutUsers_Table_Sqlite.cs | 36 + .../SqliteDatabaseContextModelSnapshot.cs | 18 + BLAZAMDatabase/Models/GenericSidList.cs | 14 + .../Models/Notifications/NotificationType.cs | 11 +- BLAZAMEmailMessage/BLAZAMEmailMessage.csproj | 3 + .../Notifications/LockedOutEmailMessage.razor | 28 + .../OUNotificationSubscriptions.razor | 23 +- .../NotificationTypeExtentions.cs | 3 + .../Attributes/AutoStartBackgroundService.cs | 23 + .../ActiveDirectoryBackgroundServiceBase.cs | 20 + .../Background/BackgroundServiceBase.cs | 55 + .../Background/LockedOutUserMonitor.cs | 89 + .../NotificationGenerationService.cs | 7 + .../{ => Exceptions}/MFARequestedException.cs | 2 +- 25 files changed, 7325 insertions(+), 100 deletions(-) create mode 100644 BLAZAMDatabase/Migrations/MySql/20241228173828_Add_LockedOutUsers_Table_MySql.Designer.cs create mode 100644 BLAZAMDatabase/Migrations/MySql/20241228173828_Add_LockedOutUsers_Table_MySql.cs create mode 100644 BLAZAMDatabase/Migrations/Sql/20241228173806_Add_LockedOutUsers_Table_Sql.Designer.cs create mode 100644 BLAZAMDatabase/Migrations/Sql/20241228173806_Add_LockedOutUsers_Table_Sql.cs create mode 100644 BLAZAMDatabase/Migrations/Sqlite/20241228173741_Add_LockedOutUsers_Table_Sqlite.Designer.cs create mode 100644 BLAZAMDatabase/Migrations/Sqlite/20241228173741_Add_LockedOutUsers_Table_Sqlite.cs create mode 100644 BLAZAMDatabase/Models/GenericSidList.cs create mode 100644 BLAZAMEmailMessage/Email/Notifications/LockedOutEmailMessage.razor create mode 100644 BLAZAMServices/Attributes/AutoStartBackgroundService.cs create mode 100644 BLAZAMServices/Background/ActiveDirectoryBackgroundServiceBase.cs create mode 100644 BLAZAMServices/Background/BackgroundServiceBase.cs create mode 100644 BLAZAMServices/Background/LockedOutUserMonitor.cs rename BLAZAMServices/{ => Exceptions}/MFARequestedException.cs (96%) diff --git a/BLAZAM/BLAZAM.csproj b/BLAZAM/BLAZAM.csproj index 0b096971f..bb7f378d6 100644 --- a/BLAZAM/BLAZAM.csproj +++ b/BLAZAM/BLAZAM.csproj @@ -6,7 +6,7 @@ enable false 1.2.4 - 2024.12.27.1637 + 2024.12.28.2159 false BLAZAM True diff --git a/BLAZAM/ProgramHelpers.cs b/BLAZAM/ProgramHelpers.cs index f847b5339..923501e1f 100644 --- a/BLAZAM/ProgramHelpers.cs +++ b/BLAZAM/ProgramHelpers.cs @@ -31,6 +31,7 @@ using System.Reflection; using System.Text; using Polly.Contrib.WaitAndRetry; +using BLAZAM.Services.Attributes; namespace BLAZAM.Server { @@ -176,12 +177,12 @@ public static WebApplicationBuilder InjectServices(this WebApplicationBuilder bu options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, // Important: Validate the signing key - IssuerSigningKey = new SymmetricSecurityKey (Encryption.Instance.Key), + IssuerSigningKey = new SymmetricSecurityKey(Encryption.Instance.Key), ValidateIssuer = false, ValidateAudience = false, ValidateActor = false, ValidateLifetime = true, - + }; options.Events = new JwtAuthenticationEventsHandler( builder.Services.BuildServiceProvider().GetRequiredService(), @@ -243,7 +244,7 @@ public static WebApplicationBuilder InjectServices(this WebApplicationBuilder bu ServerCertificateCustomValidationCallback = (m, c, ch, e) => true }); - + //Provide a way to get the current HTTP userPrincipal as a service builder.Services.AddHttpContextAccessor(); @@ -316,7 +317,7 @@ public static WebApplicationBuilder InjectServices(this WebApplicationBuilder bu //Provide notification publishing as a service builder.Services.AddSingleton(); - + builder.InjectBackgroundServices(); builder.Services.AddSessionServices(); @@ -352,48 +353,48 @@ public static WebApplicationBuilder InjectServices(this WebApplicationBuilder bu builder.Services.AddSwaggerGen(c => { - c.SwaggerDoc("v1", new OpenApiInfo - { - Title = "Blazam API", - Version = "v1", - Description = "The official Blazam API documentation." + - "
Authorization is required for API access." + - "
The \"Authorization\" header value must be \"Bearer {token}\"", - License = new OpenApiLicense() { Name = "MIT License", Url = new Uri("https://github.com/Blazam-App/BLAZAM/blob/v1-Dev/LICENSE") }, - Contact = new() + c.SwaggerDoc("v1", new OpenApiInfo { - Email = "support@blazam.org", - Name = "Blazam Support", - Url = new("https://blazam.org/support") - }, - TermsOfService = new Uri("https://blazam.org/tos") - }); + Title = "Blazam API", + Version = "v1", + Description = "The official Blazam API documentation." + + "
Authorization is required for API access." + + "
The \"Authorization\" header value must be \"Bearer {token}\"", + License = new OpenApiLicense() { Name = "MIT License", Url = new Uri("https://github.com/Blazam-App/BLAZAM/blob/v1-Dev/LICENSE") }, + Contact = new() + { + Email = "support@blazam.org", + Name = "Blazam Support", + Url = new("https://blazam.org/support") + }, + TermsOfService = new Uri("https://blazam.org/tos") + }); - // Add descriptions using XML comments - var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; - c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename)); + // Add descriptions using XML comments + var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; + c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename)); - // Configure Swagger to use JWT Bearer authorization - var jwtSecurityScheme = new OpenApiSecurityScheme - { - Description = "Enter only the token supplied by Blazam", - Name = "Authorization", - In = ParameterLocation.Header, - Type = SecuritySchemeType.Http, - Scheme = JwtBearerDefaults.AuthenticationScheme, - BearerFormat = "JWT", - Reference = new OpenApiReference + // Configure Swagger to use JWT Bearer authorization + var jwtSecurityScheme = new OpenApiSecurityScheme { - Id = JwtBearerDefaults.AuthenticationScheme, - Type = ReferenceType.SecurityScheme - } - }; + Description = "Enter only the token supplied by Blazam", + Name = "Authorization", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + Scheme = JwtBearerDefaults.AuthenticationScheme, + BearerFormat = "JWT", + Reference = new OpenApiReference + { + Id = JwtBearerDefaults.AuthenticationScheme, + Type = ReferenceType.SecurityScheme + } + }; c.AddSecurityDefinition(jwtSecurityScheme.Reference.Id, jwtSecurityScheme); - c.AddSecurityRequirement(new OpenApiSecurityRequirement() { + c.AddSecurityRequirement(new OpenApiSecurityRequirement() { { jwtSecurityScheme,Array.Empty() } }); - }); + }); builder.Host.UseWindowsService(); @@ -401,85 +402,144 @@ public static WebApplicationBuilder InjectServices(this WebApplicationBuilder bu return builder; } - - public static void PreRun(this WebApplication application) - { - //Setup Seq logging if allowed by admin - try + private static readonly object _lock = new object(); + public static WebApplicationBuilder InjectBackgroundServices(this WebApplicationBuilder builder) { - using var context = Program.AppInstance.Services.GetRequiredService().CreateDbContext(); - if (context != null && context.AppSettings.FirstOrDefault()?.SendLogsToDeveloper != null) + + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + Parallel.ForEach(assemblies, assembly => { - Loggers.SendToSeqServer = context.AppSettings.FirstOrDefault().SendLogsToDeveloper; + var types = assembly.GetTypes() + .Where(t => t.IsClass && !t.IsAbstract && t.GetCustomAttribute() != null); - } + foreach (var type in types) + { + lock (_lock) + { + builder.Services.AddSingleton(type); + } + } + }); - } - catch (Exception ex) - { - Loggers.SystemLogger.Error(ex.Message + " {@Error}", ex); - } - PreloadServices(); - } - static IAsyncPolicy GetWebhookRetryPolicy() - { - var delay = Backoff.DecorrelatedJitterBackoffV2(medianFirstRetryDelay: TimeSpan.FromSeconds(1), retryCount: 5); + //foreach (var assembly in assemblies) + //{ + // var types = assembly.GetTypes() + // .Where(t => t.IsClass && !t.IsAbstract && t.GetCustomAttribute() != null); - return HttpPolicyExtensions - .HandleTransientHttpError() - .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound) - .WaitAndRetryAsync(delay); - } - private static void PreloadServices() - { - try - { - var context = Program.AppInstance.Services.GetRequiredService(); - } - catch (Exception ex) - { - Loggers.SystemLogger.Error(ex.Message + " {@Error}", ex); + // foreach (var type in types) + // { + // builder.Services.AddSingleton(type); + // } + //} + return builder; } - try + + public static void PreRun(this WebApplication application) { - if (ApplicationInfo.installationCompleted) + try { - var context = Program.AppInstance.Services.GetRequiredService(); + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + + foreach (var assembly in assemblies) + { + var types = assembly.GetTypes() + .Where(t => t.IsClass && !t.IsAbstract && t.GetCustomAttribute() != null); + + foreach (var type in types) + { + var service = application.Services.GetRequiredService(type) as BackgroundServiceBase; + try + { + service.Start(); + } + catch + { + + } + } + } } + catch + { - } - catch (Exception ex) - { - Loggers.SystemLogger.Error(ex.Message + " {@Error}", ex); - } - try - { - if (ApplicationInfo.installationCompleted) + } + //Setup Seq logging if allowed by admin + try { - var context = Program.AppInstance.Services.GetRequiredService(); - context.Initialize(); + using var context = Program.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); } + PreloadServices(); } - catch (Exception ex) + static IAsyncPolicy GetWebhookRetryPolicy() { - Loggers.SystemLogger.Error(ex.Message + " {@Error}", ex); + var delay = Backoff.DecorrelatedJitterBackoffV2(medianFirstRetryDelay: TimeSpan.FromSeconds(1), retryCount: 5); + + return HttpPolicyExtensions + .HandleTransientHttpError() + .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound) + .WaitAndRetryAsync(delay); } - try + private static void PreloadServices() { - if (ApplicationInfo.installationCompleted) + try { - var context = Program.AppInstance.Services.GetRequiredService(); + var context = Program.AppInstance.Services.GetRequiredService(); + } + catch (Exception ex) + { + Loggers.SystemLogger.Error(ex.Message + " {@Error}", ex); + } + try + { + if (ApplicationInfo.installationCompleted) + { + var context = Program.AppInstance.Services.GetRequiredService(); + } } + catch (Exception ex) + { + Loggers.SystemLogger.Error(ex.Message + " {@Error}", ex); + } + try + { + if (ApplicationInfo.installationCompleted) + { + var context = Program.AppInstance.Services.GetRequiredService(); + context.Initialize(); + } - } - catch (Exception ex) - { - Loggers.SystemLogger.Error(ex.Message + " {@Error}", ex); - } + } + catch (Exception ex) + { + Loggers.SystemLogger.Error(ex.Message + " {@Error}", ex); + } + try + { + if (ApplicationInfo.installationCompleted) + { + var context = Program.AppInstance.Services.GetRequiredService(); + + } + + } + catch (Exception ex) + { + Loggers.SystemLogger.Error(ex.Message + " {@Error}", ex); + } + } } } -} diff --git a/BLAZAMDatabase/Context/DatabaseContextBase.cs b/BLAZAMDatabase/Context/DatabaseContextBase.cs index 9a4acebb5..04450e7fa 100644 --- a/BLAZAMDatabase/Context/DatabaseContextBase.cs +++ b/BLAZAMDatabase/Context/DatabaseContextBase.cs @@ -107,6 +107,9 @@ public DatabaseContextBase(DbContextOptions options) : base(options) } + //Data tables + public virtual DbSet LockedOutUsers { get; set; } + //App Settings public virtual DbSet AppSettings { get; set; } public virtual DbSet ActiveDirectorySettings { get; set; } diff --git a/BLAZAMDatabase/Context/IDatabaseContext.cs b/BLAZAMDatabase/Context/IDatabaseContext.cs index d27dfd0ba..13d1f803b 100644 --- a/BLAZAMDatabase/Context/IDatabaseContext.cs +++ b/BLAZAMDatabase/Context/IDatabaseContext.cs @@ -70,6 +70,7 @@ public interface IDatabaseContext : IEFCoreDbContext DbSet ApiTokens { get; set; } DbSet WebHookSubscriptions { get; set; } DbSet WebHookAttempts { get; set; } + DbSet LockedOutUsers { get; set; } void Export(string directory); } diff --git a/BLAZAMDatabase/Migrations/MySql/20241228173828_Add_LockedOutUsers_Table_MySql.Designer.cs b/BLAZAMDatabase/Migrations/MySql/20241228173828_Add_LockedOutUsers_Table_MySql.Designer.cs new file mode 100644 index 000000000..8be68d437 --- /dev/null +++ b/BLAZAMDatabase/Migrations/MySql/20241228173828_Add_LockedOutUsers_Table_MySql.Designer.cs @@ -0,0 +1,2270 @@ +// +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.MySql +{ + [DbContext(typeof(MySqlDatabaseContext))] + [Migration("20241228173828_Add_LockedOutUsers_Table_MySql")] + partial class Add_LockedOutUsers_Table_MySql + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(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("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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FieldName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FieldType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("ActiveDirectoryFields"); + + b.HasData( + new + { + Id = 1, + DisplayName = "Last Name", + FieldName = "sn", + FieldType = 0 + }, + new + { + Id = 2, + DisplayName = "First Name", + FieldName = "givenname", + FieldType = 0 + }, + new + { + Id = 3, + DisplayName = "Office", + FieldName = "physicalDeliveryOfficeName", + FieldType = 0 + }, + new + { + Id = 4, + DisplayName = "Employee ID", + FieldName = "employeeId", + FieldType = 0 + }, + new + { + Id = 5, + DisplayName = "Home Directory", + FieldName = "homeDirectory", + FieldType = 0 + }, + new + { + Id = 6, + DisplayName = "Logon Script Path", + FieldName = "scriptPath", + FieldType = 0 + }, + new + { + Id = 7, + DisplayName = "Profile Path", + FieldName = "profilePath", + FieldType = 0 + }, + new + { + Id = 8, + DisplayName = "Home Phone Number", + FieldName = "homePhone", + FieldType = 0 + }, + new + { + Id = 9, + DisplayName = "Street Address", + FieldName = "streetAddress", + FieldType = 0 + }, + new + { + Id = 10, + DisplayName = "City", + FieldName = "l", + FieldType = 0 + }, + new + { + Id = 11, + DisplayName = "State", + FieldName = "st", + FieldType = 0 + }, + new + { + Id = 12, + DisplayName = "Zip Code", + FieldName = "postalCode", + FieldType = 0 + }, + new + { + Id = 13, + DisplayName = "Site", + FieldName = "site", + FieldType = 0 + }, + new + { + Id = 14, + DisplayName = "Name", + FieldName = "name", + FieldType = 0 + }, + new + { + Id = 15, + DisplayName = "Username", + FieldName = "samaccountname", + FieldType = 0 + }, + new + { + Id = 16, + DisplayName = "SID", + FieldName = "objectSID", + FieldType = 2 + }, + new + { + Id = 17, + DisplayName = "E-Mail Address", + FieldName = "mail", + FieldType = 0 + }, + new + { + Id = 18, + DisplayName = "Description", + FieldName = "description", + FieldType = 0 + }, + new + { + Id = 19, + DisplayName = "Display Name", + FieldName = "displayName", + FieldType = 0 + }, + new + { + Id = 20, + DisplayName = "Distinguished Name", + FieldName = "distinguishedName", + FieldType = 0 + }, + new + { + Id = 21, + DisplayName = "Member Of", + FieldName = "memberOf", + FieldType = 4 + }, + new + { + Id = 22, + DisplayName = "Company", + FieldName = "company", + FieldType = 0 + }, + new + { + Id = 23, + DisplayName = "Title", + FieldName = "title", + FieldType = 0 + }, + new + { + Id = 24, + DisplayName = "User Principal Name", + FieldName = "userPrincipalName", + FieldType = 0 + }, + new + { + Id = 25, + DisplayName = "Telephone Number", + FieldName = "telephoneNumber", + FieldType = 0 + }, + new + { + Id = 26, + DisplayName = "PO Box", + FieldName = "postOfficeBox", + FieldType = 0 + }, + new + { + Id = 27, + DisplayName = "Canonical Name", + FieldName = "cn", + FieldType = 0 + }, + new + { + Id = 28, + DisplayName = "Home Drive", + FieldName = "homeDrive", + FieldType = 3 + }, + new + { + Id = 29, + DisplayName = "Department", + FieldName = "department", + FieldType = 0 + }, + new + { + Id = 30, + DisplayName = "Middle Name", + FieldName = "middleName", + FieldType = 0 + }, + new + { + Id = 31, + DisplayName = "Pager", + FieldName = "pager", + FieldType = 0 + }, + new + { + Id = 32, + DisplayName = "OS", + FieldName = "operatingSystemVersion", + FieldType = 0 + }, + new + { + Id = 33, + DisplayName = "Account Expiration", + FieldName = "accountExpires", + FieldType = 1 + }, + new + { + Id = 34, + DisplayName = "Manager", + FieldName = "manager", + FieldType = 0 + }, + new + { + Id = 35, + DisplayName = "Photo", + FieldName = "thumbnail", + FieldType = 2 + }, + new + { + Id = 36, + DisplayName = "Log On To", + FieldName = "userWorkstations", + FieldType = 0 + }, + new + { + Id = 37, + DisplayName = "Logon Hours", + FieldName = "logonHours", + FieldType = 2 + }); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.ActiveDirectoryFieldObjectType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(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("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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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("RequireMFA") + .HasColumnType("tinyint(1)"); + + 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, + RequireMFA = false, + SessionTimeout = 15 + }); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Chat.ChatRoom", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Body") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TemplateType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("EmailTemplates"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.GenericSidList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Added") + .HasColumnType("datetime(6)"); + + b.Property("Sid") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("LockedOutUsers"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.NotificationSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Block") + .HasColumnType("tinyint(1)"); + + b.Property("ByEmail") + .HasColumnType("tinyint(1)"); + + b.Property("DeletedAt") + .HasColumnType("datetime(6)"); + + b.Property("InApp") + .HasColumnType("tinyint(1)"); + + b.Property("OU") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationSubscriptions"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.SubscriptionNotificationType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("NotificationSubscriptionId") + .HasColumnType("int"); + + b.Property("NotificationType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NotificationSubscriptionId"); + + b.ToTable("SubscriptionNotificationType"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.SubscriptionWebHookType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("NotificationType") + .HasColumnType("int"); + + b.Property("WebHookSubscriptionId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("WebHookSubscriptionId"); + + b.ToTable("SubscriptionWebHookType"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.WebHookAttempt", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Body") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Delivered") + .HasColumnType("tinyint(1)"); + + b.Property("EventTimestamp") + .HasColumnType("datetime(6)"); + + b.Property("EventType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LastAttemptTimestamp") + .HasColumnType("datetime(6)"); + + b.Property("MessageGuid") + .HasColumnType("char(36)"); + + b.Property("ResponseCode") + .HasColumnType("int"); + + b.Property("ResponseHeaders") + .HasColumnType("longtext"); + + b.Property("ResponseMessage") + .HasColumnType("longtext"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.Property("Signature") + .HasColumnType("longtext"); + + b.Property("Uri") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("WebHookSubscriptionId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("WebHookSubscriptionId"); + + b.ToTable("WebHookAttempts"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.WebHookSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("AuthorizationToken") + .HasColumnType("longtext"); + + b.Property("DeletedAt") + .HasColumnType("datetime(6)"); + + b.Property("HmacKey") + .HasColumnType("longtext"); + + b.Property("IgnoreSSLVerification") + .HasColumnType("tinyint(1)"); + + b.Property("OU") + .HasColumnType("longtext"); + + b.Property("PrivateKey") + .HasColumnType("longtext"); + + b.Property("PublicKey") + .HasColumnType("longtext"); + + b.Property("URL") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("WebHookAuthorization") + .HasColumnType("int"); + + b.Property("WebHookMethod") + .HasColumnType("int"); + + b.Property("WebHookSignature") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("WebHookSubscriptions"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Permissions.AccessLevel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(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.GlobalPermissionRequestActions", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ObjectAction") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("GlobalPermissionRequestActions"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Permissions.GlobalPermissionSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("AllowAccessRequest") + .HasColumnType("tinyint(1)"); + + b.Property("AllowSelfModification") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("GlobalPermissionSettings"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Permissions.ObjectAccessLevel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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" + }, + new + { + Id = 10, + Action = 9, + Name = "Set Password" + }); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Permissions.PermissionDelegate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("DelegateName") + .HasColumnType("longtext"); + + b.Property("DelegateSid") + .IsRequired() + .HasColumnType("varbinary(3072)"); + + b.Property("DeletedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsSuperAdmin") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("DelegateSid") + .IsUnique(); + + b.ToTable("PermissionDelegate"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Permissions.PermissionMapping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("AllowCustomGroups") + .HasColumnType("tinyint(1)"); + + b.Property("AllowUsernameOverride") + .HasColumnType("tinyint(1)"); + + b.Property("AskForAlternateEmail") + .HasColumnType("tinyint(1)"); + + b.Property("Category") + .HasColumnType("longtext"); + + b.Property("DeletedAt") + .HasColumnType("datetime(6)"); + + b.Property("DisplayNameFormula") + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("ObjectType") + .HasColumnType("int"); + + b.Property("ParentOU") + .HasColumnType("longtext"); + + b.Property("ParentTemplateId") + .HasColumnType("int"); + + b.Property("PasswordFormula") + .HasColumnType("longtext"); + + b.Property("RequirePasswordChange") + .HasColumnType("tinyint(1)"); + + b.Property("SendWelcomeEmail") + .HasColumnType("tinyint(1)"); + + b.Property("UsernameFormula") + .HasColumnType("longtext"); + + b.Property("Visible") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("ParentTemplateId"); + + b.ToTable("DirectoryTemplates"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Templates.DirectoryTemplateFieldValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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.ApiToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DeletedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ExpiresAt") + .HasColumnType("datetime(6)"); + + b.Property("IsRevoked") + .HasColumnType("tinyint(1)"); + + b.Property("LastUsedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TokenHash") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("ApiTokens"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.AppUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("AuthenticatorSecret") + .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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("int"); + + b.Property("Created") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("int"); + + 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("MessageType") + .HasColumnType("int"); + + b.Property("TargetDN") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("CreatorId"); + + b.ToTable("NotificationMessages"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.ReadNewsItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ItemsPerPage") + .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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + 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.Notifications.NotificationSubscription", b => + { + b.HasOne("BLAZAM.Database.Models.User.AppUser", "User") + .WithMany("NotificationSubscriptions") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.SubscriptionNotificationType", b => + { + b.HasOne("BLAZAM.Database.Models.Notifications.NotificationSubscription", "NotificationSubscription") + .WithMany("NotificationTypes") + .HasForeignKey("NotificationSubscriptionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NotificationSubscription"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.SubscriptionWebHookType", b => + { + b.HasOne("BLAZAM.Database.Models.Notifications.WebHookSubscription", "WebHookSubscription") + .WithMany("NotificationTypes") + .HasForeignKey("WebHookSubscriptionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("WebHookSubscription"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.WebHookAttempt", b => + { + b.HasOne("BLAZAM.Database.Models.Notifications.WebHookSubscription", "WebHookSubscription") + .WithMany("WebHookAttempts") + .HasForeignKey("WebHookSubscriptionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("WebHookSubscription"); + }); + + 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.ApiToken", b => + { + b.HasOne("BLAZAM.Database.Models.User.AppUser", "User") + .WithMany("APITokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.NotificationMessage", b => + { + b.HasOne("BLAZAM.Database.Models.User.AppUser", "Creator") + .WithMany() + .HasForeignKey("CreatorId"); + + b.Navigation("Creator"); + }); + + 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("Notifications") + .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.Notifications.NotificationSubscription", b => + { + b.Navigation("NotificationTypes"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.WebHookSubscription", b => + { + b.Navigation("NotificationTypes"); + + b.Navigation("WebHookAttempts"); + }); + + 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("APITokens"); + + b.Navigation("DashboardWidgets"); + + b.Navigation("FavoriteEntries"); + + b.Navigation("NotificationSubscriptions"); + + b.Navigation("Notifications"); + + b.Navigation("ReadNewsItems"); + }); + + modelBuilder.Entity("BLAZAM.Server.Data.ChatMessage", b => + { + b.Navigation("NotReadBy"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/BLAZAMDatabase/Migrations/MySql/20241228173828_Add_LockedOutUsers_Table_MySql.cs b/BLAZAMDatabase/Migrations/MySql/20241228173828_Add_LockedOutUsers_Table_MySql.cs new file mode 100644 index 000000000..914a3a200 --- /dev/null +++ b/BLAZAMDatabase/Migrations/MySql/20241228173828_Add_LockedOutUsers_Table_MySql.cs @@ -0,0 +1,39 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BLAZAM.Database.Migrations.MySql +{ + /// + public partial class Add_LockedOutUsers_Table_MySql : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "LockedOutUsers", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Sid = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Added = table.Column(type: "datetime(6)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_LockedOutUsers", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "LockedOutUsers"); + } + } +} diff --git a/BLAZAMDatabase/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs b/BLAZAMDatabase/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs index a55451d39..c593ff820 100644 --- a/BLAZAMDatabase/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs +++ b/BLAZAMDatabase/Migrations/MySql/MySqlDatabaseContextModelSnapshot.cs @@ -931,6 +931,26 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("EmailTemplates"); }); + modelBuilder.Entity("BLAZAM.Database.Models.GenericSidList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Added") + .HasColumnType("datetime(6)"); + + b.Property("Sid") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("LockedOutUsers"); + }); + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.NotificationSubscription", b => { b.Property("Id") diff --git a/BLAZAMDatabase/Migrations/Sql/20241228173806_Add_LockedOutUsers_Table_Sql.Designer.cs b/BLAZAMDatabase/Migrations/Sql/20241228173806_Add_LockedOutUsers_Table_Sql.Designer.cs new file mode 100644 index 000000000..6d6857faa --- /dev/null +++ b/BLAZAMDatabase/Migrations/Sql/20241228173806_Add_LockedOutUsers_Table_Sql.Designer.cs @@ -0,0 +1,2270 @@ +// +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("20241228173806_Add_LockedOutUsers_Table_Sql")] + partial class Add_LockedOutUsers_Table_Sql + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.11") + .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 + }, + new + { + Id = 36, + DisplayName = "Log On To", + FieldName = "userWorkstations", + FieldType = 0 + }, + new + { + Id = 37, + DisplayName = "Logon Hours", + FieldName = "logonHours", + FieldType = 2 + }); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.ActiveDirectoryFieldObjectType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + 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("RequireMFA") + .HasColumnType("bit"); + + 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, + RequireMFA = false, + 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("Body") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TemplateType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("EmailTemplates"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.GenericSidList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Added") + .HasColumnType("datetime2"); + + b.Property("Sid") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("LockedOutUsers"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.NotificationSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Block") + .HasColumnType("bit"); + + b.Property("ByEmail") + .HasColumnType("bit"); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("InApp") + .HasColumnType("bit"); + + b.Property("OU") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationSubscriptions"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.SubscriptionNotificationType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("NotificationSubscriptionId") + .HasColumnType("int"); + + b.Property("NotificationType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NotificationSubscriptionId"); + + b.ToTable("SubscriptionNotificationType"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.SubscriptionWebHookType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("NotificationType") + .HasColumnType("int"); + + b.Property("WebHookSubscriptionId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("WebHookSubscriptionId"); + + b.ToTable("SubscriptionWebHookType"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.WebHookAttempt", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Body") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Delivered") + .HasColumnType("bit"); + + b.Property("EventTimestamp") + .HasColumnType("datetime2"); + + b.Property("EventType") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastAttemptTimestamp") + .HasColumnType("datetime2"); + + b.Property("MessageGuid") + .HasColumnType("uniqueidentifier"); + + b.Property("ResponseCode") + .HasColumnType("int"); + + b.Property("ResponseHeaders") + .HasColumnType("nvarchar(max)"); + + b.Property("ResponseMessage") + .HasColumnType("nvarchar(max)"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.Property("Signature") + .HasColumnType("nvarchar(max)"); + + b.Property("Uri") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("WebHookSubscriptionId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("WebHookSubscriptionId"); + + b.ToTable("WebHookAttempts"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.WebHookSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AuthorizationToken") + .HasColumnType("nvarchar(max)"); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("HmacKey") + .HasColumnType("nvarchar(max)"); + + b.Property("IgnoreSSLVerification") + .HasColumnType("bit"); + + b.Property("OU") + .HasColumnType("nvarchar(max)"); + + b.Property("PrivateKey") + .HasColumnType("nvarchar(max)"); + + b.Property("PublicKey") + .HasColumnType("nvarchar(max)"); + + b.Property("URL") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("WebHookAuthorization") + .HasColumnType("int"); + + b.Property("WebHookMethod") + .HasColumnType("int"); + + b.Property("WebHookSignature") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("WebHookSubscriptions"); + }); + + 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.GlobalPermissionRequestActions", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ObjectAction") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("GlobalPermissionRequestActions"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Permissions.GlobalPermissionSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AllowAccessRequest") + .HasColumnType("bit"); + + b.Property("AllowSelfModification") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.ToTable("GlobalPermissionSettings"); + }); + + 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" + }, + new + { + Id = 10, + Action = 9, + Name = "Set Password" + }); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Permissions.PermissionDelegate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DelegateName") + .HasColumnType("nvarchar(max)"); + + 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("AllowUsernameOverride") + .HasColumnType("bit"); + + b.Property("AskForAlternateEmail") + .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("SendWelcomeEmail") + .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.ApiToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("ExpiresAt") + .HasColumnType("datetime2"); + + b.Property("IsRevoked") + .HasColumnType("bit"); + + b.Property("LastUsedAt") + .HasColumnType("datetime2"); + + b.Property("Token") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TokenHash") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("ApiTokens"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.AppUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AuthenticatorSecret") + .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("Action") + .HasColumnType("int"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatorId") + .HasColumnType("int"); + + 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("MessageType") + .HasColumnType("int"); + + b.Property("TargetDN") + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("CreatorId"); + + 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("ItemsPerPage") + .HasColumnType("int"); + + 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.Notifications.NotificationSubscription", b => + { + b.HasOne("BLAZAM.Database.Models.User.AppUser", "User") + .WithMany("NotificationSubscriptions") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.SubscriptionNotificationType", b => + { + b.HasOne("BLAZAM.Database.Models.Notifications.NotificationSubscription", "NotificationSubscription") + .WithMany("NotificationTypes") + .HasForeignKey("NotificationSubscriptionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NotificationSubscription"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.SubscriptionWebHookType", b => + { + b.HasOne("BLAZAM.Database.Models.Notifications.WebHookSubscription", "WebHookSubscription") + .WithMany("NotificationTypes") + .HasForeignKey("WebHookSubscriptionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("WebHookSubscription"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.WebHookAttempt", b => + { + b.HasOne("BLAZAM.Database.Models.Notifications.WebHookSubscription", "WebHookSubscription") + .WithMany("WebHookAttempts") + .HasForeignKey("WebHookSubscriptionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("WebHookSubscription"); + }); + + 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.ApiToken", b => + { + b.HasOne("BLAZAM.Database.Models.User.AppUser", "User") + .WithMany("APITokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.NotificationMessage", b => + { + b.HasOne("BLAZAM.Database.Models.User.AppUser", "Creator") + .WithMany() + .HasForeignKey("CreatorId"); + + b.Navigation("Creator"); + }); + + 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("Notifications") + .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.Notifications.NotificationSubscription", b => + { + b.Navigation("NotificationTypes"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.WebHookSubscription", b => + { + b.Navigation("NotificationTypes"); + + b.Navigation("WebHookAttempts"); + }); + + 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("APITokens"); + + b.Navigation("DashboardWidgets"); + + b.Navigation("FavoriteEntries"); + + b.Navigation("NotificationSubscriptions"); + + b.Navigation("Notifications"); + + b.Navigation("ReadNewsItems"); + }); + + modelBuilder.Entity("BLAZAM.Server.Data.ChatMessage", b => + { + b.Navigation("NotReadBy"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/BLAZAMDatabase/Migrations/Sql/20241228173806_Add_LockedOutUsers_Table_Sql.cs b/BLAZAMDatabase/Migrations/Sql/20241228173806_Add_LockedOutUsers_Table_Sql.cs new file mode 100644 index 000000000..4422899c9 --- /dev/null +++ b/BLAZAMDatabase/Migrations/Sql/20241228173806_Add_LockedOutUsers_Table_Sql.cs @@ -0,0 +1,36 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BLAZAM.Database.Migrations.Sql +{ + /// + public partial class Add_LockedOutUsers_Table_Sql : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "LockedOutUsers", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Sid = table.Column(type: "nvarchar(max)", nullable: false), + Added = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_LockedOutUsers", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "LockedOutUsers"); + } + } +} diff --git a/BLAZAMDatabase/Migrations/Sql/SqlDatabaseContextModelSnapshot.cs b/BLAZAMDatabase/Migrations/Sql/SqlDatabaseContextModelSnapshot.cs index bae38c700..4daff578f 100644 --- a/BLAZAMDatabase/Migrations/Sql/SqlDatabaseContextModelSnapshot.cs +++ b/BLAZAMDatabase/Migrations/Sql/SqlDatabaseContextModelSnapshot.cs @@ -931,6 +931,26 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("EmailTemplates"); }); + modelBuilder.Entity("BLAZAM.Database.Models.GenericSidList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Added") + .HasColumnType("datetime2"); + + b.Property("Sid") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("LockedOutUsers"); + }); + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.NotificationSubscription", b => { b.Property("Id") diff --git a/BLAZAMDatabase/Migrations/Sqlite/20241228173741_Add_LockedOutUsers_Table_Sqlite.Designer.cs b/BLAZAMDatabase/Migrations/Sqlite/20241228173741_Add_LockedOutUsers_Table_Sqlite.Designer.cs new file mode 100644 index 000000000..af7f1a8c1 --- /dev/null +++ b/BLAZAMDatabase/Migrations/Sqlite/20241228173741_Add_LockedOutUsers_Table_Sqlite.Designer.cs @@ -0,0 +1,2182 @@ +// +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("20241228173741_Add_LockedOutUsers_Table_Sqlite")] + partial class Add_LockedOutUsers_Table_Sqlite + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.11"); + + 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 + }, + new + { + Id = 36, + DisplayName = "Log On To", + FieldName = "userWorkstations", + FieldType = 0 + }, + new + { + Id = 37, + DisplayName = "Logon Hours", + FieldName = "logonHours", + FieldType = 2 + }); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.ActiveDirectoryFieldObjectType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("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("RequireMFA") + .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, + RequireMFA = false, + 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("Body") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TemplateType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("EmailTemplates"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.GenericSidList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Added") + .HasColumnType("TEXT"); + + b.Property("Sid") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("LockedOutUsers"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.NotificationSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Block") + .HasColumnType("INTEGER"); + + b.Property("ByEmail") + .HasColumnType("INTEGER"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("InApp") + .HasColumnType("INTEGER"); + + b.Property("OU") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationSubscriptions"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.SubscriptionNotificationType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("NotificationSubscriptionId") + .HasColumnType("INTEGER"); + + b.Property("NotificationType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NotificationSubscriptionId"); + + b.ToTable("SubscriptionNotificationType"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.SubscriptionWebHookType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("NotificationType") + .HasColumnType("INTEGER"); + + b.Property("WebHookSubscriptionId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("WebHookSubscriptionId"); + + b.ToTable("SubscriptionWebHookType"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.WebHookAttempt", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Body") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Delivered") + .HasColumnType("INTEGER"); + + b.Property("EventTimestamp") + .HasColumnType("TEXT"); + + b.Property("EventType") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("LastAttemptTimestamp") + .HasColumnType("TEXT"); + + b.Property("MessageGuid") + .HasColumnType("TEXT"); + + b.Property("ResponseCode") + .HasColumnType("INTEGER"); + + b.Property("ResponseHeaders") + .HasColumnType("TEXT"); + + b.Property("ResponseMessage") + .HasColumnType("TEXT"); + + b.Property("RetryCount") + .HasColumnType("INTEGER"); + + b.Property("Signature") + .HasColumnType("TEXT"); + + b.Property("Uri") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WebHookSubscriptionId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("WebHookSubscriptionId"); + + b.ToTable("WebHookAttempts"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.WebHookSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuthorizationToken") + .HasColumnType("TEXT"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("HmacKey") + .HasColumnType("TEXT"); + + b.Property("IgnoreSSLVerification") + .HasColumnType("INTEGER"); + + b.Property("OU") + .HasColumnType("TEXT"); + + b.Property("PrivateKey") + .HasColumnType("TEXT"); + + b.Property("PublicKey") + .HasColumnType("TEXT"); + + b.Property("URL") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("WebHookAuthorization") + .HasColumnType("INTEGER"); + + b.Property("WebHookMethod") + .HasColumnType("INTEGER"); + + b.Property("WebHookSignature") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("WebHookSubscriptions"); + }); + + 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.GlobalPermissionRequestActions", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ObjectAction") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("GlobalPermissionRequestActions"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Permissions.GlobalPermissionSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AllowAccessRequest") + .HasColumnType("INTEGER"); + + b.Property("AllowSelfModification") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("GlobalPermissionSettings"); + }); + + 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" + }, + new + { + Id = 10, + Action = 9, + Name = "Set Password" + }); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Permissions.PermissionDelegate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DelegateName") + .HasColumnType("TEXT"); + + 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("AllowUsernameOverride") + .HasColumnType("INTEGER"); + + b.Property("AskForAlternateEmail") + .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("SendWelcomeEmail") + .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.ApiToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("ExpiresAt") + .HasColumnType("TEXT"); + + b.Property("IsRevoked") + .HasColumnType("INTEGER"); + + b.Property("LastUsedAt") + .HasColumnType("TEXT"); + + b.Property("Token") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TokenHash") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("ApiTokens"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.AppUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuthenticatorSecret") + .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("Action") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("CreatorId") + .HasColumnType("INTEGER"); + + 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("MessageType") + .HasColumnType("INTEGER"); + + b.Property("TargetDN") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatorId"); + + 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("ItemsPerPage") + .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.Notifications.NotificationSubscription", b => + { + b.HasOne("BLAZAM.Database.Models.User.AppUser", "User") + .WithMany("NotificationSubscriptions") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.SubscriptionNotificationType", b => + { + b.HasOne("BLAZAM.Database.Models.Notifications.NotificationSubscription", "NotificationSubscription") + .WithMany("NotificationTypes") + .HasForeignKey("NotificationSubscriptionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NotificationSubscription"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.SubscriptionWebHookType", b => + { + b.HasOne("BLAZAM.Database.Models.Notifications.WebHookSubscription", "WebHookSubscription") + .WithMany("NotificationTypes") + .HasForeignKey("WebHookSubscriptionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("WebHookSubscription"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.WebHookAttempt", b => + { + b.HasOne("BLAZAM.Database.Models.Notifications.WebHookSubscription", "WebHookSubscription") + .WithMany("WebHookAttempts") + .HasForeignKey("WebHookSubscriptionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("WebHookSubscription"); + }); + + 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.ApiToken", b => + { + b.HasOne("BLAZAM.Database.Models.User.AppUser", "User") + .WithMany("APITokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.User.NotificationMessage", b => + { + b.HasOne("BLAZAM.Database.Models.User.AppUser", "Creator") + .WithMany() + .HasForeignKey("CreatorId"); + + b.Navigation("Creator"); + }); + + 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("Notifications") + .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.Notifications.NotificationSubscription", b => + { + b.Navigation("NotificationTypes"); + }); + + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.WebHookSubscription", b => + { + b.Navigation("NotificationTypes"); + + b.Navigation("WebHookAttempts"); + }); + + 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("APITokens"); + + b.Navigation("DashboardWidgets"); + + b.Navigation("FavoriteEntries"); + + b.Navigation("NotificationSubscriptions"); + + b.Navigation("Notifications"); + + b.Navigation("ReadNewsItems"); + }); + + modelBuilder.Entity("BLAZAM.Server.Data.ChatMessage", b => + { + b.Navigation("NotReadBy"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/BLAZAMDatabase/Migrations/Sqlite/20241228173741_Add_LockedOutUsers_Table_Sqlite.cs b/BLAZAMDatabase/Migrations/Sqlite/20241228173741_Add_LockedOutUsers_Table_Sqlite.cs new file mode 100644 index 000000000..e700f92b2 --- /dev/null +++ b/BLAZAMDatabase/Migrations/Sqlite/20241228173741_Add_LockedOutUsers_Table_Sqlite.cs @@ -0,0 +1,36 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BLAZAM.Database.Migrations.Sqlite +{ + /// + public partial class Add_LockedOutUsers_Table_Sqlite : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "LockedOutUsers", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Sid = table.Column(type: "TEXT", nullable: false), + Added = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_LockedOutUsers", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "LockedOutUsers"); + } + } +} diff --git a/BLAZAMDatabase/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs b/BLAZAMDatabase/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs index fd48767f3..67c24bb92 100644 --- a/BLAZAMDatabase/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs +++ b/BLAZAMDatabase/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs @@ -899,6 +899,24 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("EmailTemplates"); }); + modelBuilder.Entity("BLAZAM.Database.Models.GenericSidList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Added") + .HasColumnType("TEXT"); + + b.Property("Sid") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("LockedOutUsers"); + }); + modelBuilder.Entity("BLAZAM.Database.Models.Notifications.NotificationSubscription", b => { b.Property("Id") diff --git a/BLAZAMDatabase/Models/GenericSidList.cs b/BLAZAMDatabase/Models/GenericSidList.cs new file mode 100644 index 000000000..769507977 --- /dev/null +++ b/BLAZAMDatabase/Models/GenericSidList.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BLAZAM.Database.Models +{ + public class GenericSidList:AppDbSetBase + { + public string Sid { get; set; } + public DateTime Added { get; set; } + } +} diff --git a/BLAZAMDatabase/Models/Notifications/NotificationType.cs b/BLAZAMDatabase/Models/Notifications/NotificationType.cs index 243cb70a3..51675165c 100644 --- a/BLAZAMDatabase/Models/Notifications/NotificationType.cs +++ b/BLAZAMDatabase/Models/Notifications/NotificationType.cs @@ -6,6 +6,15 @@ namespace BLAZAM.Database.Models.Notifications { - public enum NotificationType { Create, Delete, Modify, Unassign, Assign, PasswordChange } + public enum NotificationType + { + Create, + Delete, + Modify, + Unassign, + Assign, + PasswordChange, + LockedOut + } } diff --git a/BLAZAMEmailMessage/BLAZAMEmailMessage.csproj b/BLAZAMEmailMessage/BLAZAMEmailMessage.csproj index e672d4fb2..8d33d09bb 100644 --- a/BLAZAMEmailMessage/BLAZAMEmailMessage.csproj +++ b/BLAZAMEmailMessage/BLAZAMEmailMessage.csproj @@ -28,6 +28,9 @@ true + + true + diff --git a/BLAZAMEmailMessage/Email/Notifications/LockedOutEmailMessage.razor b/BLAZAMEmailMessage/Email/Notifications/LockedOutEmailMessage.razor new file mode 100644 index 000000000..0180ecc6c --- /dev/null +++ b/BLAZAMEmailMessage/Email/Notifications/LockedOutEmailMessage.razor @@ -0,0 +1,28 @@ +@using BLAZAM.Helpers +@using System.Security +@inherits NotificationTemplateComponent + + + @AppLocalization["User locked out"] + + + + @EntryName @AppLocalization[" has been locked out"]. +
+ + +
+ + +@code{ + [Parameter] + public string EntryName { get; set; } + + public override string Render() => new ComponentRenderer() + .UseLayout() + .AddServiceProvider(ApplicationInfo.services) + .Set(c => c.EntryName, EntryName).Render(); +} + + + diff --git a/BLAZAMGui/UI/Settings/Notifications/OUNotificationSubscriptions.razor b/BLAZAMGui/UI/Settings/Notifications/OUNotificationSubscriptions.razor index 7a3711b65..580d93084 100644 --- a/BLAZAMGui/UI/Settings/Notifications/OUNotificationSubscriptions.razor +++ b/BLAZAMGui/UI/Settings/Notifications/OUNotificationSubscriptions.razor @@ -11,7 +11,7 @@ - + @AppLocalization["Events"] @@ -133,16 +133,26 @@ + + + + @foreach (var type in Enum.GetValues(typeof(NotificationType))) { + var originalEnum = (NotificationType)type; + if (originalEnum == NotificationType.Unassign || originalEnum == NotificationType.Assign) + { + continue; + } @{ } + Value="@(effectiveInAppSubscription.NotificationTypes.Any(x=>x.NotificationType==originalEnum)==true)" /> @@ -173,9 +183,18 @@ + + + + @foreach (var type in Enum.GetValues(typeof(NotificationType))) { var originalEnum = (NotificationType)type; + if (originalEnum == NotificationType.Unassign || originalEnum == NotificationType.Assign) + { + continue; + } @{ diff --git a/BLAZAMNotifications/Notifications/NotificationTypeExtentions.cs b/BLAZAMNotifications/Notifications/NotificationTypeExtentions.cs index 37939849a..c31ffab10 100644 --- a/BLAZAMNotifications/Notifications/NotificationTypeExtentions.cs +++ b/BLAZAMNotifications/Notifications/NotificationTypeExtentions.cs @@ -27,6 +27,9 @@ public static class NotificationTypeExtentions case NotificationType.Assign: notificationTemplate = new EntryAssignedEmailMessage(); break; + case NotificationType.LockedOut: + notificationTemplate = new LockedOutEmailMessage(); + break; } if (notificationTemplate != null) diff --git a/BLAZAMServices/Attributes/AutoStartBackgroundService.cs b/BLAZAMServices/Attributes/AutoStartBackgroundService.cs new file mode 100644 index 000000000..dbbd3af73 --- /dev/null +++ b/BLAZAMServices/Attributes/AutoStartBackgroundService.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BLAZAM.Services.Attributes +{ + public class AutoStartBackgroundService:System.Attribute + { + public int IntervalInMinutes { get; set; } + + + /// + /// + /// + /// The time in minutes this service should execute + public AutoStartBackgroundService(int interval) + { + IntervalInMinutes = interval; + } + } +} diff --git a/BLAZAMServices/Background/ActiveDirectoryBackgroundServiceBase.cs b/BLAZAMServices/Background/ActiveDirectoryBackgroundServiceBase.cs new file mode 100644 index 000000000..538b5bec1 --- /dev/null +++ b/BLAZAMServices/Background/ActiveDirectoryBackgroundServiceBase.cs @@ -0,0 +1,20 @@ +using BLAZAM.ActiveDirectory.Interfaces; +using BLAZAM.Database.Context; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BLAZAM.Services.Background +{ + public class ActiveDirectoryBackgroundServiceBase:BackgroundServiceBase + { + protected readonly IActiveDirectoryContextFactory activeDirectoryContextFactory; + + public ActiveDirectoryBackgroundServiceBase(IActiveDirectoryContextFactory activeDirectoryContextFactory, IAppDatabaseFactory dbFactory) : base(dbFactory) + { + this.activeDirectoryContextFactory = activeDirectoryContextFactory; + } + } +} diff --git a/BLAZAMServices/Background/BackgroundServiceBase.cs b/BLAZAMServices/Background/BackgroundServiceBase.cs new file mode 100644 index 000000000..d056f2819 --- /dev/null +++ b/BLAZAMServices/Background/BackgroundServiceBase.cs @@ -0,0 +1,55 @@ +using BLAZAM.Database.Context; +using BLAZAM.Services.Attributes; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BLAZAM.Services.Background +{ + public class BackgroundServiceBase : IDisposable + { + protected virtual IAppDatabaseFactory dbFactory { get; } + protected virtual Timer? Timer { get; set; } + protected virtual TimeSpan Interval{ get; set; } = TimeSpan.FromMinutes(10); + protected static bool started { get; set; } + public BackgroundServiceBase(IAppDatabaseFactory dbFactory) + { + this.dbFactory = dbFactory; + + } + public virtual void Start(bool immediate=false) + { + if (!started) + { + int delay=0; + if (!immediate) + { + Random rand = new Random(); + int jitter = rand.Next(-15, 15); + delay = 30 + jitter; + + } + Timer = new Timer(Execute, null, TimeSpan.FromSeconds(delay), Interval); + started = true; + } + } + + public virtual void Stop() + { + Timer?.Dispose(); + started = false; + } + + protected virtual void Execute(object? state=null) + { + throw new NotImplementedException(); + } + + public virtual void Dispose() + { + Timer?.Dispose(); + } + } +} diff --git a/BLAZAMServices/Background/LockedOutUserMonitor.cs b/BLAZAMServices/Background/LockedOutUserMonitor.cs new file mode 100644 index 000000000..9fbe5dbbc --- /dev/null +++ b/BLAZAMServices/Background/LockedOutUserMonitor.cs @@ -0,0 +1,89 @@ +using BLAZAM.ActiveDirectory.Interfaces; +using BLAZAM.Database.Context; +using BLAZAM.Database.Models; +using BLAZAM.Database.Models.Notifications; +using BLAZAM.Helpers; +using BLAZAM.Jobs; +using BLAZAM.Services.Attributes; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BLAZAM.Services.Background +{ + [AutoStartBackgroundService(10)] + internal class LockedOutUserMonitor : ActiveDirectoryBackgroundServiceBase + { + private NotificationGenerationService _notificationGenerationService; + + public LockedOutUserMonitor(NotificationGenerationService notificationGenerationService, IActiveDirectoryContextFactory activeDirectoryContextFactory, IAppDatabaseFactory dbFactory) : base(activeDirectoryContextFactory, dbFactory) + { + _notificationGenerationService = notificationGenerationService; + } + + protected override void Execute(object? state = null) + { + using var context = dbFactory.CreateDbContext(); + using var directory = activeDirectoryContextFactory.CreateActiveDirectoryContext(); + + List usersInTable = new List(); + + List lockedOutUsers = new List(); + Job executeJob = new Job("Monitor Locked Out Users"); + JobStep prepareStep = new JobStep("Prepare data", (state) => + { + usersInTable = context.LockedOutUsers.Take(500).ToList(); + var lockedOutUsers = directory.Users.FindLockedOutUsers(); + return true; + }); + executeJob.AddStep(prepareStep); + JobStep analyzeStep = new JobStep("Analyze data", (state) => + { + foreach (var user in lockedOutUsers) + { + if (user == null) continue; + if (user.LockedOut) + { + if (!usersInTable.Any(x => x.Sid == user.SID.ToSidString())) + { + //add user to lockout table + context.LockedOutUsers.Add(new() { Sid = user.SID.ToSidString(), Added = DateTime.UtcNow }); + + if(user.LockoutTime > DateTime.UtcNow.AddDays(-1)) + { + _notificationGenerationService.PostAsync(user, NotificationType.LockedOut); + } + } + + } + } + foreach (var user in usersInTable) + { + if (user == null) continue; + var adUser = directory.GetDirectoryEntryBySid(user.Sid) as IADUser; + if (adUser!=null && !adUser.LockedOut) + { + var existing = context.LockedOutUsers.FirstOrDefault(x => x.Sid == user.Sid); + if (existing != null) + { + context.LockedOutUsers.Remove(existing); + + } + + + + } + } + context.SaveChanges(); + return true; + }); + executeJob.AddStep(analyzeStep); + var result = executeJob.Run(); + + + } + } +} diff --git a/BLAZAMServices/Background/NotificationGenerationService.cs b/BLAZAMServices/Background/NotificationGenerationService.cs index a5d1015a5..d6bd0f93c 100644 --- a/BLAZAMServices/Background/NotificationGenerationService.cs +++ b/BLAZAMServices/Background/NotificationGenerationService.cs @@ -218,6 +218,13 @@ public void PackageNotification(IDirectoryEntryAdapter source, NotificationType passwordChangeMessage.EntryName = source.CanonicalName; emailMessage = passwordChangeMessage; break; + case NotificationType.LockedOut: + notificationTitle += _appLocalization["User locked out"]; + notificationBody += _appLocalization["has been locked out at "] + time; + var lockedOutMessage = NotificationType.LockedOut.ToNotification(); + lockedOutMessage.EntryName = source.CanonicalName; + emailMessage = lockedOutMessage; + break; } if (actor != null) diff --git a/BLAZAMServices/MFARequestedException.cs b/BLAZAMServices/Exceptions/MFARequestedException.cs similarity index 96% rename from BLAZAMServices/MFARequestedException.cs rename to BLAZAMServices/Exceptions/MFARequestedException.cs index 004c0ac53..48c4375fa 100644 --- a/BLAZAMServices/MFARequestedException.cs +++ b/BLAZAMServices/Exceptions/MFARequestedException.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Components.Authorization; using System.Runtime.Serialization; -namespace BLAZAM.Services +namespace BLAZAM.Services.Exceptions { [Serializable] internal class MFARequestedException : Exception From 0adeb82ed723d3b6ccfb8becbef5757327676670 Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Sat, 28 Dec 2024 18:27:06 -0500 Subject: [PATCH 2/3] Remove unlocked users --- .../Background/LockedOutUserMonitor.cs | 1 - BLAZAMServices/GlobalUsing.cs | 1 + BLAZAMServices/UserSeederService.cs | 37 +++++++------------ BLAZAMSession/ApplicationNewsService.cs | 21 ++++++----- 4 files changed, 26 insertions(+), 34 deletions(-) create mode 100644 BLAZAMServices/GlobalUsing.cs diff --git a/BLAZAMServices/Background/LockedOutUserMonitor.cs b/BLAZAMServices/Background/LockedOutUserMonitor.cs index 9fbe5dbbc..d9b1f3a27 100644 --- a/BLAZAMServices/Background/LockedOutUserMonitor.cs +++ b/BLAZAMServices/Background/LockedOutUserMonitor.cs @@ -4,7 +4,6 @@ using BLAZAM.Database.Models.Notifications; using BLAZAM.Helpers; using BLAZAM.Jobs; -using BLAZAM.Services.Attributes; using System; using System.Collections.Generic; using System.IO; diff --git a/BLAZAMServices/GlobalUsing.cs b/BLAZAMServices/GlobalUsing.cs new file mode 100644 index 000000000..0084f7f74 --- /dev/null +++ b/BLAZAMServices/GlobalUsing.cs @@ -0,0 +1 @@ +global using BLAZAM.Services.Attributes; diff --git a/BLAZAMServices/UserSeederService.cs b/BLAZAMServices/UserSeederService.cs index b0513d98d..b7d50c1e6 100644 --- a/BLAZAMServices/UserSeederService.cs +++ b/BLAZAMServices/UserSeederService.cs @@ -3,36 +3,24 @@ using BLAZAM.Database.Context; using BLAZAM.Helpers; using BLAZAM.Logger; +using BLAZAM.Services.Background; namespace BLAZAM.Services { /// /// Prefills the user table with all users who have login access /// - public class UserSeederService + [AutoStartBackgroundService(60)] + public class UserSeederService:ActiveDirectoryBackgroundServiceBase { private readonly ApplicationInfo _applicationInfo; - private readonly IActiveDirectoryContext _activeDirectoryContext; - private readonly IAppDatabaseFactory _dbFactory; - public UserSeederService(IAppDatabaseFactory dbFactory, - IActiveDirectoryContextFactory adFactory, - ApplicationInfo applicationInfo) + public UserSeederService(ApplicationInfo applicationInfo,IActiveDirectoryContextFactory activeDirectoryContextFactory, IAppDatabaseFactory dbFactory) : base(activeDirectoryContextFactory, dbFactory) { - _applicationInfo = applicationInfo; - _activeDirectoryContext = adFactory.CreateActiveDirectoryContext(); - _dbFactory = dbFactory; - - //TODO Move ProgramEvents to Common - //ProgramEvents.PermissionsChanged += SeedUsers; - Task.Delay(30000).ContinueWith(task => - { - SeedUsers(); - }); - //SeedUsers(); + _applicationInfo= applicationInfo; } - private void SeedUsers(object obj = null) + protected override void Execute(object? obj = null) { try { @@ -41,11 +29,12 @@ private void SeedUsers(object obj = null) if (_applicationInfo.InDemoMode) EnsureDemoExists(); - using var context = _dbFactory.CreateDbContext(); + using var context = dbFactory.CreateDbContext(); + using var activeDirectoryContext = activeDirectoryContextFactory.CreateActiveDirectoryContext(); if (context.Status != ServiceConnectionState.Up) return; foreach (var deleg in context.PermissionDelegate.Where(x => x.DeletedAt == null).ToList()) { - var entry = _activeDirectoryContext.FindEntryBySID(deleg.DelegateSid); + var entry = activeDirectoryContext.FindEntryBySID(deleg.DelegateSid); if (entry != null) { if (entry is IADUser user) @@ -75,7 +64,7 @@ private void SeedUsers(object obj = null) /// private void EnsureUserExists(IADUser user) { - using var context = _dbFactory.CreateDbContext(); + using var context = dbFactory.CreateDbContext(); if (!context.UserSettings.Any(us => us.UserGUID == user.SID.ToSidString())) { context.UserSettings.Add(new() @@ -92,7 +81,7 @@ private void EnsureUserExists(IADUser user) /// private void EnsureAdminExists() { - using var context = _dbFactory.CreateDbContext(); + using var context = dbFactory.CreateDbContext(); if (!context.UserSettings.Any(us => us.UserGUID == "1")) { context.UserSettings.Add(new() @@ -108,7 +97,7 @@ private void EnsureAdminExists() /// private void EnsureDemoExists() { - using var context = _dbFactory.CreateDbContext(); + using var context = dbFactory.CreateDbContext(); if (!context.UserSettings.Any(us => us.UserGUID == "2")) { context.UserSettings.Add(new() @@ -124,7 +113,7 @@ private void EnsureDemoExists() /// private void EnsureSelfExists() { - using var context = _dbFactory.CreateDbContext(); + using var context = dbFactory.CreateDbContext(); if (!context.UserSettings.Any(us => us.UserGUID == "3")) { context.UserSettings.Add(new() diff --git a/BLAZAMSession/ApplicationNewsService.cs b/BLAZAMSession/ApplicationNewsService.cs index f4f124d69..3557e794b 100644 --- a/BLAZAMSession/ApplicationNewsService.cs +++ b/BLAZAMSession/ApplicationNewsService.cs @@ -19,7 +19,7 @@ public class ApplicationNewsService : IApplicationNewsService 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.ScheduledAt < DateTime.Now) && (x.ExpiresAt == null || x.ExpiresAt > DateTime.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() { @@ -89,7 +89,7 @@ public List GetUnreadNewsItems(IApplicationUserState user) { try { - var activeItems = activeNewsItems; + var activeItems = _activeNewsItems; var unreadItems = new List(); foreach (var item in activeItems) { @@ -131,16 +131,19 @@ public List GetReadNewsItems(IApplicationUserState user) { try { - - var activeItems = activeNewsItems; - if (user.ReadNewsItems != null) + if (user != null) { - var readItems = activeItems.Where(x => user.ReadNewsItems.Any(r => r.NewsItemId == x.Id && r.NewsItemUpdatedAt >= x.UpdatedAt)).ToList(); + var activeItems = _activeNewsItems; + if (user.ReadNewsItems != null) + { + var readItems = activeItems.Where(x => user.ReadNewsItems.Any(r => r.NewsItemId == x.Id && r.NewsItemUpdatedAt >= x.UpdatedAt)).ToList(); - return readItems; - } + return readItems; + } - return new(); + return new(); + } + return new List(); } catch (Exception ex) From 497a6d82f2257f30f263d22bbc72f12f33107d0c Mon Sep 17 00:00:00 2001 From: Chris Jacobsen Date: Sun, 29 Dec 2024 13:30:48 -0500 Subject: [PATCH 3/3] Auto-start attribute usage expanded --- BLAZAM/BLAZAM.csproj | 2 +- BLAZAM/ProgramHelpers.cs | 73 ++++++++++++------ BLAZAMGui/BLAZAMGui.csproj | 6 +- BLAZAMGui/Helper/GuiHelpers.cs | 3 +- BLAZAMJobs/Job.cs | 36 +++++++++ .../ApplicationNews.dll | Bin .../Attributes/AutoStartBackgroundService.cs | 5 +- BLAZAMServices/BLAZAMServices.csproj | 7 ++ .../Background}/ApplicationNewsService.cs | 17 ++-- .../Background}/AutoUpdateService.cs | 22 ++++-- .../Background/BackgroundServiceBase.cs | 2 +- .../Background}/IApplicationNewsService.cs | 0 .../{ => Background}/UserSeederService.cs | 71 +++++++++-------- BLAZAMSession/BLAZAMSession.csproj | 6 -- BLAZAMUpdate/Helpers/UpdateHelpers.cs | 2 +- 15 files changed, 167 insertions(+), 85 deletions(-) rename {BLAZAMSession => BLAZAMServices}/ApplicationNews.dll (100%) rename {BLAZAMSession => BLAZAMServices/Background}/ApplicationNewsService.cs (93%) rename {BLAZAMUpdate/Services => BLAZAMServices/Background}/AutoUpdateService.cs (95%) rename {BLAZAMSession/Interfaces => BLAZAMServices/Background}/IApplicationNewsService.cs (100%) rename BLAZAMServices/{ => Background}/UserSeederService.cs (59%) diff --git a/BLAZAM/BLAZAM.csproj b/BLAZAM/BLAZAM.csproj index bb7f378d6..2a3b880e7 100644 --- a/BLAZAM/BLAZAM.csproj +++ b/BLAZAM/BLAZAM.csproj @@ -6,7 +6,7 @@ enable false 1.2.4 - 2024.12.28.2159 + 2024.12.29.1826 false BLAZAM True diff --git a/BLAZAM/ProgramHelpers.cs b/BLAZAM/ProgramHelpers.cs index 923501e1f..0a8f3be8d 100644 --- a/BLAZAM/ProgramHelpers.cs +++ b/BLAZAM/ProgramHelpers.cs @@ -268,9 +268,6 @@ public static WebApplicationBuilder InjectServices(this WebApplicationBuilder bu //Provide a PermissionHandler as a service builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - - builder.Services.AddSingleton(); //Provide a AuditLogger as a service builder.Services.AddScoped(); @@ -410,58 +407,86 @@ public static WebApplicationBuilder InjectBackgroundServices(this WebApplication Parallel.ForEach(assemblies, assembly => { var types = assembly.GetTypes() - .Where(t => t.IsClass && !t.IsAbstract && t.GetCustomAttribute() != null); + .Where(t => t.IsClass && !t.IsAbstract + && t.GetCustomAttribute() != null); foreach (var type in types) { - lock (_lock) + var interfaceType = type.GetInterfaces() + .FirstOrDefault(i => i.GetCustomAttribute() == null + && i.Name != "IDisposable"); + + if (interfaceType != null) { - builder.Services.AddSingleton(type); + lock (_lock) + { + builder.Services.AddSingleton(interfaceType, type); + } + } + else + { + lock (_lock) + { + builder.Services.AddSingleton(type); + } } } }); - - - //foreach (var assembly in assemblies) - //{ - // var types = assembly.GetTypes() - // .Where(t => t.IsClass && !t.IsAbstract && t.GetCustomAttribute() != null); - - // foreach (var type in types) - // { - // builder.Services.AddSingleton(type); - // } - //} return builder; } + /// + /// Auto-starts adorned classes and + /// sets the Seq logging opt-out, and other singleton services + /// + /// public static void PreRun(this WebApplication application) { try { var assemblies = AppDomain.CurrentDomain.GetAssemblies(); - + foreach (var assembly in assemblies) { var types = assembly.GetTypes() - .Where(t => t.IsClass && !t.IsAbstract && t.GetCustomAttribute() != null); + .Where(t => t.IsClass && !t.IsAbstract + && t.GetCustomAttribute() != null); foreach (var type in types) { - var service = application.Services.GetRequiredService(type) as BackgroundServiceBase; try { - service.Start(); + var interfaceType = type.GetInterfaces() + .FirstOrDefault(i => i.GetCustomAttribute() == null + && i.Name != "IDisposable"); + BackgroundServiceBase? service; + + if (interfaceType != null) + { + service = application.Services.GetRequiredService(interfaceType) as BackgroundServiceBase; + + } + else + { + service = application.Services.GetRequiredService(type) as BackgroundServiceBase; + + } + + + var data = type.GetCustomAttribute(); + service?.Start(data?.Immediate==true); } - catch + catch (Exception ex) { + Loggers.SystemLogger.Error("Critical error starting up background service! {Error}", ex); } } } } - catch + catch (Exception ex) { + Loggers.SystemLogger.Error("Critical error getting loaded assemblies! {Error}", ex); } //Setup Seq logging if allowed by admin diff --git a/BLAZAMGui/BLAZAMGui.csproj b/BLAZAMGui/BLAZAMGui.csproj index c3b292d01..48522bc6c 100644 --- a/BLAZAMGui/BLAZAMGui.csproj +++ b/BLAZAMGui/BLAZAMGui.csproj @@ -42,9 +42,9 @@ - - ..\BLAZAMSession\ApplicationNews.dll - + + ..\BLAZAMServices\ApplicationNews.dll + diff --git a/BLAZAMGui/Helper/GuiHelpers.cs b/BLAZAMGui/Helper/GuiHelpers.cs index 20a099c51..3fc72a47d 100644 --- a/BLAZAMGui/Helper/GuiHelpers.cs +++ b/BLAZAMGui/Helper/GuiHelpers.cs @@ -1,4 +1,5 @@ -using ApplicationNews; + +using ApplicationNews; using BLAZAM.Database.Models.Templates; using BLAZAM.Gui.UI.Modals; using Microsoft.AspNetCore.Components.Forms; diff --git a/BLAZAMJobs/Job.cs b/BLAZAMJobs/Job.cs index 6f3cd63bb..c6cd698f3 100644 --- a/BLAZAMJobs/Job.cs +++ b/BLAZAMJobs/Job.cs @@ -1,5 +1,10 @@  +using BLAZAM.Helpers; +using System.Diagnostics; +using System.Reflection; +using System.Runtime.CompilerServices; + namespace BLAZAM.Jobs { @@ -38,6 +43,10 @@ public Job(string? title = null, string? requestingUser = null, CancellationToke { Name = title; User = requestingUser; + if (User.IsNullOrEmpty()) + { + User = GetCallingClassName(); + } if (externalCancellationToken != null) { cancellationTokenSource = externalCancellationToken; @@ -46,7 +55,34 @@ public Job(string? title = null, string? requestingUser = null, CancellationToke JobMonitor.AddJob(this); } + private string GetCallingClassName() + { + var stackTrace = new StackTrace(); + MethodBase? method=null; + // Start from frame 2 to skip Job and GetCallingClassName + + + for (int i = 2; i < stackTrace.FrameCount; i++) + { + var frame = stackTrace.GetFrame(i); + method = frame?.GetMethod(); + + // Check for async methods and compiler-generated types + if ( + method?.DeclaringType?.Name.StartsWith("<") == true) + { + // If async, skip this frame AND the next one + i++; // Skip the next frame as well + + continue; + } + // Found a non-async, non-compiler-generated method + break; + } + + return method?.DeclaringType?.Name ?? "System"; + } /// /// Used for scheduled triggering diff --git a/BLAZAMSession/ApplicationNews.dll b/BLAZAMServices/ApplicationNews.dll similarity index 100% rename from BLAZAMSession/ApplicationNews.dll rename to BLAZAMServices/ApplicationNews.dll diff --git a/BLAZAMServices/Attributes/AutoStartBackgroundService.cs b/BLAZAMServices/Attributes/AutoStartBackgroundService.cs index dbbd3af73..10135a39a 100644 --- a/BLAZAMServices/Attributes/AutoStartBackgroundService.cs +++ b/BLAZAMServices/Attributes/AutoStartBackgroundService.cs @@ -9,15 +9,16 @@ namespace BLAZAM.Services.Attributes public class AutoStartBackgroundService:System.Attribute { public int IntervalInMinutes { get; set; } - + public bool Immediate { get; set; } /// /// /// /// The time in minutes this service should execute - public AutoStartBackgroundService(int interval) + public AutoStartBackgroundService(int interval, bool immediate=false) { IntervalInMinutes = interval; + Immediate = immediate; } } } diff --git a/BLAZAMServices/BLAZAMServices.csproj b/BLAZAMServices/BLAZAMServices.csproj index d574fd82a..ae5f7e1ff 100644 --- a/BLAZAMServices/BLAZAMServices.csproj +++ b/BLAZAMServices/BLAZAMServices.csproj @@ -23,6 +23,13 @@ + + + + + + ApplicationNews.dll + diff --git a/BLAZAMSession/ApplicationNewsService.cs b/BLAZAMServices/Background/ApplicationNewsService.cs similarity index 93% rename from BLAZAMSession/ApplicationNewsService.cs rename to BLAZAMServices/Background/ApplicationNewsService.cs index 3557e794b..990c54c0e 100644 --- a/BLAZAMSession/ApplicationNewsService.cs +++ b/BLAZAMServices/Background/ApplicationNewsService.cs @@ -10,9 +10,10 @@ using System.Text.Json; using System.Threading.Tasks; -namespace BLAZAM.Session +namespace BLAZAM.Services.Background { - public class ApplicationNewsService : IApplicationNewsService + [AutoStartBackgroundService(15, true)] + public class ApplicationNewsService : BackgroundServiceBase, IApplicationNewsService { private HttpClient _httpClient; private HttpClient _secondaryHttpClient; @@ -21,7 +22,8 @@ public class ApplicationNewsService : IApplicationNewsService private List _allNewsItems = new List(); 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() + + public ApplicationNewsService(IAppDatabaseFactory dbFactory) : base(dbFactory) { _httpClient = new HttpClient { @@ -33,16 +35,12 @@ public ApplicationNewsService() BaseAddress = new Uri("https://blazam-news.azurewebsites.net/api/"), Timeout = TimeSpan.FromSeconds(60) }; - _pollingTimer = new Timer(Tick, null, 10, 1000 * 60 * 15); + //_pollingTimer = new Timer(Tick, null, 10, 1000 * 60 * 15); // GetAllNewsItems(); } - private async void Tick(object? state) - { - await GetAllNewsItems(); - } - private async Task GetAllNewsItems() + protected override async void Execute(object? obj = null) { try { @@ -155,6 +153,7 @@ public List GetReadNewsItems(IApplicationUserState user) public void Dispose() { _httpClient.Dispose(); + _secondaryHttpClient.Dispose(); _pollingTimer?.Dispose(); } } diff --git a/BLAZAMUpdate/Services/AutoUpdateService.cs b/BLAZAMServices/Background/AutoUpdateService.cs similarity index 95% rename from BLAZAMUpdate/Services/AutoUpdateService.cs rename to BLAZAMServices/Background/AutoUpdateService.cs index cb5436e69..23214ddd5 100644 --- a/BLAZAMUpdate/Services/AutoUpdateService.cs +++ b/BLAZAMServices/Background/AutoUpdateService.cs @@ -4,14 +4,17 @@ using BLAZAM.Helpers; using BLAZAM.Jobs; using BLAZAM.Logger; +using BLAZAM.Update; +using BLAZAM.Update.Services; using Microsoft.AspNetCore.Components; using Microsoft.EntityFrameworkCore; using SQLitePCL; using System.DirectoryServices.Protocols; -namespace BLAZAM.Update.Services +namespace BLAZAM.Services.Background { - public class AutoUpdateService + [AutoStartBackgroundService(60)] + public class AutoUpdateService : BackgroundServiceBase, IDisposable { public AppEvent OnAutoUpdateQueued { get; set; } @@ -32,13 +35,13 @@ public class AutoUpdateService //private AuditLogger Audit; - public AutoUpdateService(IAppDatabaseFactory factory, UpdateService updateService, ApplicationInfo applicationInfo) + public AutoUpdateService(IAppDatabaseFactory factory, UpdateService updateService, ApplicationInfo applicationInfo):base(factory) { _applicationInfo = applicationInfo; this.factory = factory; this.updateService = updateService; - updateCheckTimer = new Timer(CheckForUpdate, null, (int)TimeSpan.FromSeconds(1).TotalMilliseconds, (int)TimeSpan.FromHours(1).TotalMilliseconds); - directoryCleaner = new Timer(CleanDirectories, null, (int)TimeSpan.FromSeconds(30).TotalMilliseconds, (int)TimeSpan.FromHours(20).TotalMilliseconds); + //updateCheckTimer = new Timer(CheckForUpdate, null, (int)TimeSpan.FromSeconds(1).TotalMilliseconds, (int)TimeSpan.FromHours(1).TotalMilliseconds); + directoryCleaner = new Timer(CleanDirectories, null, TimeSpan.FromSeconds(30), TimeSpan.FromHours(20)); } private void CleanDirectories(object? state) @@ -181,7 +184,7 @@ private void CleanDirectories(object? state) } - private async void CheckForUpdate(object? state) + protected override async void Execute(object? state) { using var context = factory.CreateDbContext(); IJob updateCheckJob = new Job("Check for Update"); @@ -367,5 +370,12 @@ private async void Update(object? state) } + + public void Dispose() + { + autoUpdateApplyTimer?.Dispose(); + updateCheckTimer?.Dispose(); + directoryCleaner?.Dispose(); + } } } diff --git a/BLAZAMServices/Background/BackgroundServiceBase.cs b/BLAZAMServices/Background/BackgroundServiceBase.cs index d056f2819..8abd6897a 100644 --- a/BLAZAMServices/Background/BackgroundServiceBase.cs +++ b/BLAZAMServices/Background/BackgroundServiceBase.cs @@ -13,7 +13,7 @@ public class BackgroundServiceBase : IDisposable protected virtual IAppDatabaseFactory dbFactory { get; } protected virtual Timer? Timer { get; set; } protected virtual TimeSpan Interval{ get; set; } = TimeSpan.FromMinutes(10); - protected static bool started { get; set; } + protected bool started { get; set; } public BackgroundServiceBase(IAppDatabaseFactory dbFactory) { this.dbFactory = dbFactory; diff --git a/BLAZAMSession/Interfaces/IApplicationNewsService.cs b/BLAZAMServices/Background/IApplicationNewsService.cs similarity index 100% rename from BLAZAMSession/Interfaces/IApplicationNewsService.cs rename to BLAZAMServices/Background/IApplicationNewsService.cs diff --git a/BLAZAMServices/UserSeederService.cs b/BLAZAMServices/Background/UserSeederService.cs similarity index 59% rename from BLAZAMServices/UserSeederService.cs rename to BLAZAMServices/Background/UserSeederService.cs index b7d50c1e6..077427ac9 100644 --- a/BLAZAMServices/UserSeederService.cs +++ b/BLAZAMServices/Background/UserSeederService.cs @@ -2,61 +2,70 @@ using BLAZAM.Common.Data; using BLAZAM.Database.Context; using BLAZAM.Helpers; +using BLAZAM.Jobs; using BLAZAM.Logger; -using BLAZAM.Services.Background; -namespace BLAZAM.Services +namespace BLAZAM.Services.Background { /// /// Prefills the user table with all users who have login access /// [AutoStartBackgroundService(60)] - public class UserSeederService:ActiveDirectoryBackgroundServiceBase + public class UserSeederService : ActiveDirectoryBackgroundServiceBase { private readonly ApplicationInfo _applicationInfo; - public UserSeederService(ApplicationInfo applicationInfo,IActiveDirectoryContextFactory activeDirectoryContextFactory, IAppDatabaseFactory dbFactory) : base(activeDirectoryContextFactory, dbFactory) + public UserSeederService(ApplicationInfo applicationInfo, IActiveDirectoryContextFactory activeDirectoryContextFactory, IAppDatabaseFactory dbFactory) : base(activeDirectoryContextFactory, dbFactory) { - _applicationInfo= applicationInfo; + _applicationInfo = applicationInfo; } protected override void Execute(object? obj = null) { - try + Job seedJob = new Job("Seed New Users"); + JobStep step = new JobStep("Check for new users", (state) => { - EnsureAdminExists(); - EnsureSelfExists(); - - if (_applicationInfo.InDemoMode) - EnsureDemoExists(); - using var context = dbFactory.CreateDbContext(); - using var activeDirectoryContext = activeDirectoryContextFactory.CreateActiveDirectoryContext(); - if (context.Status != ServiceConnectionState.Up) return; - foreach (var deleg in context.PermissionDelegate.Where(x => x.DeletedAt == null).ToList()) + try { - var entry = activeDirectoryContext.FindEntryBySID(deleg.DelegateSid); - if (entry != null) + EnsureAdminExists(); + EnsureSelfExists(); + + if (_applicationInfo.InDemoMode) + EnsureDemoExists(); + using var context = dbFactory.CreateDbContext(); + using var activeDirectoryContext = activeDirectoryContextFactory.CreateActiveDirectoryContext(); + if (context.Status != ServiceConnectionState.Up) return false; + foreach (var deleg in context.PermissionDelegate.Where(x => x.DeletedAt == null).ToList()) { - if (entry is IADUser user) - { - EnsureUserExists(user); - } - if (entry is IADGroup group) + var entry = activeDirectoryContext.FindEntryBySID(deleg.DelegateSid); + if (entry != null) { - foreach (var member in group.NestedMembers) + if (entry is IADUser user) + { + EnsureUserExists(user); + } + if (entry is IADGroup group) { - var type = member.GetType(); - if (member is IADUser aduser) - EnsureUserExists(aduser); + foreach (var member in group.NestedMembers) + { + var type = member.GetType(); + if (member is IADUser aduser) + EnsureUserExists(aduser); + } } } } } - } - catch (Exception ex) - { - Loggers.SystemLogger.Error("Error attempting to synchronize directory and application users. {@Error}", ex); - } + catch (Exception ex) + { + Loggers.SystemLogger.Error("Error attempting to synchronize directory and application users. {@Error}", ex); + return false; + } + return true; + }); + seedJob.AddStep(step); + var result = seedJob.Run(); + } /// /// Checks the database for this user, if not found they are added diff --git a/BLAZAMSession/BLAZAMSession.csproj b/BLAZAMSession/BLAZAMSession.csproj index 2ba0cfb36..73a29ff4f 100644 --- a/BLAZAMSession/BLAZAMSession.csproj +++ b/BLAZAMSession/BLAZAMSession.csproj @@ -12,10 +12,4 @@ - - - ApplicationNews.dll - - - diff --git a/BLAZAMUpdate/Helpers/UpdateHelpers.cs b/BLAZAMUpdate/Helpers/UpdateHelpers.cs index f059ce2cc..4502e8bc4 100644 --- a/BLAZAMUpdate/Helpers/UpdateHelpers.cs +++ b/BLAZAMUpdate/Helpers/UpdateHelpers.cs @@ -20,7 +20,7 @@ public static IServiceCollection AddUpdateServices(this IServiceCollection servi //Provide Automatic Updates as a service //This service runs checks every 4 hours for an update and if found, schedules an //update at a time of day specified in the database - services.AddSingleton(); + //services.AddSingleton(); return services; } }