diff --git a/SecurityService.BusinessLogic/RequestHandlers/UserRequestHandler.cs b/SecurityService.BusinessLogic/RequestHandlers/UserRequestHandler.cs index 4053557a..7c8fdfe3 100644 --- a/SecurityService.BusinessLogic/RequestHandlers/UserRequestHandler.cs +++ b/SecurityService.BusinessLogic/RequestHandlers/UserRequestHandler.cs @@ -183,6 +183,7 @@ public async Task Handle(SecurityServiceCommands.CreateUserCommand comma MiddleName = command.MiddleName, FamilyName = command.FamilyName, EmailConfirmed = string.IsNullOrWhiteSpace(command.EmailAddress), + RegistrationDateTime = DateTime.Now, }; Result passwordValueResult = String.IsNullOrEmpty(command.Password) ? PasswordGenerator.GenerateRandomPassword(this.Options.Value.PasswordOptions) : command.Password; @@ -350,6 +351,7 @@ private async Task MapAsync(ApplicationUser user) user.GivenName, user.MiddleName, user.FamilyName, + user.RegistrationDateTime, claims.GroupBy(claim => claim.Type, StringComparer.OrdinalIgnoreCase).ToDictionary(group => group.Key, group => group.Last().Value, StringComparer.OrdinalIgnoreCase), roles.ToArray()); } diff --git a/SecurityService.DataTransferObjects/Responses.cs b/SecurityService.DataTransferObjects/Responses.cs index 99d0fae5..efc96fdd 100644 --- a/SecurityService.DataTransferObjects/Responses.cs +++ b/SecurityService.DataTransferObjects/Responses.cs @@ -163,6 +163,10 @@ public sealed record UserResponse { [JsonProperty("roles")] [JsonPropertyName("roles")] public IReadOnlyCollection Roles { get; set; } + + [JsonProperty("registration_date_time")] + [JsonPropertyName("registration_date_time")] + public DateTime RegistrationDateTime { get; set; } } public class TokenResponse diff --git a/SecurityService.Database/ApplicationUser.cs b/SecurityService.Database/ApplicationUser.cs index 109335f9..85ed96cb 100644 --- a/SecurityService.Database/ApplicationUser.cs +++ b/SecurityService.Database/ApplicationUser.cs @@ -9,4 +9,6 @@ public sealed class ApplicationUser : IdentityUser public string? MiddleName { get; set; } public string? FamilyName { get; set; } + + public DateTime RegistrationDateTime { get; set; } } diff --git a/SecurityService.Database/SecurityService.Database.csproj b/SecurityService.Database/SecurityService.Database.csproj index 1d6ac12d..e062705c 100644 --- a/SecurityService.Database/SecurityService.Database.csproj +++ b/SecurityService.Database/SecurityService.Database.csproj @@ -13,6 +13,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/SecurityService.Models/DetailsModels.cs b/SecurityService.Models/DetailsModels.cs index c9477966..45a8950d 100644 --- a/SecurityService.Models/DetailsModels.cs +++ b/SecurityService.Models/DetailsModels.cs @@ -46,6 +46,7 @@ public sealed record UserDetails( string? GivenName, string? MiddleName, string? FamilyName, + DateTime RegistrationDateTime, IReadOnlyDictionary Claims, IReadOnlyCollection Roles); diff --git a/SecurityService.SqlServerMigrations/Migrations/20260412202818_record_registration_date.Designer.cs b/SecurityService.SqlServerMigrations/Migrations/20260412202818_record_registration_date.Designer.cs new file mode 100644 index 00000000..669586d6 --- /dev/null +++ b/SecurityService.SqlServerMigrations/Migrations/20260412202818_record_registration_date.Designer.cs @@ -0,0 +1,647 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SecurityService.Database.DbContexts; + +#nullable disable + +namespace SecurityService.SqlServerMigrations.Migrations +{ + [DbContext(typeof(SecurityServiceDbContext))] + [Migration("20260412202818_record_registration_date")] + partial class record_registration_date + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("ClientSecret") + .HasColumnType("nvarchar(max)"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("DisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayNames") + .HasColumnType("nvarchar(max)"); + + b.Property("JsonWebKeySet") + .HasColumnType("nvarchar(max)"); + + b.Property("Permissions") + .HasColumnType("nvarchar(max)"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("nvarchar(max)"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("RedirectUris") + .HasColumnType("nvarchar(max)"); + + b.Property("Requirements") + .HasColumnType("nvarchar(max)"); + + b.Property("Settings") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId") + .IsUnique() + .HasFilter("[ClientId] IS NOT NULL"); + + b.ToTable("OpenIddictApplications", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("ApplicationId") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("Scopes") + .HasColumnType("nvarchar(max)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("nvarchar(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("Descriptions") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayNames") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("Resources") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique() + .HasFilter("[Name] IS NOT NULL"); + + b.ToTable("OpenIddictScopes", (string)null); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("ApplicationId") + .HasColumnType("nvarchar(450)"); + + b.Property("AuthorizationId") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ExpirationDate") + .HasColumnType("datetime2"); + + b.Property("Payload") + .HasColumnType("nvarchar(max)"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("RedemptionDate") + .HasColumnType("datetime2"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("nvarchar(400)"); + + b.Property("Type") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId") + .IsUnique() + .HasFilter("[ReferenceId] IS NOT NULL"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", (string)null); + }); + + modelBuilder.Entity("SecurityService.Database.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FamilyName") + .HasColumnType("nvarchar(max)"); + + b.Property("GivenName") + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("MiddleName") + .HasColumnType("nvarchar(max)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("RegistrationDateTime") + .HasColumnType("datetime2"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("SecurityService.Database.Entities.ClientDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AllowOfflineAccess") + .HasColumnType("bit"); + + b.Property("AllowedGrantTypesJson") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AllowedScopesJson") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ClientName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ClientType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("ClientUri") + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("PostLogoutRedirectUrisJson") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("RedirectUrisJson") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("RequireConsent") + .HasColumnType("bit"); + + b.Property("SecretHash") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId") + .IsUnique(); + + b.ToTable("ClientDefinitions"); + }); + + modelBuilder.Entity("SecurityService.Database.Entities.ResourceDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimsJson") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("Emphasize") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ScopesJson") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SecretHash") + .HasColumnType("nvarchar(max)"); + + b.Property("ShowInDiscoveryDocument") + .HasColumnType("bit"); + + b.Property("Type") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "Type") + .IsUnique(); + + b.ToTable("ResourceDefinitions"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("SecurityService.Database.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("SecurityService.Database.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("SecurityService.Database.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("SecurityService.Database.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b => + { + b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Authorizations") + .HasForeignKey("ApplicationId"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b => + { + b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Tokens") + .HasForeignKey("ApplicationId"); + + b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", "Authorization") + .WithMany("Tokens") + .HasForeignKey("AuthorizationId"); + + b.Navigation("Application"); + + b.Navigation("Authorization"); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b => + { + b.Navigation("Authorizations"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Navigation("Tokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20250318231606_record_registration_date.cs b/SecurityService.SqlServerMigrations/Migrations/20260412202818_record_registration_date.cs similarity index 93% rename from archive/SecurityService.SqlServerMigrations/AuthenticationDb/20250318231606_record_registration_date.cs rename to SecurityService.SqlServerMigrations/Migrations/20260412202818_record_registration_date.cs index a016a438..b263938b 100644 --- a/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20250318231606_record_registration_date.cs +++ b/SecurityService.SqlServerMigrations/Migrations/20260412202818_record_registration_date.cs @@ -3,7 +3,7 @@ #nullable disable -namespace SecurityService.SqlServerMigrations.AuthenticationDb +namespace SecurityService.SqlServerMigrations.Migrations { /// public partial class record_registration_date : Migration diff --git a/SecurityService.SqlServerMigrations/Migrations/SecurityServiceDbContextModelSnapshot.cs b/SecurityService.SqlServerMigrations/Migrations/SecurityServiceDbContextModelSnapshot.cs index 42e299a2..b6943b92 100644 --- a/SecurityService.SqlServerMigrations/Migrations/SecurityServiceDbContextModelSnapshot.cs +++ b/SecurityService.SqlServerMigrations/Migrations/SecurityServiceDbContextModelSnapshot.cs @@ -155,189 +155,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("AspNetUserTokens", (string)null); }); - modelBuilder.Entity("SecurityService.Database.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("FamilyName") - .HasColumnType("nvarchar(max)"); - - b.Property("GivenName") - .HasColumnType("nvarchar(max)"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("MiddleName") - .HasColumnType("nvarchar(max)"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("SecurityService.Database.Entities.ClientDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("AllowOfflineAccess") - .HasColumnType("bit"); - - b.Property("AllowedGrantTypesJson") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("AllowedScopesJson") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientName") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientType") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.Property("ClientUri") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("PostLogoutRedirectUrisJson") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("RedirectUrisJson") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("RequireConsent") - .HasColumnType("bit"); - - b.Property("SecretHash") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId") - .IsUnique(); - - b.ToTable("ClientDefinitions"); - }); - - modelBuilder.Entity("SecurityService.Database.Entities.ResourceDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("ClaimsJson") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("DisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("Emphasize") - .HasColumnType("bit"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Required") - .HasColumnType("bit"); - - b.Property("ScopesJson") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("SecretHash") - .HasColumnType("nvarchar(max)"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("bit"); - - b.Property("Type") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("Name", "Type") - .IsUnique(); - - b.ToTable("ResourceDefinitions"); - }); - modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b => { b.Property("Id") @@ -549,6 +366,192 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("OpenIddictTokens", (string)null); }); + modelBuilder.Entity("SecurityService.Database.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("FamilyName") + .HasColumnType("nvarchar(max)"); + + b.Property("GivenName") + .HasColumnType("nvarchar(max)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("MiddleName") + .HasColumnType("nvarchar(max)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("RegistrationDateTime") + .HasColumnType("datetime2"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("SecurityService.Database.Entities.ClientDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AllowOfflineAccess") + .HasColumnType("bit"); + + b.Property("AllowedGrantTypesJson") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("AllowedScopesJson") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ClientName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ClientType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("ClientUri") + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("PostLogoutRedirectUrisJson") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("RedirectUrisJson") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("RequireConsent") + .HasColumnType("bit"); + + b.Property("SecretHash") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId") + .IsUnique(); + + b.ToTable("ClientDefinitions"); + }); + + modelBuilder.Entity("SecurityService.Database.Entities.ResourceDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimsJson") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("Emphasize") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ScopesJson") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SecretHash") + .HasColumnType("nvarchar(max)"); + + b.Property("ShowInDiscoveryDocument") + .HasColumnType("bit"); + + b.Property("Type") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "Type") + .IsUnique(); + + b.ToTable("ResourceDefinitions"); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) diff --git a/SecurityService/Factories/ModelFactory.cs b/SecurityService/Factories/ModelFactory.cs index 8d40611e..edb650e4 100644 --- a/SecurityService/Factories/ModelFactory.cs +++ b/SecurityService/Factories/ModelFactory.cs @@ -22,7 +22,7 @@ public static UserResponse ConvertFrom(UserDetails model) { Claims = model.Claims, UserId = model.UserId, EmailAddress = model.EmailAddress, - //RegistrationDateTime = model.RegistrationDateTime + RegistrationDateTime = model.RegistrationDateTime, FamilyName = model.FamilyName, GivenName = model.GivenName, MiddleName = model.MiddleName diff --git a/archive/SecurityService.BusinessLogic/ApplicationUser.cs b/archive/SecurityService.BusinessLogic/ApplicationUser.cs deleted file mode 100644 index 8ba10bd6..00000000 --- a/archive/SecurityService.BusinessLogic/ApplicationUser.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace SecurityService.BusinessLogic -{ - using Microsoft.AspNetCore.Identity; - using System; - - public class ApplicationUser : IdentityUser - { - public DateTime RegistrationDateTime { get; set; } - } -} \ No newline at end of file diff --git a/archive/SecurityService.BusinessLogic/AssemblyInfo.cs b/archive/SecurityService.BusinessLogic/AssemblyInfo.cs deleted file mode 100644 index 88f02294..00000000 --- a/archive/SecurityService.BusinessLogic/AssemblyInfo.cs +++ /dev/null @@ -1,3 +0,0 @@ -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("SecurityService.UnitTests")] \ No newline at end of file diff --git a/archive/SecurityService.BusinessLogic/Exceptions/IdentityResultException.cs b/archive/SecurityService.BusinessLogic/Exceptions/IdentityResultException.cs deleted file mode 100644 index 10ffdd07..00000000 --- a/archive/SecurityService.BusinessLogic/Exceptions/IdentityResultException.cs +++ /dev/null @@ -1,48 +0,0 @@ -namespace SecurityService.BusinessLogic.Exceptions -{ - using System; - using System.Diagnostics.CodeAnalysis; - using System.Linq; - using System.Text; - using Microsoft.AspNetCore.Identity; - - [ExcludeFromCodeCoverage] - public class IdentityResultException : Exception - { - #region Public Properties - - /// - /// Gets the error. - /// - /// - /// The error. - /// - public String Error { get; private set; } - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The message. - /// The identity result. - public IdentityResultException(String message, IdentityResult identityResult) : base(message) - { - StringBuilder errors = new StringBuilder(); - if (identityResult.Errors.Any()) - { - // If there are any Errors then build up the error message - foreach (var identityError in identityResult.Errors) - { - errors.AppendLine(identityError.Description); - } - } - - this.Error = errors.ToString(); - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.BusinessLogic/Extensions.cs b/archive/SecurityService.BusinessLogic/Extensions.cs deleted file mode 100644 index b4c28264..00000000 --- a/archive/SecurityService.BusinessLogic/Extensions.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace SecurityService.BusinessLogic -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.EntityFrameworkCore; - - [ExcludeFromCodeCoverage] - public static class Extensions - { - #region Methods - - /// - /// Converts to listasyncsafe. - /// - /// The type of the source. - /// The source. - /// The cancellation token. - /// - /// source - public static Task> ToListAsyncSafe(this IQueryable source, - CancellationToken cancellationToken) - { - if (source == null) - throw new ArgumentNullException(nameof(source)); - if (!(source is IAsyncEnumerable)) - return Task.FromResult(source.ToList()); - return source.ToListAsync(cancellationToken); - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.BusinessLogic/PasswordOptions.cs b/archive/SecurityService.BusinessLogic/PasswordOptions.cs deleted file mode 100644 index 4dab3ea1..00000000 --- a/archive/SecurityService.BusinessLogic/PasswordOptions.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace SecurityService.BusinessLogic; - -using System; - -public class PasswordOptions -{ - #region Properties - - public Boolean RequireDigit { get; set; } - - public Int32 RequiredLength { get; set; } - - public Boolean RequireUpperCase { get; set; } - - #endregion -} \ No newline at end of file diff --git a/archive/SecurityService.BusinessLogic/RequestHandlers/ApiResourceRequestHandler.cs b/archive/SecurityService.BusinessLogic/RequestHandlers/ApiResourceRequestHandler.cs deleted file mode 100644 index 148fe5d3..00000000 --- a/archive/SecurityService.BusinessLogic/RequestHandlers/ApiResourceRequestHandler.cs +++ /dev/null @@ -1,102 +0,0 @@ -using Duende.IdentityModel; -using SecurityService.DataTransferObjects.Requests; -using SimpleResults; - -namespace SecurityService.BusinessLogic.RequestHandlers{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - using Duende.IdentityServer.EntityFramework.DbContexts; - using Duende.IdentityServer.EntityFramework.Mappers; - using Duende.IdentityServer.Models; - using MediatR; - using Microsoft.EntityFrameworkCore; - using Requests; - using Shared.Exceptions; - - public class ApiResourceRequestHandler : IRequestHandler, - IRequestHandler>, - IRequestHandler>>{ - #region Fields - - private readonly ConfigurationDbContext ConfigurationDbContext; - - #endregion - - #region Constructors - - public ApiResourceRequestHandler(ConfigurationDbContext configurationDbContext){ - this.ConfigurationDbContext = configurationDbContext; - } - - #endregion - - #region Methods - - public async Task Handle(SecurityServiceCommands.CreateApiResourceCommand command, CancellationToken cancellationToken) { - ApiResource apiResource = new ApiResource - { - ApiSecrets = new List{ - new Secret(command.Secret.ToSha256()) - }, - Description = command.Description, - DisplayName = command.DisplayName, - Name = command.Name, - UserClaims = command.UserClaims, - }; - - if (command.Scopes != null && command.Scopes.Any()) - { - foreach (String scope in command.Scopes) - { - apiResource.Scopes.Add(scope); - } - } - - // Now translate the model to the entity - await this.ConfigurationDbContext.ApiResources.AddAsync(apiResource.ToEntity(), cancellationToken); - - // Save the changes - await this.ConfigurationDbContext.SaveChangesAsync(cancellationToken); - - return Result.Success(); - } - - public async Task> Handle(SecurityServiceQueries.GetApiResourceQuery query, CancellationToken cancellationToken){ - ApiResource apiResourceModel = null; - - Duende.IdentityServer.EntityFramework.Entities.ApiResource apiResourceEntity = await this.ConfigurationDbContext.ApiResources - .Where(a => a.Name == query.Name).Include(a => a.Scopes) - .Include(a => a.UserClaims) - .SingleOrDefaultAsync(cancellationToken:cancellationToken); - - if (apiResourceEntity == null){ - return Result.NotFound($"No Api Resource found with Name [{query.Name}]"); - } - - apiResourceModel = apiResourceEntity.ToModel(); - - return Result.Success(apiResourceModel); - } - - public async Task>> Handle(SecurityServiceQueries.GetApiResourcesQuery request, CancellationToken cancellationToken){ - List apiResourceModels = new List(); - - List apiResourceEntities = await this.ConfigurationDbContext.ApiResources.Include(a => a.Scopes) - .Include(a => a.UserClaims) - .ToListAsync(cancellationToken:cancellationToken); - - if (apiResourceEntities.Any()){ - foreach (Duende.IdentityServer.EntityFramework.Entities.ApiResource apiResourceEntity in apiResourceEntities){ - apiResourceModels.Add(apiResourceEntity.ToModel()); - } - } - - return Result.Success(apiResourceModels); - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.BusinessLogic/RequestHandlers/ApiScopeRequestHandler.cs b/archive/SecurityService.BusinessLogic/RequestHandlers/ApiScopeRequestHandler.cs deleted file mode 100644 index df35e564..00000000 --- a/archive/SecurityService.BusinessLogic/RequestHandlers/ApiScopeRequestHandler.cs +++ /dev/null @@ -1,92 +0,0 @@ -using SecurityService.DataTransferObjects.Requests; -using SimpleResults; - -namespace SecurityService.BusinessLogic.RequestHandlers{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - using Duende.IdentityServer.EntityFramework.DbContexts; - using Duende.IdentityServer.EntityFramework.Mappers; - using Duende.IdentityServer.Models; - using MediatR; - using Microsoft.EntityFrameworkCore; - using Requests; - using Shared.Exceptions; - - public class ApiScopeRequestHandler : IRequestHandler, - IRequestHandler>, - IRequestHandler>>{ - #region Fields - - private readonly ConfigurationDbContext ConfigurationDbContext; - - #endregion - - #region Constructors - - public ApiScopeRequestHandler(ConfigurationDbContext configurationDbContext){ - this.ConfigurationDbContext = configurationDbContext; - } - - #endregion - - #region Methods - - public async Task Handle(SecurityServiceCommands.CreateApiScopeCommand command, CancellationToken cancellationToken){ - ApiScope apiScope = new ApiScope - { - Description = command.Description, - DisplayName = command.DisplayName, - Name = command.Name, - Emphasize = false, - Enabled = true, - Required = false, - ShowInDiscoveryDocument = true - }; - - // Now translate the model to the entity - await this.ConfigurationDbContext.ApiScopes.AddAsync(apiScope.ToEntity(), cancellationToken); - - // Save the changes - await this.ConfigurationDbContext.SaveChangesAsync(cancellationToken); - - return Result.Success(); - } - - public async Task> Handle(SecurityServiceQueries.GetApiScopeQuery query, CancellationToken cancellationToken){ - ApiScope apiScopeModel = null; - - Duende.IdentityServer.EntityFramework.Entities.ApiScope apiScopeEntity = await this.ConfigurationDbContext.ApiScopes.Where(a => a.Name == query.Name) - .Include(a => a.Properties).Include(a => a.UserClaims) - .SingleOrDefaultAsync(cancellationToken:cancellationToken); - - if (apiScopeEntity == null){ - return Result.NotFound($"No Api Scope found with Name [{query.Name}]"); - } - - apiScopeModel = apiScopeEntity.ToModel(); - - return Result.Success(apiScopeModel); - } - - public async Task>> Handle(SecurityServiceQueries.GetApiScopesQuery query, CancellationToken cancellationToken){ - List apiScopeModels = new List(); - - List apiScopeEntities = await this.ConfigurationDbContext.ApiScopes.Include(a => a.Properties) - .Include(a => a.UserClaims) - .ToListAsync(cancellationToken:cancellationToken); - - if (apiScopeEntities.Any()){ - foreach (Duende.IdentityServer.EntityFramework.Entities.ApiScope apiScopeEntity in apiScopeEntities){ - apiScopeModels.Add(apiScopeEntity.ToModel()); - } - } - - return Result.Success(apiScopeModels); - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.BusinessLogic/RequestHandlers/ClientRequestHandler.cs b/archive/SecurityService.BusinessLogic/RequestHandlers/ClientRequestHandler.cs deleted file mode 100644 index 99b42665..00000000 --- a/archive/SecurityService.BusinessLogic/RequestHandlers/ClientRequestHandler.cs +++ /dev/null @@ -1,142 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Duende.IdentityModel; -using SecurityService.DataTransferObjects.Requests; -using SimpleResults; - -namespace SecurityService.BusinessLogic.RequestHandlers -{ - using System.Threading; - using Duende.IdentityServer.EntityFramework.DbContexts; - using Duende.IdentityServer.EntityFramework.Entities; - using Duende.IdentityServer.EntityFramework.Mappers; - using Duende.IdentityServer.Models; - using MediatR; - using Microsoft.EntityFrameworkCore; - using Requests; - using Shared.Exceptions; - using Client = Duende.IdentityServer.Models.Client; - using Secret = Duende.IdentityServer.Models.Secret; - - public class ClientRequestHandler : IRequestHandler, - IRequestHandler>, - IRequestHandler>>{ - private readonly ConfigurationDbContext ConfigurationDbContext; - - public ClientRequestHandler(ConfigurationDbContext configurationDbContext){ - this.ConfigurationDbContext = configurationDbContext; - } - - public async Task Handle(SecurityServiceCommands.CreateClientCommand command, CancellationToken cancellationToken){ - // Validate the grant types list - Result validationResult = this.ValidateGrantTypes(command.AllowedGrantTypes); - if (validationResult.IsFailed) { - return validationResult; - } - - // Create the model from the request - Client client = new Client - { - ClientId = command.ClientId, - ClientName = command.ClientName, - Description = command.ClientDescription, - ClientSecrets ={ - new Secret(command.Secret.ToSha256()) - }, - AllowedGrantTypes = command.AllowedGrantTypes, - AllowedScopes = command.AllowedScopes, - RequireConsent = command.RequireConsent, - AllowOfflineAccess = command.AllowOfflineAccess, - ClientUri = command.ClientUri - }; - - if (command.AllowedGrantTypes.Contains("hybrid")) - { - client.RequirePkce = false; - } - - if (command.ClientRedirectUris != null && command.ClientRedirectUris.Any()) - { - client.RedirectUris = new List(); - foreach (String clientRedirectUri in command.ClientRedirectUris) - { - client.RedirectUris.Add(clientRedirectUri); - } - } - - if (command.ClientPostLogoutRedirectUris != null && command.ClientPostLogoutRedirectUris.Any()) - { - client.PostLogoutRedirectUris = new List(); - foreach (String clientPostLogoutRedirectUri in command.ClientPostLogoutRedirectUris) - { - client.PostLogoutRedirectUris.Add(clientPostLogoutRedirectUri); - } - } - - // Now translate the model to the entity - await this.ConfigurationDbContext.Clients.AddAsync(client.ToEntity(), cancellationToken); - - // Save the changes - await this.ConfigurationDbContext.SaveChangesAsync(cancellationToken); - - return Result.Success(); - } - - public async Task> Handle(SecurityServiceQueries.GetClientQuery query, CancellationToken cancellationToken){ - Client clientModel = null; - - Duende.IdentityServer.EntityFramework.Entities.Client clientEntity = await this.ConfigurationDbContext.Clients.Include(c => c.AllowedGrantTypes) - .Include(c => c.AllowedScopes).Where(c => c.ClientId == query.ClientId) - .SingleOrDefaultAsync(cancellationToken: cancellationToken); - - if (clientEntity == null) - { - return Result.NotFound($"No client found with Client Id [{query.ClientId}]"); - } - - clientModel = clientEntity.ToModel(); - - return Result.Success(clientModel); - } - - public async Task>> Handle(SecurityServiceQueries.GetClientsQuery query, CancellationToken cancellationToken){ - List clientModels = new List(); - - List clientEntities = await this.ConfigurationDbContext.Clients.Include(c => c.AllowedGrantTypes) - .Include(c => c.AllowedScopes) - .ToListAsync(cancellationToken: cancellationToken); - - if (clientEntities.Any()) - { - foreach (Duende.IdentityServer.EntityFramework.Entities.Client clientEntity in clientEntities) - { - clientModels.Add(clientEntity.ToModel()); - } - } - - return Result.Success(clientModels); - } - - private Result ValidateGrantTypes(List allowedGrantTypes){ - // Get a list of valid grant types - List validTypesList = new List(); - - validTypesList.Add(GrantType.AuthorizationCode); - validTypesList.Add(GrantType.ClientCredentials); - validTypesList.Add(GrantType.DeviceFlow); - validTypesList.Add(GrantType.Hybrid); - validTypesList.Add(GrantType.Implicit); - validTypesList.Add(GrantType.ResourceOwnerPassword); - - List invalidGrantTypes = allowedGrantTypes.Where(a => validTypesList.All(v => v != a)).ToList(); - - if (invalidGrantTypes.Any()){ - return Result.Invalid($"The grant types [{String.Join(", ", invalidGrantTypes)}] are not valid to create a new client"); - } - return Result.Success(); - } - } -} diff --git a/archive/SecurityService.BusinessLogic/RequestHandlers/IdentityResourceRequestHandler.cs b/archive/SecurityService.BusinessLogic/RequestHandlers/IdentityResourceRequestHandler.cs deleted file mode 100644 index 171d97cd..00000000 --- a/archive/SecurityService.BusinessLogic/RequestHandlers/IdentityResourceRequestHandler.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using SecurityService.DataTransferObjects.Requests; -using SimpleResults; - -namespace SecurityService.BusinessLogic.RequestHandlers -{ - using System.Security.Claims; - using System.Threading; - using Duende.IdentityServer.EntityFramework.DbContexts; - using Duende.IdentityServer.EntityFramework.Mappers; - using Duende.IdentityServer.Models; - using MediatR; - using Microsoft.EntityFrameworkCore; - using Requests; - using Shared.Exceptions; - - public class IdentityResourceRequestHandler : IRequestHandler, - IRequestHandler>, - IRequestHandler>>{ - private readonly ConfigurationDbContext ConfigurationDbContext; - - public IdentityResourceRequestHandler(ConfigurationDbContext configurationDbContext){ - this.ConfigurationDbContext = configurationDbContext; - } - - public async Task Handle(SecurityServiceCommands.CreateIdentityResourceCommand command, CancellationToken cancellationToken){ - IdentityResource identityResource = new IdentityResource(command.Name, command.DisplayName, command.Claims); - identityResource.Emphasize = command.Emphasize; - identityResource.Required = command.Required; - identityResource.ShowInDiscoveryDocument = command.ShowInDiscoveryDocument; - identityResource.Description = command.Description; - - // Now translate the model to the entity - await this.ConfigurationDbContext.IdentityResources.AddAsync(identityResource.ToEntity(), cancellationToken); - - // Save the changes - await this.ConfigurationDbContext.SaveChangesAsync(cancellationToken); - - return Result.Success(); - } - - public async Task> Handle(SecurityServiceQueries.GetIdentityResourceQuery query, CancellationToken cancellationToken){ - IdentityResource identityResourceModel = null; - - Duende.IdentityServer.EntityFramework.Entities.IdentityResource identityResourceEntity = await this.ConfigurationDbContext.IdentityResources - .Where(a => a.Name == query.IdentityResourceName) - .Include(a => a.UserClaims) - .SingleOrDefaultAsync(cancellationToken: cancellationToken); - - if (identityResourceEntity == null) - { - return Result.NotFound($"No Identity Resource found with Name [{query.IdentityResourceName}]"); - } - - identityResourceModel = identityResourceEntity.ToModel(); - - return Result.Success(identityResourceModel); - } - - public async Task>> Handle(SecurityServiceQueries.GetIdentityResourcesQuery query, CancellationToken cancellationToken){ - List identityResourceModels = new List(); - - List identityResourceEntities = - await this.ConfigurationDbContext.IdentityResources.Include(a => a.UserClaims).ToListAsync(cancellationToken: cancellationToken); - - if (identityResourceEntities.Any()) - { - foreach (Duende.IdentityServer.EntityFramework.Entities.IdentityResource identityResourceEntity in identityResourceEntities) - { - identityResourceModels.Add(identityResourceEntity.ToModel()); - } - } - - return Result.Success(identityResourceModels); - } - } -} diff --git a/archive/SecurityService.BusinessLogic/RequestHandlers/RoleRequestHandler.cs b/archive/SecurityService.BusinessLogic/RequestHandlers/RoleRequestHandler.cs deleted file mode 100644 index a1152f9c..00000000 --- a/archive/SecurityService.BusinessLogic/RequestHandlers/RoleRequestHandler.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using SecurityService.DataTransferObjects.Requests; -using SimpleResults; - -namespace SecurityService.BusinessLogic.RequestHandlers -{ - using System.Threading; - using Exceptions; - using MediatR; - using Microsoft.AspNetCore.Identity; - using Models; - using Requests; - using Shared.Exceptions; - - public class RoleRequestHandler : IRequestHandler, - IRequestHandler>, - IRequestHandler>>{ - private readonly RoleManager RoleManager; - - public RoleRequestHandler(RoleManager roleManager){ - this.RoleManager = roleManager; - } - public async Task Handle(SecurityServiceCommands.CreateRoleCommand command, CancellationToken cancellationToken){ - - IdentityRole newIdentityRole = new IdentityRole - { - Id = command.RoleId.ToString(), - Name = command.Name, - NormalizedName = command.Name.ToUpper() - }; - - // Ensure role name is not a duplicate - if (await this.RoleManager.RoleExistsAsync(newIdentityRole.Name)) - { - return Result.Conflict($"Role {newIdentityRole.Name} already exists"); - } - - IdentityResult createResult = await this.RoleManager.CreateAsync(newIdentityRole); - - if (!createResult.Succeeded) - { - return Result.Failure($"Error creating role {newIdentityRole.Name} {createResult}"); - } - return Result.Success(); - } - - public async Task> Handle(SecurityServiceQueries.GetRoleQuery query, CancellationToken cancellationToken){ - IdentityRole identityRole = await this.RoleManager.FindByIdAsync(query.RoleId.ToString()); - - if (identityRole == null) - { - return Result.NotFound($"No role found with Id {query.RoleId}"); - } - - // Role has been found - RoleDetails response = new RoleDetails - { - RoleId = Guid.Parse(identityRole.Id), - RoleName = identityRole.Name - }; - - return Result.Success(response); - } - - public async Task>> Handle(SecurityServiceQueries.GetRolesQuery query, CancellationToken cancellationToken){ - List response = new List(); - - IQueryable roleQuery = this.RoleManager.Roles; - - List roles = await roleQuery.ToListAsyncSafe(cancellationToken); - - foreach (IdentityRole identityRole in roles) - { - response.Add(new RoleDetails - { - RoleId = Guid.Parse(identityRole.Id), - RoleName = identityRole.Name - }); - } - - return Result.Success(response); - } - } -} diff --git a/archive/SecurityService.BusinessLogic/RequestHandlers/UserRequestHandler.cs b/archive/SecurityService.BusinessLogic/RequestHandlers/UserRequestHandler.cs deleted file mode 100644 index d48c2aa7..00000000 --- a/archive/SecurityService.BusinessLogic/RequestHandlers/UserRequestHandler.cs +++ /dev/null @@ -1,611 +0,0 @@ -using Duende.IdentityModel; -using Shared.Results; - -namespace SecurityService.BusinessLogic.RequestHandlers{ - using DataTransferObjects.Responses; - using Duende.IdentityServer; - using Duende.IdentityServer.EntityFramework.DbContexts; - using Duende.IdentityServer.EntityFramework.Entities; - using MediatR; - using MessagingService.Client; - using MessagingService.DataTransferObjects; - using Microsoft.AspNetCore.Identity; - using Microsoft.AspNetCore.Mvc; - using Microsoft.EntityFrameworkCore; - using Requests; - using SecurityService.Models; - using Shared.Logger; - using SimpleResults; - using System; - using System.Collections.Generic; - using System.Linq; - using System.Security.Claims; - using System.Security.Cryptography; - using System.Text; - using System.Text.Encodings.Web; - using System.Threading; - using System.Threading.Tasks; - using UserDetails = Models.UserDetails; - - public class UserRequestHandler : IRequestHandler, - IRequestHandler>, - IRequestHandler>>, - IRequestHandler>, - IRequestHandler, - IRequestHandler>, - IRequestHandler, - IRequestHandler { - #region Fields - - private readonly ConfigurationDbContext ConfigurationDbContext; - - private readonly IdentityServerTools IdentityServerTools; - - private readonly IMessagingServiceClient MessagingServiceClient; - - private readonly IPasswordHasher PasswordHasher; - - private readonly ServiceOptions ServiceOptions; - - private TokenResponse TokenResponse; - - private readonly UserManager UserManager; - - #endregion - - #region Constructors - - public UserRequestHandler(IPasswordHasher passwordHasher, - UserManager userManager, - ServiceOptions serviceOptions, - IMessagingServiceClient messagingServiceClient, - IdentityServerTools identityServerTools, - ConfigurationDbContext configurationDbContext){ - this.PasswordHasher = passwordHasher; - this.UserManager = userManager; - this.ServiceOptions = serviceOptions; - this.MessagingServiceClient = messagingServiceClient; - this.IdentityServerTools = identityServerTools; - this.ConfigurationDbContext = configurationDbContext; - } - - #endregion - - #region Methods - - public async Task Handle(SecurityServiceCommands.CreateUserCommand command, - CancellationToken cancellationToken) { - // request is valid now add the user - ApplicationUser newIdentityUser = new() { - Id = command.UserId.ToString(), - Email = command.EmailAddress, - UserName = command.UserName, - NormalizedEmail = command.EmailAddress.ToUpper(), - NormalizedUserName = command.UserName.ToUpper(), - SecurityStamp = Guid.NewGuid().ToString("D"), - PhoneNumber = command.PhoneNumber, - RegistrationDateTime = DateTime.Now - }; - - Result passwordValueResult = String.IsNullOrEmpty(command.Password) ? PasswordGenerator.GenerateRandomPassword(this.UserManager.Options.Password) : command.Password; - - if (passwordValueResult.IsFailed) - return ResultHelpers.CreateFailure(passwordValueResult); - - // Hash the default password - newIdentityUser.PasswordHash = this.PasswordHasher.HashPassword(newIdentityUser, passwordValueResult.Data); - - if (String.IsNullOrEmpty(newIdentityUser.PasswordHash)) { - return Result.Failure("Error generating password hash value, hash was null or empty"); - } - - // Create the User - Result createResult = await this.CreateUser(newIdentityUser); - Result addRolesToUserResult = await this.AddRolesToUser(newIdentityUser, command.Roles); - Result addClaimsToUserResult = await this.AddClaimsToUser(newIdentityUser, command); - - Result result = (createResult.IsSuccess, addRolesToUserResult.IsSuccess, addClaimsToUserResult.IsSuccess) switch - { - (true, true, true) => await SendConfirmationEmail(newIdentityUser, cancellationToken), - _ => await DeleteUser(createResult, addRolesToUserResult,addClaimsToUserResult, newIdentityUser) - }; - return result; - } - - private async Task SendConfirmationEmail(ApplicationUser newIdentityUser, CancellationToken cancellationToken) { - // If we are here we have created the user - String confirmationToken = await this.UserManager.GenerateEmailConfirmationTokenAsync(newIdentityUser); - confirmationToken = UrlEncoder.Default.Encode(confirmationToken); - String uri = $"{this.ServiceOptions.PublicOrigin}/Account/EmailConfirmation/Confirm?userName={newIdentityUser.UserName}&confirmationToken={confirmationToken}"; - - TokenResponse token = await this.GetToken(); - SendEmailRequest emailRequest = this.BuildEmailConfirmationRequest(newIdentityUser, uri); - Result sendEmailResult = await this.MessagingServiceClient.SendEmail(token.AccessToken, emailRequest, cancellationToken); - if (sendEmailResult.IsFailed) - Logger.LogWarning($"Error sending email to {newIdentityUser.Email} as part of user creation {sendEmailResult}"); - return Result.Success(); - } - - private async Task DeleteUser(Result createResult, Result addRolesToUserResult, Result addClaimsToUserResult , ApplicationUser identityUserToDelete) { - // User has been created so need to remove this - IdentityResult deleteResult = await this.UserManager.DeleteAsync(identityUserToDelete); - - if (deleteResult.Succeeded == false) { - return Result.Failure($"Error deleting user {identityUserToDelete.UserName} as part of cleanup {deleteResult}"); - } - - return Result.Failure($"At least one part of the user creation failed - createResult: {createResult.IsSuccess} addRolesToUserResult: {addRolesToUserResult.IsSuccess} addClaimsToUserResult: {addClaimsToUserResult.IsSuccess}"); - } - - - private async Task CreateUser(ApplicationUser newIdentityUser) { - var createResult = await this.UserManager.CreateAsync(newIdentityUser); - - if (!createResult.Succeeded) - { - return Result.Failure($"Error creating user {newIdentityUser.UserName} {createResult}"); - } - return Result.Success(); - } - - private async Task AddRolesToUser(ApplicationUser newIdentityUser, List roles) { - // Add the requested roles to the user - if (roles != null && roles.Any()) - { - IdentityResult addRolesResult = await this.UserManager.AddToRolesAsync(newIdentityUser, roles); - - if (!addRolesResult.Succeeded) - { - return Result.Failure($"Error adding roles [{String.Join(",", roles)}] to user {newIdentityUser.UserName} {addRolesResult}"); - } - } - - return Result.Success(); - } - - private async Task AddClaimsToUser(ApplicationUser newIdentityUser, SecurityServiceCommands.CreateUserCommand command) { - // Add the requested claims - List claimsToAdd = new List(); - if (command.Claims != null) - { - foreach (KeyValuePair claim in command.Claims) - { - claimsToAdd.Add(new Claim(claim.Key, claim.Value)); - } - } - - // Add the email address and role as claims - if (command.Roles != null) - { - foreach (String requestRole in command.Roles) - { - claimsToAdd.Add(new Claim(JwtClaimTypes.Role, requestRole)); - } - } - - claimsToAdd.Add(new Claim(JwtClaimTypes.Email, command.EmailAddress)); - claimsToAdd.Add(new Claim(JwtClaimTypes.GivenName, command.GivenName)); - claimsToAdd.Add(new Claim(JwtClaimTypes.FamilyName, command.FamilyName)); - - if (String.IsNullOrEmpty(command.MiddleName) == false) - { - claimsToAdd.Add(new Claim(JwtClaimTypes.MiddleName, command.MiddleName)); - } - - var addClaimsResult = await this.UserManager.AddClaimsAsync(newIdentityUser, claimsToAdd); - - if (!addClaimsResult.Succeeded) - { - List claimList = new List(); - claimsToAdd.ForEach(c => claimList.Add($"Name: {c.Type} Value: {c.Value}")); - return Result.Failure($"Error adding claims [{String.Join(",", claimsToAdd)}] to user {newIdentityUser.UserName} {addClaimsResult}"); - } - - return Result.Success(); - } - - public async Task> Handle(SecurityServiceQueries.GetUserQuery query, CancellationToken cancellationToken){ - - ApplicationUser user = await this.UserManager.FindByIdAsync(query.UserId.ToString()); - - if (user == null){ - return Result.NotFound($"No user found with user Id {query.UserId}"); - } - - UserDetails response = new UserDetails(); - response.Email = user.Email; - response.PhoneNumber = user.PhoneNumber; - response.UserId = query.UserId; - response.SubjectId = query.UserId.ToString(); - response.Username = user.UserName; - response.RegistrationDateTime = user.RegistrationDateTime; - - // Get the users roles - response.Roles = await this.ConvertUsersRoles(user); - - // Get the users claims - response.Claims = await this.ConvertUsersClaims(user); - - return Result.Success(response); - } - - public async Task>> Handle(SecurityServiceQueries.GetUsersQuery query, CancellationToken cancellationToken){ - List response = new List(); - - IQueryable userQuery = this.UserManager.Users; - - if (String.IsNullOrEmpty(query.UserName) == false){ - userQuery = userQuery.Where(u => u.UserName.Contains(query.UserName)); - } - - List users = await userQuery.ToListAsyncSafe(cancellationToken); - - foreach (ApplicationUser identityUser in users){ - Dictionary claims = await this.ConvertUsersClaims(identityUser); - List roles = await this.ConvertUsersRoles(identityUser); - - response.Add(new UserDetails{ - UserId = Guid.Parse(identityUser.Id), - SubjectId = identityUser.Id, - Username = identityUser.UserName, - Claims = claims, - Email = identityUser.Email, - PhoneNumber = identityUser.PhoneNumber, - Roles = roles - }); - } - - return Result.Success(response); - } - - public async Task> Handle(SecurityServiceCommands.ChangeUserPasswordCommand command, CancellationToken cancellationToken){ - - //Logger.LogWarning("In Handle ChangeUserPasswordCommand"); - // Find the user based on the user name passed in - ApplicationUser user = await this.UserManager.FindByNameAsync(command.UserName); - - if (user == null){ - //Logger.LogWarning("In Handle ChangeUserPasswordCommand - user is null"); - // this prevents giving away info to a potential hacker... - return Result.NotFound(); - } - //Logger.LogWarning("In Handle ChangeUserPasswordCommand - user is not null"); - IdentityResult result = await this.UserManager.ChangePasswordAsync(user, - command.CurrentPassword, - command.NewPassword); - - if (result.Succeeded == false){ - // Log any errors - Logger.LogInformation($"Errors during password change for user [{command.UserName} and Client [{command.ClientId}]"); - foreach (IdentityError identityError in result.Errors){ - Logger.LogInformation($"Code {identityError.Code} Description {identityError.Description}"); - } - - return Result.Failure($"Errors during password change for user [{command.UserName} and Client [{command.ClientId}]"); - } - - //Logger.LogWarning("In Handle ChangeUserPasswordCommand - password changed"); - // build the redirect uri - Client client = await this.ConfigurationDbContext.Clients.SingleOrDefaultAsync(c => c.ClientId == command.ClientId, cancellationToken:cancellationToken); - - if (client == null){ - //Logger.LogWarning("In Handle ChangeUserPasswordCommand - client not found"); - Logger.LogInformation($"Client not found for clientId {command.ClientId}"); - return Result.Invalid($"Client not found for clientId {command.ClientId}"); - } - - Logger.LogWarning($"Client uri: {client.ClientUri}"); - return Result.Success(new ChangeUserPasswordResult { IsSuccessful = true, RedirectUri = client.ClientUri}); - } - - public async Task Handle(SecurityServiceCommands.ConfirmUserEmailAddressCommand command, CancellationToken cancellationToken){ - ApplicationUser identityUser = await this.UserManager.FindByNameAsync(command.UserName); - - if (identityUser == null) - { - Logger.LogInformation($"No user found with username {command.UserName}"); - return Result.NotFound($"No user found with username {command.UserName}"); - } - - IdentityResult result = await this.UserManager.ConfirmEmailAsync(identityUser, command.ConfirmEmailToken); - - if (result.Succeeded == false) - { - Logger.LogInformation($"Errors during confirm email for user [{command.UserName}"); - foreach (IdentityError identityError in result.Errors) - { - Logger.LogInformation($"Code {identityError.Code} Description {identityError.Description}"); - } - return Result.Failure($"Errors during confirm email for user [{command.UserName}"); - } - - return Result.Success(); - } - - public async Task> Handle(SecurityServiceCommands.ProcessPasswordResetConfirmationCommand command, CancellationToken cancellationToken){ - // Find the user based on the user name passed in - ApplicationUser user = await this.UserManager.FindByNameAsync(command.Username); - - if (user == null) - { - // this prevents giving away info to a potential hacker... - Logger.LogInformation($"user not found for username {command.Username}"); - return Result.NotFound($"user not found for username {command.Username}"); - } - - IdentityResult result = await this.UserManager.ResetPasswordAsync(user, command.Token, command.Password); - - // handle the result... - if (result.Succeeded == false) - { - // Log any errors - Logger.LogInformation($"Errors during password reset for user [{command.Username} and Client [{command.ClientId}]"); - foreach (IdentityError identityError in result.Errors) - { - Logger.LogInformation($"Code {identityError.Code} Description {identityError.Description}"); - } - - return Result.Failure($"Errors during password reset for user [{command.Username} and Client [{command.ClientId}]"); - } - - // build the redirect uri - Client client = await this.ConfigurationDbContext.Clients.SingleOrDefaultAsync(c => c.ClientId == command.ClientId, cancellationToken: cancellationToken); - - if (client == null) - { - Logger.LogInformation($"Client not found for clientId {command.ClientId}"); - return Result.Invalid($"Client not found for clientId {command.ClientId}"); - } - - return Result.Success(client.ClientUri); - } - - public async Task Handle(SecurityServiceCommands.ProcessPasswordResetRequestCommand command, CancellationToken cancellationToken){ - // Find the user based on the user name passed in - ApplicationUser user = await this.UserManager.FindByNameAsync(command.Username); - - if (user == null) - { - // this prevents giving away info to a potential hacker... - return Result.NotFound(); - } - - // User has been found so send an email with reset details - String resetToken = await this.UserManager.GeneratePasswordResetTokenAsync(user); - resetToken = UrlEncoder.Default.Encode(resetToken); - String uri = $"{this.ServiceOptions.PublicOrigin}/Account/ForgotPassword/Confirm?userName={user.UserName}&resetToken={resetToken}&clientId={command.ClientId}"; - - TokenResponse token = await this.GetToken(); - SendEmailRequest emailRequest = this.BuildPasswordResetEmailRequest(user, uri); - - Result result = await this.MessagingServiceClient.SendEmail(token.AccessToken, emailRequest, cancellationToken); - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(); - } - - public async Task Handle(SecurityServiceCommands.SendWelcomeEmailCommand command, CancellationToken cancellationToken){ - ApplicationUser i = await this.UserManager.FindByNameAsync(command.Username); - await this.UserManager.RemovePasswordAsync(i); - Result generatedPasswordResult = PasswordGenerator.GenerateRandomPassword(this.UserManager.Options.Password); - if (generatedPasswordResult.IsFailed) - return ResultHelpers.CreateFailure(generatedPasswordResult); - await this.UserManager.AddPasswordAsync(i, generatedPasswordResult.Data); - - // Send Email - TokenResponse token = await this.GetToken(); - SendEmailRequest emailRequest = this.BuildWelcomeEmail(i.Email, generatedPasswordResult.Data); - Result result = await this.MessagingServiceClient.SendEmail(token.AccessToken, emailRequest, cancellationToken); - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(); - } - - private SendEmailRequest BuildEmailConfirmationRequest(ApplicationUser user, - String emailConfirmationToken){ - StringBuilder mesasgeBuilder = new StringBuilder(); - - mesasgeBuilder.Append(""); - mesasgeBuilder.Append(""); - mesasgeBuilder.Append("

Thank you for registering

"); - mesasgeBuilder.Append("

"); - mesasgeBuilder.Append($"

Please click here to confirm your email address.

"); - mesasgeBuilder.Append("

Thanks for your registration.

"); - mesasgeBuilder.Append(""); - mesasgeBuilder.Append(""); - - SendEmailRequest request = new(){ - Body = mesasgeBuilder.ToString(), - ConnectionIdentifier = Guid.NewGuid(), - FromAddress = "golfhandicapping@btinternet.com", - IsHtml = true, - Subject = "Email Address Confirmation", - ToAddresses = new List{ - user.Email, - "stuart_ferguson1@outlook.com" - } - }; - - return request; - } - - private SendEmailRequest BuildPasswordResetEmailRequest(ApplicationUser user, - String resetToken){ - StringBuilder mesasgeBuilder = new StringBuilder(); - - mesasgeBuilder.Append(""); - mesasgeBuilder.Append(""); - mesasgeBuilder.Append("

Thanks for your password reset request

"); - mesasgeBuilder.Append("

"); - mesasgeBuilder.Append($"

Please click here to confirm this password reset was from you.

"); - mesasgeBuilder.Append("

Thanks for your password reset request.

"); - mesasgeBuilder.Append(""); - mesasgeBuilder.Append(""); - - SendEmailRequest request = new(){ - Body = mesasgeBuilder.ToString(), - ConnectionIdentifier = Guid.NewGuid(), - FromAddress = "golfhandicapping@btinternet.com", - IsHtml = true, - Subject = "Password Reset Requested", - ToAddresses = new List{ - user.Email, - "stuart_ferguson1@outlook.com" - } - }; - - return request; - } - - private SendEmailRequest BuildWelcomeEmail(String emailAddress, - String password){ - StringBuilder mesasgeBuilder = new StringBuilder(); - mesasgeBuilder.AppendLine(""); - mesasgeBuilder.AppendLine("

Welcome to Transaction Processing System

"); - mesasgeBuilder.AppendLine("

"); - mesasgeBuilder.AppendLine("

Please find below your user details:

"); - mesasgeBuilder.AppendLine(""); - mesasgeBuilder.AppendLine(""); - mesasgeBuilder.AppendLine($""); - mesasgeBuilder.AppendLine(""); - mesasgeBuilder.AppendLine($""); - mesasgeBuilder.AppendLine("
User Name
{emailAddress}
Password
{password}
"); - mesasgeBuilder.AppendLine(""); - - SendEmailRequest request = new(){ - Body = mesasgeBuilder.ToString(), - ConnectionIdentifier = Guid.NewGuid(), - FromAddress = "golfhandicapping@btinternet.com", - IsHtml = true, - Subject = "Welcome to Transaction Processing", - ToAddresses = new List{ - emailAddress, - "stuart_ferguson1@outlook.com" - } - }; - - return request; - } - - private async Task> ConvertUsersClaims(ApplicationUser identityUser){ - Dictionary response = new Dictionary(); - IList claims = await this.UserManager.GetClaimsAsync(identityUser); - foreach (Claim claim in claims){ - response.Add(claim.Type, claim.Value); - } - - return response; - } - - private async Task> ConvertUsersRoles(ApplicationUser identityUser){ - IList roles = await this.UserManager.GetRolesAsync(identityUser); - return roles.ToList(); - } - - private async Task GetToken(){ - // Get a token to talk to the estate service - String clientId = this.ServiceOptions.ClientId; - String clientSecret = this.ServiceOptions.ClientSecret; - - Logger.LogInformation($"Client Id is {clientId}"); - Logger.LogInformation($"Client Secret is {clientSecret}"); - - if (this.TokenResponse == null){ - String clientToken = await this.IdentityServerTools.IssueClientJwtAsync(clientId, 3600); - this.TokenResponse = TokenResponse.Create(clientToken, null, 3600, DateTimeOffset.Now, DateTimeOffset.Now.AddSeconds(3600)); - Logger.LogInformation($"Token is {this.TokenResponse.AccessToken}"); - return this.TokenResponse; - } - - if (this.TokenResponse.Expires.UtcDateTime.Subtract(DateTime.UtcNow) < TimeSpan.FromMinutes(2)){ - Logger.LogInformation($"Token is about to expire at {this.TokenResponse.Expires.DateTime:O}"); - Logger.LogInformation($"Token is {this.TokenResponse.AccessToken}"); - return this.TokenResponse; - } - - return this.TokenResponse; - } - - #endregion - } - - -public static class PasswordGenerator - { - public static Result GenerateRandomPassword(PasswordOptions? opts = null) - { - opts ??= DefaultOptions(); - - var categories = BuildCategories(opts); - var result = ValidateUniqueCharRequirement(opts, categories); - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - var chars = new List(); - - AddRequiredCategoryChars(chars, categories); - FillRemainingChars(chars, opts, categories); - SecureShuffle(chars); - - return Result.Success(new string(chars.ToArray())); - } - - private static PasswordOptions DefaultOptions() => new() - { - RequiredLength = 8, - RequiredUniqueChars = 4, - RequireDigit = true, - RequireLowercase = true, - RequireNonAlphanumeric = true, - RequireUppercase = true - }; - - private static List BuildCategories(PasswordOptions opts) - { - var list = new List(); - if (opts.RequireUppercase) list.Add("ABCDEFGHJKLMNOPQRSTUVWXYZ"); - if (opts.RequireLowercase) list.Add("abcdefghijkmnopqrstuvwxyz"); - if (opts.RequireDigit) list.Add("0123456789"); - if (opts.RequireNonAlphanumeric) list.Add("!@$?_-"); - if (!list.Any()) list.Add("abcdefghijkmnopqrstuvwxyz0123456789"); - return list; - } - - private static Result ValidateUniqueCharRequirement(PasswordOptions opts, List categories) - { - var all = string.Concat(categories).Distinct().Count(); - if (opts.RequiredUniqueChars > all) - return Result.Failure($"RequiredUniqueChars ({opts.RequiredUniqueChars}) exceeds available unique characters ({all})."); - - return Result.Success(); - } - - private static void AddRequiredCategoryChars(List chars, List categories) - { - foreach (var cat in categories) - chars.Add(cat[RandomNumberGenerator.GetInt32(cat.Length)]); - } - - private static void FillRemainingChars(List chars, PasswordOptions opts, List categories) - { - while (chars.Count < opts.RequiredLength || chars.Distinct().Count() < opts.RequiredUniqueChars) - { - var set = categories[RandomNumberGenerator.GetInt32(categories.Count)]; - chars.Add(set[RandomNumberGenerator.GetInt32(set.Length)]); - } - } - - private static void SecureShuffle(List chars) - { - for (int i = chars.Count - 1; i > 0; i--) - { - int j = RandomNumberGenerator.GetInt32(i + 1); - (chars[i], chars[j]) = (chars[j], chars[i]); - } - } - } - -} - diff --git a/archive/SecurityService.BusinessLogic/Requests/SecurityServiceCommands.cs b/archive/SecurityService.BusinessLogic/Requests/SecurityServiceCommands.cs deleted file mode 100644 index 4e3cd12a..00000000 --- a/archive/SecurityService.BusinessLogic/Requests/SecurityServiceCommands.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Collections.Generic; -using MediatR; -using SecurityService.Models; -using SimpleResults; - -namespace SecurityService.BusinessLogic.Requests; - -public record SecurityServiceCommands { - public record CreateApiResourceCommand(string Name, string DisplayName, string Description, string Secret, List Scopes, List UserClaims) : IRequest; - public record ChangeUserPasswordCommand(String UserName, - String CurrentPassword, - String NewPassword, - String ClientId) : IRequest>; - - public record ConfirmUserEmailAddressCommand(String UserName, String ConfirmEmailToken) : IRequest; - - public record CreateApiScopeCommand(String Name, String DisplayName, String Description) : IRequest; - - public record CreateClientCommand(String ClientId, - String Secret, - String ClientName, - String ClientDescription, - List AllowedScopes, - List AllowedGrantTypes, - String ClientUri, - List ClientRedirectUris, - List ClientPostLogoutRedirectUris, - Boolean RequireConsent, - Boolean AllowOfflineAccess) : IRequest; - - public record CreateIdentityResourceCommand(String Name, - String DisplayName, - String Description, - Boolean Required, - Boolean Emphasize, - Boolean ShowInDiscoveryDocument, - List Claims) : IRequest; - - public record CreateRoleCommand(Guid RoleId, String Name) : IRequest; - - public record CreateUserCommand(Guid UserId, - String GivenName, - String MiddleName, - String FamilyName, - String UserName, - String Password, - String EmailAddress, - String PhoneNumber, - Dictionary Claims, - List Roles) : IRequest; - - public record ProcessPasswordResetConfirmationCommand(String Username, - String Token, - String Password, - String ClientId) : IRequest>; - - public record ProcessPasswordResetRequestCommand(String Username, - String EmailAddress, - String ClientId) : IRequest; - - public record SendWelcomeEmailCommand(String Username) : IRequest; - -} \ No newline at end of file diff --git a/archive/SecurityService.BusinessLogic/Requests/SecurityServiceQueries.cs b/archive/SecurityService.BusinessLogic/Requests/SecurityServiceQueries.cs deleted file mode 100644 index ade0fcda..00000000 --- a/archive/SecurityService.BusinessLogic/Requests/SecurityServiceQueries.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; -using Duende.IdentityServer.Models; -using MediatR; -using SecurityService.Models; -using SimpleResults; - -namespace SecurityService.BusinessLogic.Requests; - -public record SecurityServiceQueries { - public record GetApiResourceQuery(string Name) : IRequest>; - public record GetApiResourcesQuery() : IRequest>>; - - public record GetApiScopeQuery(string Name) : IRequest>; - - public record GetApiScopesQuery() : IRequest>>; - - public record GetClientQuery(String ClientId) :IRequest>; - public record GetClientsQuery() : IRequest>>; - - public record GetRoleQuery(Guid RoleId) : IRequest>; - public record GetRolesQuery() : IRequest>>; - - public record GetIdentityResourceQuery(String IdentityResourceName) : IRequest>; - public record GetIdentityResourcesQuery() : IRequest>>; - - public record GetUserQuery(Guid UserId) : IRequest>; - public record GetUsersQuery(String UserName) : IRequest>>; -} \ No newline at end of file diff --git a/archive/SecurityService.BusinessLogic/SecurityService.BusinessLogic.csproj b/archive/SecurityService.BusinessLogic/SecurityService.BusinessLogic.csproj deleted file mode 100644 index d36aee54..00000000 --- a/archive/SecurityService.BusinessLogic/SecurityService.BusinessLogic.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - net10.0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/archive/SecurityService.BusinessLogic/ServiceOptions.cs b/archive/SecurityService.BusinessLogic/ServiceOptions.cs deleted file mode 100644 index cfc3868e..00000000 --- a/archive/SecurityService.BusinessLogic/ServiceOptions.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace SecurityService.BusinessLogic; - -using System; - -public class ServiceOptions -{ - public ServiceOptions() { - this.PasswordOptions = new PasswordOptions(); - this.TokenOptions = new TokenOptions(); - this.SignInOptions = new SignInOptions(); - this.UserOptions = new UserOptions(); - } - - #region Properties - - public String ClientId { get; set; } - - public String ClientSecret { get; set; } - - public String IssuerUrl { get; set; } - - public PasswordOptions PasswordOptions { get; set; } - - public String PublicOrigin { get; set; } - - public SignInOptions SignInOptions { get; set; } - - public TokenOptions TokenOptions { get; set; } - - public Boolean UseInMemoryDatabase { get; set; } - - public UserOptions UserOptions { get; set; } - - #endregion -} \ No newline at end of file diff --git a/archive/SecurityService.BusinessLogic/SignInOptions.cs b/archive/SecurityService.BusinessLogic/SignInOptions.cs deleted file mode 100644 index 4d6239c4..00000000 --- a/archive/SecurityService.BusinessLogic/SignInOptions.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace SecurityService.BusinessLogic; - -using System; - -public class SignInOptions -{ - #region Properties - - public Boolean RequireConfirmedEmail { get; set; } - - #endregion -} \ No newline at end of file diff --git a/archive/SecurityService.BusinessLogic/TestMessagingServiceClient.cs b/archive/SecurityService.BusinessLogic/TestMessagingServiceClient.cs deleted file mode 100644 index 34c46632..00000000 --- a/archive/SecurityService.BusinessLogic/TestMessagingServiceClient.cs +++ /dev/null @@ -1,35 +0,0 @@ -using SimpleResults; - -namespace SecurityService.BusinessLogic; - -using System; -using System.Diagnostics.CodeAnalysis; -using System.Threading; -using System.Threading.Tasks; -using MessagingService.Client; -using MessagingService.DataTransferObjects; -using Shared.Logger; - -[ExcludeFromCodeCoverage] -public class TestMessagingServiceClient : IMessagingServiceClient -{ - public SendEmailRequest LastEmailRequest { get; private set; } - public SendSMSRequest LastSMSRequest { get; private set; } - - public async Task ResendEmail(string accessToken, ResendEmailRequest request, CancellationToken cancellationToken) => Result.Success(); - - public async Task SendEmail(String accessToken, - SendEmailRequest request, - CancellationToken cancellationToken) { - Logger.LogWarning($"Sending Email {request.Subject}"); - this.LastEmailRequest = request; - return Result.Success(); - } - - public async Task SendSMS(String accessToken, - SendSMSRequest request, - CancellationToken cancellationToken) { - this.LastSMSRequest = request; - return Result.Success(); - } -} \ No newline at end of file diff --git a/archive/SecurityService.BusinessLogic/TokenOptions.cs b/archive/SecurityService.BusinessLogic/TokenOptions.cs deleted file mode 100644 index babff1ab..00000000 --- a/archive/SecurityService.BusinessLogic/TokenOptions.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace SecurityService.BusinessLogic; - -using System; - -public class TokenOptions -{ - #region Properties - - public Int32 EmailConfirmationTokenExpiryInHours { get; set; } - - public Int32 PasswordResetTokenExpiryInHours { get; set; } - - #endregion -} \ No newline at end of file diff --git a/archive/SecurityService.BusinessLogic/UserOptions.cs b/archive/SecurityService.BusinessLogic/UserOptions.cs deleted file mode 100644 index 18b59153..00000000 --- a/archive/SecurityService.BusinessLogic/UserOptions.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace SecurityService.BusinessLogic; - -using System; - -public class UserOptions -{ - #region Properties - - public Boolean RequireUniqueEmail { get; set; } - - #endregion -} \ No newline at end of file diff --git a/archive/SecurityService.Client/ISecurityServiceClient.cs b/archive/SecurityService.Client/ISecurityServiceClient.cs deleted file mode 100644 index df89ad7b..00000000 --- a/archive/SecurityService.Client/ISecurityServiceClient.cs +++ /dev/null @@ -1,83 +0,0 @@ -using SimpleResults; - -namespace SecurityService.Client -{ - using System; - using System.Collections.Generic; - using System.Threading; - using System.Threading.Tasks; - using DataTransferObjects; - using DataTransferObjects.Requests; - using DataTransferObjects.Responses; - - /// - /// - /// - public interface ISecurityServiceClient - { - #region Methods - - Task CreateApiResource(CreateApiResourceRequest createApiResourceRequest, - CancellationToken cancellationToken); - Task CreateApiScope(CreateApiScopeRequest createApiScopeRequest, - CancellationToken cancellationToken); - - Task CreateClient(CreateClientRequest createClientRequest, - CancellationToken cancellationToken); - - Task CreateIdentityResource(CreateIdentityResourceRequest createIdentityResourceRequest, - CancellationToken cancellationToken); - Task CreateRole(CreateRoleRequest createRoleRequest, - CancellationToken cancellationToken); - - Task CreateUser(CreateUserRequest createUserRequest, - CancellationToken cancellationToken); - - Task> GetApiResource(String apiResourceName, - CancellationToken cancellationToken); - - Task> GetApiScope(String apiScopeName, - CancellationToken cancellationToken); - - Task>> GetApiResources(CancellationToken cancellationToken); - - Task>> GetApiScopes(CancellationToken cancellationToken); - - Task> GetClient(String clientId, - CancellationToken cancellationToken); - - Task>> GetClients(CancellationToken cancellationToken); - - Task> GetIdentityResource(String identityResourceName, - CancellationToken cancellationToken); - - Task>> GetIdentityResources(CancellationToken cancellationToken); - - Task> GetRole(Guid roleId, - CancellationToken cancellationToken); - - Task>> GetRoles(CancellationToken cancellationToken); - - Task> GetToken(String username, - String password, - String clientId, - String clientSecret, - CancellationToken cancellationToken); - - Task> GetToken(String clientId, - String clientSecret, - CancellationToken cancellationToken); - - Task> GetToken(String clientId, - String clientSecret, - String refreshToken, - CancellationToken cancellationToken); - - Task> GetUser(Guid userId, - CancellationToken cancellationToken); - Task>> GetUsers(String userName, - CancellationToken cancellationToken); - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.Client/SecurityService.Client.csproj b/archive/SecurityService.Client/SecurityService.Client.csproj deleted file mode 100644 index 4e05c275..00000000 --- a/archive/SecurityService.Client/SecurityService.Client.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - net10.0 - $(TargetsForTfmSpecificBuildOutput);IncludeP2PAssets - - - - - - - - - - - - - - - - - - diff --git a/archive/SecurityService.Client/SecurityServiceClient.cs b/archive/SecurityService.Client/SecurityServiceClient.cs deleted file mode 100644 index ed62e7bd..00000000 --- a/archive/SecurityService.Client/SecurityServiceClient.cs +++ /dev/null @@ -1,570 +0,0 @@ -using Shared.Results; -using SimpleResults; - -namespace SecurityService.Client -{ - using System; - using System.Collections.Generic; - using System.Net.Http; - using System.Text; - using System.Threading; - using System.Threading.Tasks; - using ClientProxyBase; - using DataTransferObjects; - using DataTransferObjects.Requests; - using DataTransferObjects.Responses; - using Newtonsoft.Json; - using static Shared.Results.ResultHelpers; - - /// - /// - /// - /// - /// - public class SecurityServiceClient : ClientProxyBase, ISecurityServiceClient - { - #region Fields - - /// - /// The base address - /// - private String BaseAddress; - - /// - /// The base address resolver - /// - private readonly Func BaseAddressResolver; - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The base address resolver. - /// The HTTP client. - public SecurityServiceClient(Func baseAddressResolver, - HttpClient httpClient) : base(httpClient) - { - this.BaseAddressResolver = baseAddressResolver; - this.BaseAddress = baseAddressResolver("SecurityService"); - - // Add the API version header - this.HttpClient.DefaultRequestHeaders.Add("api-version", "1.0"); - } - - #endregion - - #region Methods - - public async Task CreateApiResource(CreateApiResourceRequest createApiResourceRequest, - CancellationToken cancellationToken) - { - String requestUri = this.BuildRequestUrl("/api/apiresources"); - - try - { - Result result = await this.SendHttpPostRequest(requestUri, createApiResourceRequest, cancellationToken); - - if(result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(); - } - catch(Exception ex) - { - // An exception has occurred, add some additional information to the message - Exception exception = new Exception($"Error creating api resource {createApiResourceRequest.Name}.", ex); - - throw exception; - } - } - - public async Task CreateApiScope(CreateApiScopeRequest createApiScopeRequest, - CancellationToken cancellationToken) - { - String requestUri = this.BuildRequestUrl("/api/apiscopes"); - - try - { - Result result = await this.SendHttpPostRequest(requestUri, createApiScopeRequest, cancellationToken); - - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(); - } - catch(Exception ex) - { - // An exception has occurred, add some additional information to the message - Exception exception = new Exception($"Error creating api scope {createApiScopeRequest.Name}.", ex); - - throw exception; - } - } - - public async Task CreateClient(CreateClientRequest createClientRequest, - CancellationToken cancellationToken) - { - String requestUri = this.BuildRequestUrl("/api/clients"); - - try - { - Result result = await this.SendHttpPostRequest(requestUri, createClientRequest, cancellationToken); - - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(); - } - catch(Exception ex) - { - // An exception has occurred, add some additional information to the message - Exception exception = new Exception($"Error creating client {createClientRequest.ClientId}.", ex); - - throw exception; - } - } - - public async Task CreateIdentityResource(CreateIdentityResourceRequest createIdentityResourceRequest, - CancellationToken cancellationToken) - { - String requestUri = this.BuildRequestUrl("/api/identityresources"); - - try - { - Result result = await this.SendHttpPostRequest(requestUri, createIdentityResourceRequest, cancellationToken); - - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(); - } - catch(Exception ex) - { - // An exception has occurred, add some additional information to the message - Exception exception = new Exception($"Error creating identity resource {createIdentityResourceRequest.DisplayName}.", ex); - - throw exception; - } - } - - public async Task CreateRole(CreateRoleRequest createRoleRequest, - CancellationToken cancellationToken) - { - String requestUri = this.BuildRequestUrl("/api/roles"); - - try - { - Result result = await this.SendHttpPostRequest(requestUri, createRoleRequest, cancellationToken); - - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(); - } - catch(Exception ex) - { - // An exception has occurred, add some additional information to the message - Exception exception = new Exception($"Error creating role {createRoleRequest.RoleName}.", ex); - - throw exception; - } - } - - /// - /// Creates the user. - /// - /// The create user request. - /// The cancellation token. - /// - public async Task CreateUser(CreateUserRequest createUserRequest, - CancellationToken cancellationToken) - { - String requestUri = this.BuildRequestUrl("/api/users"); - - try - { - Result result = await this.SendHttpPostRequest(requestUri, createUserRequest, cancellationToken); - - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(); - } - catch(Exception ex) - { - // An exception has occurred, add some additional information to the message - Exception exception = new Exception($"Error creating user {createUserRequest.EmailAddress}.", ex); - - throw exception; - } - } - - public async Task> GetApiResource(String apiResourceName, - CancellationToken cancellationToken) - { - String requestUri = this.BuildRequestUrl($"/api/apiresources/{apiResourceName}"); - - try { - Result result = await this.SendHttpGetRequest(requestUri, cancellationToken); - - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(result.Data); - } - catch(Exception ex) - { - // An exception has occurred, add some additional information to the message - Exception exception = new Exception($"Error getting api resource {apiResourceName}.", ex); - - throw exception; - } - } - - public async Task>> GetApiResources(CancellationToken cancellationToken) - { - String requestUri = this.BuildRequestUrl("/api/apiresources"); - - try - { - Result> result = await this.SendHttpGetRequest>(requestUri, cancellationToken); - - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(result.Data); - } - catch(Exception ex) - { - // An exception has occurred, add some additional information to the message - Exception exception = new Exception("Error getting api resources.", ex); - - throw exception; - } - } - - public async Task> GetApiScope(String apiScopeName, - CancellationToken cancellationToken) - { - String requestUri = this.BuildRequestUrl($"/api/apiscopes/{apiScopeName}"); - - try - { - var result = await this.SendHttpGetRequest(requestUri, cancellationToken); - - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(result.Data); - } - catch(Exception ex) - { - // An exception has occurred, add some additional information to the message - Exception exception = new Exception($"Error getting api scope {apiScopeName}.", ex); - - throw exception; - } - } - - public async Task>> GetApiScopes(CancellationToken cancellationToken) - { - String requestUri = this.BuildRequestUrl("/api/apiscopes"); - - try - { - var result = await this.SendHttpGetRequest>(requestUri, cancellationToken); - - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(result.Data); - } - catch(Exception ex) - { - // An exception has occurred, add some additional information to the message - Exception exception = new Exception("Error getting api scopes.", ex); - - throw exception; - } - } - - public async Task> GetClient(String clientId, - CancellationToken cancellationToken) - { - String requestUri = this.BuildRequestUrl($"/api/clients/{clientId}"); - - try - { - var result = await this.SendHttpGetRequest(requestUri, cancellationToken); - - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(result.Data); - } - catch(Exception ex) - { - // An exception has occurred, add some additional information to the message - Exception exception = new Exception($"Error getting client {clientId}.", ex); - - throw exception; - } - } - - public async Task>> GetClients(CancellationToken cancellationToken) - { - String requestUri = this.BuildRequestUrl("/api/clients"); - - try - { - var result = await this.SendHttpGetRequest>(requestUri, cancellationToken); - - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(result.Data); - } - catch(Exception ex) - { - // An exception has occurred, add some additional information to the message - Exception exception = new Exception("Error getting clients.", ex); - - throw exception; - } - } - - public async Task> GetIdentityResource(String identityResourceName, - CancellationToken cancellationToken) - { - String requestUri = this.BuildRequestUrl($"/api/identityresources/{identityResourceName}"); - - try - { - var result = await this.SendHttpGetRequest(requestUri, cancellationToken); - - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(result.Data); - } - catch(Exception ex) - { - // An exception has occurred, add some additional information to the message - Exception exception = new Exception($"Error getting identity resource {identityResourceName}.", ex); - - throw exception; - } - } - - public async Task>> GetIdentityResources(CancellationToken cancellationToken) - { - String requestUri = this.BuildRequestUrl("/api/identityresources"); - - try - { - var result = await this.SendHttpGetRequest>(requestUri, cancellationToken); - - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(result.Data); - } - catch(Exception ex) - { - // An exception has occurred, add some additional information to the message - Exception exception = new Exception("Error getting identity resources.", ex); - - throw exception; - } - } - - public async Task> GetRole(Guid roleId, - CancellationToken cancellationToken) - { - String requestUri = this.BuildRequestUrl($"/api/roles/{roleId}"); - - try - { - var result = await this.SendHttpGetRequest(requestUri, cancellationToken); - - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(result.Data); - } - catch(Exception ex) - { - // An exception has occurred, add some additional information to the message - Exception exception = new Exception($"Error get role with Id {roleId}.", ex); - - throw exception; - } - } - - public async Task>> GetRoles(CancellationToken cancellationToken) - { - String requestUri = this.BuildRequestUrl("/api/roles"); - - try - { - var result = await this.SendHttpGetRequest>(requestUri, cancellationToken); - - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(result.Data); - } - catch(Exception ex) - { - // An exception has occurred, add some additional information to the message - Exception exception = new Exception("Error get roles.", ex); - - throw exception; - } - } - - public async Task> GetToken(String username, - String password, - String clientId, - String clientSecret, - CancellationToken cancellationToken) - { - StringBuilder queryString = new StringBuilder(); - - queryString.Append("grant_type=password"); - queryString.Append($"&client_id={clientId}"); - queryString.Append($"&client_secret={clientSecret}"); - queryString.Append($"&username={username}"); - queryString.Append($"&password={password}"); - - return await this.GetToken(queryString.ToString(), cancellationToken); - } - - public async Task> GetToken(String clientId, - String clientSecret, - CancellationToken cancellationToken) - { - StringBuilder queryString = new StringBuilder(); - - queryString.Append("grant_type=client_credentials"); - queryString.Append($"&client_id={clientId}"); - queryString.Append($"&client_secret={clientSecret}"); - - return await this.GetToken(queryString.ToString(), cancellationToken); - } - - public async Task> GetToken(String clientId, - String clientSecret, - String refreshToken, - CancellationToken cancellationToken) - { - StringBuilder queryString = new StringBuilder(); - - queryString.Append("grant_type=client_credentials"); - queryString.Append($"&client_id={clientId}"); - queryString.Append($"&client_secret={clientSecret}"); - queryString.Append($"&refresh_token={refreshToken}"); - - return await this.GetToken(queryString.ToString(), cancellationToken); - } - - public async Task> GetUser(Guid userId, - CancellationToken cancellationToken) - { - String requestUri = this.BuildRequestUrl($"/api/users/{userId}"); - - try - { - var result = await this.SendHttpGetRequest(requestUri, cancellationToken); - - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(result.Data); - } - catch(Exception ex) - { - // An exception has occurred, add some additional information to the message - Exception exception = new Exception($"Error get user with Id {userId}.", ex); - - throw exception; - } - } - - public async Task>> GetUsers(String userName, - CancellationToken cancellationToken) - { - String requestUri = this.BuildRequestUrl("/api/users"); - - try - { - if (string.IsNullOrEmpty(userName) == false) - { - requestUri = $"{requestUri}?username={userName}"; - } - - var result = await this.SendHttpGetRequest>(requestUri, cancellationToken); - - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - return Result.Success(result.Data); - } - catch(Exception ex) - { - // An exception has occurred, add some additional information to the message - Exception exception = new Exception("Error get users.", ex); - - throw exception; - } - } - - private String BuildRequestUrl(String route) - { - if (string.IsNullOrEmpty(this.BaseAddress)) - { - this.BaseAddress = this.BaseAddressResolver("SecurityService"); - } - - String requestUri = $"{this.BaseAddress}{route}"; - return requestUri; - } - - private async Task> GetToken(String tokenRequest, - CancellationToken cancellationToken) - { - String requestUri = this.BuildRequestUrl("/connect/token"); - - try - { - StringContent httpContent = new StringContent(tokenRequest, Encoding.UTF8, "application/x-www-form-urlencoded"); - - // Make the Http Call here - HttpResponseMessage httpResponse = await this.HttpClient.PostAsync(requestUri, httpContent, cancellationToken); - - // Process the response - Result result = await this.HandleResponseX(httpResponse, cancellationToken); - - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); - - // call was successful so now deserialise the body to the response object - TokenResponse responseData = TokenResponse.Create(result.Data); - - return Result.Success(responseData); - } - catch(Exception ex) - { - // An exception has occurred, add some additional information to the message - Exception exception = new Exception("Error getting token.", ex); - - throw exception; - } - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.DataTransferObjects/Requests/CreateApiResourceRequest.cs b/archive/SecurityService.DataTransferObjects/Requests/CreateApiResourceRequest.cs deleted file mode 100644 index 3db21f54..00000000 --- a/archive/SecurityService.DataTransferObjects/Requests/CreateApiResourceRequest.cs +++ /dev/null @@ -1,69 +0,0 @@ -namespace SecurityService.DataTransferObjects.Requests -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using Newtonsoft.Json; - - [ExcludeFromCodeCoverage] - public class CreateApiResourceRequest - { - #region Properties - - /// - /// Gets or sets the description. - /// - /// - /// The description. - /// - [JsonProperty("description")] - public String Description { get; set; } - - /// - /// Gets or sets the display name. - /// - /// - /// The display name. - /// - [JsonProperty("display_name")] - public String DisplayName { get; set; } - - /// - /// Gets or sets the name. - /// - /// - /// The name. - /// - [JsonProperty("name")] - public String Name { get; set; } - - /// - /// Gets or sets the scopes. - /// - /// - /// The scopes. - /// - [JsonProperty("scopes")] - public List Scopes { get; set; } - - /// - /// Gets or sets the secret. - /// - /// - /// The secret. - /// - [JsonProperty("secret")] - public String Secret { get; set; } - - /// - /// Gets or sets the user claims. - /// - /// - /// The user claims. - /// - [JsonProperty("user_claims")] - public List UserClaims { get; set; } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.DataTransferObjects/Requests/CreateApiScopeRequest.cs b/archive/SecurityService.DataTransferObjects/Requests/CreateApiScopeRequest.cs deleted file mode 100644 index 6b3fc51d..00000000 --- a/archive/SecurityService.DataTransferObjects/Requests/CreateApiScopeRequest.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace SecurityService.DataTransferObjects.Requests -{ - using System; - using System.Diagnostics.CodeAnalysis; - using Newtonsoft.Json; - - [ExcludeFromCodeCoverage] - public class CreateApiScopeRequest - { - #region Properties - - /// - /// Gets or sets the description. - /// - /// - /// The description. - /// - [JsonProperty("description")] - public String Description { get; set; } - - /// - /// Gets or sets the display name. - /// - /// - /// The display name. - /// - [JsonProperty("display_name")] - public String DisplayName { get; set; } - - /// - /// Gets or sets the name. - /// - /// - /// The name. - /// - [JsonProperty("name")] - public String Name { get; set; } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.DataTransferObjects/Requests/CreateClientRequest.cs b/archive/SecurityService.DataTransferObjects/Requests/CreateClientRequest.cs deleted file mode 100644 index 2cc297db..00000000 --- a/archive/SecurityService.DataTransferObjects/Requests/CreateClientRequest.cs +++ /dev/null @@ -1,111 +0,0 @@ -namespace SecurityService.DataTransferObjects.Requests -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using Newtonsoft.Json; - - /// - /// - /// - [ExcludeFromCodeCoverage] - public class CreateClientRequest - { - #region Properties - - /// - /// Gets or sets the allowed grant types. - /// - /// - /// The allowed grant types. - /// - [JsonProperty("allowed_grant_types")] - public List AllowedGrantTypes { get; set; } - - /// - /// Gets or sets the allowed scopes. - /// - /// - /// The allowed scopes. - /// - [JsonProperty("allowed_scopes")] - public List AllowedScopes { get; set; } - - /// - /// Gets or sets a value indicating whether [allow offline access]. - /// - /// - /// true if [allow offline access]; otherwise, false. - /// - [JsonProperty("allow_offline_access")] - public Boolean AllowOfflineAccess { get; set; } - - /// - /// Gets or sets the client description. - /// - /// - /// The client description. - /// - [JsonProperty("client_description")] - public String ClientDescription { get; set; } - - /// - /// Gets or sets the client identifier. - /// - /// - /// The client identifier. - /// - [JsonProperty("client_id")] - public String ClientId { get; set; } - - /// - /// Gets or sets the name of the client. - /// - /// - /// The name of the client. - /// - [JsonProperty("client_name")] - public String ClientName { get; set; } - - /// - /// Gets or sets the client post logout redirect uris. - /// - /// - /// The client post logout redirect uris. - /// - [JsonProperty("client_post_logout_redirect_uris")] - public List ClientPostLogoutRedirectUris { get; set; } - - /// - /// Gets or sets the client redirect uris. - /// - /// - /// The client redirect uris. - /// - [JsonProperty("client_redirect_uris")] - public List ClientRedirectUris { get; set; } - - [JsonProperty("client_uri")] - public String ClientUri { get; set; } - - /// - /// Gets or sets a value indicating whether [require consent]. - /// - /// - /// true if [require consent]; otherwise, false. - /// - [JsonProperty("require_content")] - public Boolean RequireConsent { get; set; } - - /// - /// Gets or sets the secret. - /// - /// - /// The secret. - /// - [JsonProperty("secret")] - public String Secret { get; set; } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.DataTransferObjects/Requests/CreateIdentityResourceRequest.cs b/archive/SecurityService.DataTransferObjects/Requests/CreateIdentityResourceRequest.cs deleted file mode 100644 index ee122b13..00000000 --- a/archive/SecurityService.DataTransferObjects/Requests/CreateIdentityResourceRequest.cs +++ /dev/null @@ -1,75 +0,0 @@ -namespace SecurityService.DataTransferObjects.Requests -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using Newtonsoft.Json; - - /// - /// - /// - [ExcludeFromCodeCoverage] - public class CreateIdentityResourceRequest - { - #region Properties - - [JsonProperty("name")] - public String Name { get; set; } - - /// - /// Gets or sets the description. - /// - /// - /// The description. - /// - [JsonProperty("description")] - public String Description { get; set; } - - /// - /// Gets or sets the display name. - /// - /// - /// The display name. - /// - [JsonProperty("display_name")] - public String DisplayName { get; set; } - - /// - /// Gets or sets a value indicating whether this is emphasize. - /// - /// - /// true if emphasize; otherwise, false. - /// - [JsonProperty("emphasize")] - public Boolean Emphasize { get; set; } - - /// - /// Gets or sets a value indicating whether this is required. - /// - /// - /// true if required; otherwise, false. - /// - [JsonProperty("required")] - public Boolean Required { get; set; } - - /// - /// Gets or sets a value indicating whether [show in discovery document]. - /// - /// - /// true if [show in discovery document]; otherwise, false. - /// - [JsonProperty("show_in_discovery_document")] - public Boolean ShowInDiscoveryDocument { get; set; } - - /// - /// Gets or sets the claims. - /// - /// - /// The claims. - /// - [JsonProperty("claims")] - public List Claims { get; set; } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.DataTransferObjects/Requests/CreateRoleRequest.cs b/archive/SecurityService.DataTransferObjects/Requests/CreateRoleRequest.cs deleted file mode 100644 index c331e623..00000000 --- a/archive/SecurityService.DataTransferObjects/Requests/CreateRoleRequest.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace SecurityService.DataTransferObjects.Requests -{ - using System.Diagnostics.CodeAnalysis; - using Newtonsoft.Json; - - [ExcludeFromCodeCoverage] - public class CreateRoleRequest - { - /// - /// Gets or sets the name of the role. - /// - /// - /// The name of the role. - /// - [JsonProperty("role_name")] - public String RoleName { get; set; } - } -} diff --git a/archive/SecurityService.DataTransferObjects/Requests/CreateUserRequest.cs b/archive/SecurityService.DataTransferObjects/Requests/CreateUserRequest.cs deleted file mode 100644 index a64ee8c3..00000000 --- a/archive/SecurityService.DataTransferObjects/Requests/CreateUserRequest.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace SecurityService.DataTransferObjects -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Runtime.CompilerServices; - using Newtonsoft.Json; - - [ExcludeFromCodeCoverage] - public class CreateUserRequest - { - [JsonProperty("email_address")] - public String EmailAddress { get; set; } - - [JsonProperty("phone_number")] - public String PhoneNumber { get; set; } - - [JsonProperty("claims")] - public Dictionary Claims { get; set; } - - [JsonProperty("roles")] - public List Roles { get; set; } - - [JsonProperty("given_name")] - public String GivenName { get; set; } - - [JsonProperty("middle_name")] - public String MiddleName { get; set; } - - [JsonProperty("family_name")] - public String FamilyName { get; set; } - - [JsonProperty("password")] - public String Password { get; set; } - } -} diff --git a/archive/SecurityService.DataTransferObjects/Responses/ApiResourceDetails.cs b/archive/SecurityService.DataTransferObjects/Responses/ApiResourceDetails.cs deleted file mode 100644 index 889f7dfb..00000000 --- a/archive/SecurityService.DataTransferObjects/Responses/ApiResourceDetails.cs +++ /dev/null @@ -1,69 +0,0 @@ -namespace SecurityService.DataTransferObjects.Responses -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using Newtonsoft.Json; - - [ExcludeFromCodeCoverage] - public class ApiResourceDetails - { - #region Properties - - /// - /// Gets or sets the description. - /// - /// - /// The description. - /// - [JsonProperty("description")] - public String Description { get; set; } - - /// - /// Gets or sets the display name. - /// - /// - /// The display name. - /// - [JsonProperty("display_name")] - public String DisplayName { get; set; } - - /// - /// Gets or sets a value indicating whether this is enabled. - /// - /// - /// true if enabled; otherwise, false. - /// - [JsonProperty("enabled")] - public Boolean Enabled { get; set; } - - /// - /// Gets or sets the name. - /// - /// - /// The name. - /// - [JsonProperty("name")] - public String Name { get; set; } - - /// - /// Gets or sets the scopes. - /// - /// - /// The scopes. - /// - [JsonProperty("scopes")] - public List Scopes { get; set; } - - /// - /// Gets or sets the user claims. - /// - /// - /// The user claims. - /// - [JsonProperty("user_claims")] - public List UserClaims { get; set; } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.DataTransferObjects/Responses/ApiScopeDetails.cs b/archive/SecurityService.DataTransferObjects/Responses/ApiScopeDetails.cs deleted file mode 100644 index 374f1d43..00000000 --- a/archive/SecurityService.DataTransferObjects/Responses/ApiScopeDetails.cs +++ /dev/null @@ -1,50 +0,0 @@ -namespace SecurityService.DataTransferObjects.Responses -{ - using System; - using System.Diagnostics.CodeAnalysis; - using Newtonsoft.Json; - - [ExcludeFromCodeCoverage] - public class ApiScopeDetails - { - #region Properties - - /// - /// Gets or sets the description. - /// - /// - /// The description. - /// - [JsonProperty("description")] - public String Description { get; set; } - - /// - /// Gets or sets the display name. - /// - /// - /// The display name. - /// - [JsonProperty("display_name")] - public String DisplayName { get; set; } - - /// - /// Gets or sets a value indicating whether this is enabled. - /// - /// - /// true if enabled; otherwise, false. - /// - [JsonProperty("enabled")] - public Boolean Enabled { get; set; } - - /// - /// Gets or sets the name. - /// - /// - /// The name. - /// - [JsonProperty("name")] - public String Name { get; set; } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.DataTransferObjects/Responses/ClientDetails.cs b/archive/SecurityService.DataTransferObjects/Responses/ClientDetails.cs deleted file mode 100644 index fd76d3d5..00000000 --- a/archive/SecurityService.DataTransferObjects/Responses/ClientDetails.cs +++ /dev/null @@ -1,105 +0,0 @@ -namespace SecurityService.DataTransferObjects.Responses -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using Newtonsoft.Json; - - [ExcludeFromCodeCoverage] - public class ClientDetails - { - #region Properties - - /// - /// Gets or sets the allowed grant types. - /// - /// - /// The allowed grant types. - /// - [JsonProperty("allowed_grant_types")] - public List AllowedGrantTypes { get; set; } - - /// - /// Gets or sets the allowed scopes. - /// - /// - /// The allowed scopes. - /// - [JsonProperty("allowed_scopes")] - public List AllowedScopes { get; set; } - - /// - /// Gets or sets a value indicating whether [allow offline access]. - /// - /// - /// true if [allow offline access]; otherwise, false. - /// - [JsonProperty("allow_offline_access")] - public Boolean AllowOfflineAccess { get; set; } - - /// - /// Gets or sets the client description. - /// - /// - /// The client description. - /// - [JsonProperty("client_description")] - public String ClientDescription { get; set; } - - /// - /// Gets or sets the client identifier. - /// - /// - /// The client identifier. - /// - [JsonProperty("client_id")] - public String ClientId { get; set; } - - /// - /// Gets or sets the name of the client. - /// - /// - /// The name of the client. - /// - [JsonProperty("client_name")] - public String ClientName { get; set; } - - /// - /// Gets or sets the client post logout redirect uris. - /// - /// - /// The client post logout redirect uris. - /// - [JsonProperty("client_post_logout_redirect_uris")] - public List ClientPostLogoutRedirectUris { get; set; } - - /// - /// Gets or sets the client redirect uris. - /// - /// - /// The client redirect uris. - /// - [JsonProperty("client_redirect_uris")] - public List ClientRedirectUris { get; set; } - - /// - /// Gets or sets a value indicating whether this is enabled. - /// - /// - /// true if enabled; otherwise, false. - /// - [JsonProperty("enabled")] - public Boolean Enabled { get; set; } - - /// - /// Gets or sets a value indicating whether [require consent]. - /// - /// - /// true if [require consent]; otherwise, false. - /// - [JsonProperty("require_content")] - public Boolean RequireConsent { get; set; } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.DataTransferObjects/Responses/CreateApiResourceResponse.cs b/archive/SecurityService.DataTransferObjects/Responses/CreateApiResourceResponse.cs deleted file mode 100644 index bd54c006..00000000 --- a/archive/SecurityService.DataTransferObjects/Responses/CreateApiResourceResponse.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace SecurityService.DataTransferObjects.Responses -{ - using System.Diagnostics.CodeAnalysis; - using Newtonsoft.Json; - - [ExcludeFromCodeCoverage] - public class CreateApiResourceResponse - { - /// - /// Gets or sets the name of the API resource. - /// - /// - /// The name of the API resource. - /// - [JsonProperty("api_resource_name")] - public String ApiResourceName { get; set; } - } -} diff --git a/archive/SecurityService.DataTransferObjects/Responses/CreateApiScopeResponse.cs b/archive/SecurityService.DataTransferObjects/Responses/CreateApiScopeResponse.cs deleted file mode 100644 index 9b37e47b..00000000 --- a/archive/SecurityService.DataTransferObjects/Responses/CreateApiScopeResponse.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace SecurityService.DataTransferObjects.Responses -{ - using System; - using System.Diagnostics.CodeAnalysis; - using Newtonsoft.Json; - - [ExcludeFromCodeCoverage] - public class CreateApiScopeResponse - { - /// - /// Gets or sets the name of the API scope. - /// - /// - /// The name of the API scope. - /// - [JsonProperty("api_scope_name")] - public String ApiScopeName { get; set; } - } -} \ No newline at end of file diff --git a/archive/SecurityService.DataTransferObjects/Responses/CreateClientResponse.cs b/archive/SecurityService.DataTransferObjects/Responses/CreateClientResponse.cs deleted file mode 100644 index 1d0fb7b2..00000000 --- a/archive/SecurityService.DataTransferObjects/Responses/CreateClientResponse.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace SecurityService.DataTransferObjects -{ - using System; - using System.Diagnostics.CodeAnalysis; - using Newtonsoft.Json; - - [ExcludeFromCodeCoverage] - public class CreateClientResponse - { - #region Properties - - /// - /// Gets or sets the client identifier. - /// - /// - /// The client identifier. - /// - [JsonProperty("client_id")] - public String ClientId { get; set; } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.DataTransferObjects/Responses/CreateIdentityResourceResponse.cs b/archive/SecurityService.DataTransferObjects/Responses/CreateIdentityResourceResponse.cs deleted file mode 100644 index 8950ffaf..00000000 --- a/archive/SecurityService.DataTransferObjects/Responses/CreateIdentityResourceResponse.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace SecurityService.DataTransferObjects.Responses -{ - using System.Diagnostics.CodeAnalysis; - using Newtonsoft.Json; - - [ExcludeFromCodeCoverage] - public class CreateIdentityResourceResponse - { - /// - /// Gets or sets the name of the identity resource. - /// - /// - /// The name of the identity resource. - /// - [JsonProperty("identity_resource_name")] - public String IdentityResourceName { get; set; } - } -} diff --git a/archive/SecurityService.DataTransferObjects/Responses/CreateRoleResponse.cs b/archive/SecurityService.DataTransferObjects/Responses/CreateRoleResponse.cs deleted file mode 100644 index e902a890..00000000 --- a/archive/SecurityService.DataTransferObjects/Responses/CreateRoleResponse.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace SecurityService.DataTransferObjects.Responses -{ - using System; - using System.Diagnostics.CodeAnalysis; - using Newtonsoft.Json; - - [ExcludeFromCodeCoverage] - public class CreateRoleResponse - { - /// - /// Gets or sets the role identifier. - /// - /// - /// The role identifier. - /// - [JsonProperty("role_id")] - public Guid RoleId { get; set; } - } -} \ No newline at end of file diff --git a/archive/SecurityService.DataTransferObjects/Responses/CreateUserResponse.cs b/archive/SecurityService.DataTransferObjects/Responses/CreateUserResponse.cs deleted file mode 100644 index f0dbe3c3..00000000 --- a/archive/SecurityService.DataTransferObjects/Responses/CreateUserResponse.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace SecurityService.DataTransferObjects -{ - using System; - using System.Diagnostics.CodeAnalysis; - using Newtonsoft.Json; - - [ExcludeFromCodeCoverage] - public class CreateUserResponse - { - #region Properties - - /// - /// Gets or sets the user identifier. - /// - /// - /// The user identifier. - /// - [JsonProperty("user_id")] - public Guid UserId { get; set; } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.DataTransferObjects/Responses/IdentityResourceDetails.cs b/archive/SecurityService.DataTransferObjects/Responses/IdentityResourceDetails.cs deleted file mode 100644 index 90ae761b..00000000 --- a/archive/SecurityService.DataTransferObjects/Responses/IdentityResourceDetails.cs +++ /dev/null @@ -1,81 +0,0 @@ -namespace SecurityService.DataTransferObjects.Responses -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using Newtonsoft.Json; - - /// - /// - /// - [ExcludeFromCodeCoverage] - public class IdentityResourceDetails - { - #region Properties - - /// - /// Gets or sets the claims. - /// - /// - /// The claims. - /// - [JsonProperty("claims")] - public List Claims { get; set; } - - /// - /// Gets or sets the description. - /// - /// - /// The description. - /// - [JsonProperty("description")] - public String Description { get; set; } - - /// - /// Gets or sets the display name. - /// - /// - /// The display name. - /// - [JsonProperty("display_name")] - public String DisplayName { get; set; } - - /// - /// Gets or sets the name. - /// - /// - /// The name. - /// - [JsonProperty("name")] - public String Name { get; set; } - - /// - /// Gets or sets a value indicating whether this is emphasize. - /// - /// - /// true if emphasize; otherwise, false. - /// - [JsonProperty("emphasize")] - public Boolean Emphasize { get; set; } - - /// - /// Gets or sets a value indicating whether this is required. - /// - /// - /// true if required; otherwise, false. - /// - [JsonProperty("required")] - public Boolean Required { get; set; } - - /// - /// Gets or sets a value indicating whether [show in discovery document]. - /// - /// - /// true if [show in discovery document]; otherwise, false. - /// - [JsonProperty("show_in_discovery_document")] - public Boolean ShowInDiscoveryDocument { get; set; } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.DataTransferObjects/Responses/RoleDetails.cs b/archive/SecurityService.DataTransferObjects/Responses/RoleDetails.cs deleted file mode 100644 index 1e79df01..00000000 --- a/archive/SecurityService.DataTransferObjects/Responses/RoleDetails.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace SecurityService.DataTransferObjects.Responses -{ - using System; - using System.Diagnostics.CodeAnalysis; - using Newtonsoft.Json; - - [ExcludeFromCodeCoverage] - public class RoleDetails - { - /// - /// Gets or sets the role identifier. - /// - /// - /// The role identifier. - /// - [JsonProperty("role_id")] - public Guid RoleId { get; set; } - - /// - /// Gets or sets the name of the role. - /// - /// - /// The name of the role. - /// - [JsonProperty("role_name")] - public String RoleName { get; set; } - } -} \ No newline at end of file diff --git a/archive/SecurityService.DataTransferObjects/Responses/TokenResponse.cs b/archive/SecurityService.DataTransferObjects/Responses/TokenResponse.cs deleted file mode 100644 index f2c9534c..00000000 --- a/archive/SecurityService.DataTransferObjects/Responses/TokenResponse.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace SecurityService.DataTransferObjects.Responses -{ - using System.Diagnostics.CodeAnalysis; - using Newtonsoft.Json; - - [ExcludeFromCodeCoverage] - public class TokenResponse - { - /// - /// The access token - /// - /// The access token. - public String AccessToken { get; private set; } - - /// - /// Gets the expires. - /// - /// The expires. - public DateTimeOffset Expires { get; private set; } - - /// - /// The expires - /// - /// The expires in. - public Int64 ExpiresIn { get; private set; } - - /// - /// Gets the issued. - /// - /// The issued. - public DateTimeOffset Issued { get; private set; } - - /// - /// The refresh token - /// - /// The refresh token. - public String RefreshToken { get; private set; } - - public static TokenResponse Create(String token) - { - dynamic auth = JsonConvert.DeserializeObject(token); - - Int64 expiresIn = auth["expires_in"].Value; - String accessToken = auth["access_token"].Value; - - DateTimeOffset issued = DateTimeOffset.Now; - DateTimeOffset expires = DateTimeOffset.Now.AddSeconds(expiresIn); - - String refreshToken = null; - //For client credentials, the refresh_token will not be present - if (auth["refresh_token"] != null) - { - refreshToken = auth["refresh_token"].Value; - } - - return TokenResponse.Create(accessToken, refreshToken, expiresIn, issued, expires); - } - - public static TokenResponse Create(String accessToken, - String refreshToken, - Int64 expiresIn, - DateTimeOffset issued = default(DateTimeOffset), - DateTimeOffset expires = default(DateTimeOffset)) - { - return new TokenResponse(accessToken,refreshToken,expiresIn,issued, expires); - } - - private TokenResponse(String accessToken, - String refreshToken, - Int64 expiresIn, - DateTimeOffset issued = default(DateTimeOffset), - DateTimeOffset expires = default(DateTimeOffset)) - { - this.AccessToken = accessToken; - this.RefreshToken = refreshToken; - this.ExpiresIn = expiresIn; - this.Issued = issued; - this.Expires = expires; - } - } -} diff --git a/archive/SecurityService.DataTransferObjects/Responses/UserDetails.cs b/archive/SecurityService.DataTransferObjects/Responses/UserDetails.cs deleted file mode 100644 index b17b1e4d..00000000 --- a/archive/SecurityService.DataTransferObjects/Responses/UserDetails.cs +++ /dev/null @@ -1,72 +0,0 @@ -namespace SecurityService.DataTransferObjects.Responses -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using Newtonsoft.Json; - - [ExcludeFromCodeCoverage] - public class UserDetails - { - #region Properties - - /// - /// Gets or sets the claims. - /// - /// - /// The claims. - /// - [JsonProperty("claims")] - public Dictionary Claims { get; set; } - - /// - /// Gets or sets the email. - /// - /// - /// The email. - /// - [JsonProperty("email_address")] - public String EmailAddress { get; set; } - - /// - /// Gets or sets the phone number. - /// - /// - /// The phone number. - /// - [JsonProperty("phone_number")] - public String PhoneNumber { get; set; } - - /// - /// Gets or sets the roles. - /// - /// - /// The roles. - /// - [JsonProperty("roles")] - public List Roles { get; set; } - - /// - /// Gets or sets the user identifier. - /// - /// - /// The user identifier. - /// - [JsonProperty("user_id")] - public Guid UserId { get; set; } - - /// - /// Gets or sets the name of the user. - /// - /// - /// The name of the user. - /// - [JsonProperty("user_name")] - public String UserName { get; set; } - - [JsonProperty("registration_date_time")] - public DateTime RegistrationDateTime { get; set; } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.DataTransferObjects/SecurityService.DataTransferObjects.csproj b/archive/SecurityService.DataTransferObjects/SecurityService.DataTransferObjects.csproj deleted file mode 100644 index c6533110..00000000 --- a/archive/SecurityService.DataTransferObjects/SecurityService.DataTransferObjects.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - net10.0 - - - - D:\Projects\StuartFerguson\NewSecurity\SecurityService\SecurityService.DataTransferObjects\SecurityService.DataTransferObjects.xml - - - - - - - - diff --git a/archive/SecurityService.DataTransferObjects/SecurityService.DataTransferObjects.xml b/archive/SecurityService.DataTransferObjects/SecurityService.DataTransferObjects.xml deleted file mode 100644 index 9bba998f..00000000 --- a/archive/SecurityService.DataTransferObjects/SecurityService.DataTransferObjects.xml +++ /dev/null @@ -1,653 +0,0 @@ - - - - SecurityService.DataTransferObjects - - - - - Gets or sets the description. - - - The description. - - - - - Gets or sets the display name. - - - The display name. - - - - - Gets or sets the name. - - - The name. - - - - - Gets or sets the scopes. - - - The scopes. - - - - - Gets or sets the secret. - - - The secret. - - - - - Gets or sets the user claims. - - - The user claims. - - - - - Gets or sets the description. - - - The description. - - - - - Gets or sets the display name. - - - The display name. - - - - - Gets or sets the name. - - - The name. - - - - - - - - - - Gets or sets the allowed grant types. - - - The allowed grant types. - - - - - Gets or sets the allowed scopes. - - - The allowed scopes. - - - - - Gets or sets a value indicating whether [allow offline access]. - - - true if [allow offline access]; otherwise, false. - - - - - Gets or sets the client description. - - - The client description. - - - - - Gets or sets the client identifier. - - - The client identifier. - - - - - Gets or sets the name of the client. - - - The name of the client. - - - - - Gets or sets the client post logout redirect uris. - - - The client post logout redirect uris. - - - - - Gets or sets the client redirect uris. - - - The client redirect uris. - - - - - Gets or sets a value indicating whether [require consent]. - - - true if [require consent]; otherwise, false. - - - - - Gets or sets the secret. - - - The secret. - - - - - - - - - - Gets or sets the description. - - - The description. - - - - - Gets or sets the display name. - - - The display name. - - - - - Gets or sets a value indicating whether this is emphasize. - - - true if emphasize; otherwise, false. - - - - - Gets or sets a value indicating whether this is required. - - - true if required; otherwise, false. - - - - - Gets or sets a value indicating whether [show in discovery document]. - - - true if [show in discovery document]; otherwise, false. - - - - - Gets or sets the claims. - - - The claims. - - - - - Gets or sets the name of the role. - - - The name of the role. - - - - - Gets or sets the email address. - - - The email address. - - - - - Gets or sets the phone number. - - - The phone number. - - - - - Gets or sets the password. - - - The password. - - - - - Gets or sets the claims. - - - The claims. - - - - - Gets or sets the roles. - - - The roles. - - - - - Gets or sets the name of the given. - - - The name of the given. - - - - - Gets or sets the name of the middle. - - - The name of the middle. - - - - - Gets or sets the name of the family. - - - The name of the family. - - - - - Gets or sets the description. - - - The description. - - - - - Gets or sets the display name. - - - The display name. - - - - - Gets or sets a value indicating whether this is enabled. - - - true if enabled; otherwise, false. - - - - - Gets or sets the name. - - - The name. - - - - - Gets or sets the scopes. - - - The scopes. - - - - - Gets or sets the user claims. - - - The user claims. - - - - - Gets or sets the description. - - - The description. - - - - - Gets or sets the display name. - - - The display name. - - - - - Gets or sets a value indicating whether this is enabled. - - - true if enabled; otherwise, false. - - - - - Gets or sets the name. - - - The name. - - - - - Gets or sets the allowed grant types. - - - The allowed grant types. - - - - - Gets or sets the allowed scopes. - - - The allowed scopes. - - - - - Gets or sets a value indicating whether [allow offline access]. - - - true if [allow offline access]; otherwise, false. - - - - - Gets or sets the client description. - - - The client description. - - - - - Gets or sets the client identifier. - - - The client identifier. - - - - - Gets or sets the name of the client. - - - The name of the client. - - - - - Gets or sets the client post logout redirect uris. - - - The client post logout redirect uris. - - - - - Gets or sets the client redirect uris. - - - The client redirect uris. - - - - - Gets or sets a value indicating whether this is enabled. - - - true if enabled; otherwise, false. - - - - - Gets or sets a value indicating whether [require consent]. - - - true if [require consent]; otherwise, false. - - - - - Gets or sets the name of the API resource. - - - The name of the API resource. - - - - - Gets or sets the name of the API scope. - - - The name of the API scope. - - - - - Gets or sets the name of the identity resource. - - - The name of the identity resource. - - - - - Gets or sets the role identifier. - - - The role identifier. - - - - - - - - - - Gets or sets the claims. - - - The claims. - - - - - Gets or sets the description. - - - The description. - - - - - Gets or sets the display name. - - - The display name. - - - - - Gets or sets the name. - - - The name. - - - - - Gets or sets a value indicating whether this is emphasize. - - - true if emphasize; otherwise, false. - - - - - Gets or sets a value indicating whether this is required. - - - true if required; otherwise, false. - - - - - Gets or sets a value indicating whether [show in discovery document]. - - - true if [show in discovery document]; otherwise, false. - - - - - Gets or sets the role identifier. - - - The role identifier. - - - - - Gets or sets the name of the role. - - - The name of the role. - - - - - The access token - - The access token. - - - - Gets the expires. - - The expires. - - - - The expires - - The expires in. - - - - Gets the issued. - - The issued. - - - - The refresh token - - The refresh token. - - - - Gets or sets the claims. - - - The claims. - - - - - Gets or sets the email. - - - The email. - - - - - Gets or sets the phone number. - - - The phone number. - - - - - Gets or sets the roles. - - - The roles. - - - - - Gets or sets the user identifier. - - - The user identifier. - - - - - Gets or sets the name of the user. - - - The name of the user. - - - - - Gets or sets the client identifier. - - - The client identifier. - - - - - Gets or sets the user identifier. - - - The user identifier. - - - - diff --git a/archive/SecurityService.Database/DbContexts/AuthenticationDbContext.cs b/archive/SecurityService.Database/DbContexts/AuthenticationDbContext.cs deleted file mode 100644 index cda4d88c..00000000 --- a/archive/SecurityService.Database/DbContexts/AuthenticationDbContext.cs +++ /dev/null @@ -1,69 +0,0 @@ -using Microsoft.Data.SqlClient; -using SecurityService.BusinessLogic; - -namespace SecurityService.Database.DbContexts -{ - using Duende.IdentityServer.EntityFramework.DbContexts; - using Duende.IdentityServer.EntityFramework.Options; - using Microsoft.AspNetCore.Identity; - using Microsoft.AspNetCore.Identity.EntityFrameworkCore; - using Microsoft.EntityFrameworkCore; - using Shared.General; - using System; - using System.Threading; - using System.Threading.Tasks; - - public class AuthenticationDbContext : IdentityDbContext { - public AuthenticationDbContext(DbContextOptions options) : base(options) { - } - - protected override void OnModelCreating(ModelBuilder builder) { - base.OnModelCreating(builder); - // Customize the ASP.NET Identity model and override the defaults if needed. - // For example, you can rename the ASP.NET Identity table names and more. - // Add your customizations after calling base.OnModelCreating(builder); - } - } - public static class Extensions - { - - public static async Task SetDbInSimpleMode(this DbContext context, CancellationToken cancellationToken) - { - var dbName = context.Database.GetDbConnection().Database; - - var connection = context.Database.GetDbConnection(); - if (connection.State != System.Data.ConnectionState.Open) - await connection.OpenAsync(cancellationToken); - - // 1. Check current recovery model - await using var checkCommand = connection.CreateCommand(); - checkCommand.CommandText = @" -SELECT recovery_model_desc -FROM sys.databases -WHERE name = @dbName; -"; - var param = checkCommand.CreateParameter(); - param.ParameterName = "@dbName"; - param.Value = dbName; - checkCommand.Parameters.Add(param); - - var result = await checkCommand.ExecuteScalarAsync(cancellationToken); - var currentRecoveryModel = result?.ToString(); - - if (currentRecoveryModel != "SIMPLE") - { - // 2. Alter database outside transaction - await using var alterCommand = connection.CreateCommand(); - alterCommand.CommandText = $@" -ALTER DATABASE [{dbName}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; -ALTER DATABASE [{dbName}] SET RECOVERY SIMPLE; -ALTER DATABASE [{dbName}] SET MULTI_USER; -"; - // Execute outside EF transaction - await alterCommand.ExecuteNonQueryAsync(cancellationToken); - } - } - } - - -} \ No newline at end of file diff --git a/archive/SecurityService.Database/SecurityService.Database.csproj b/archive/SecurityService.Database/SecurityService.Database.csproj deleted file mode 100644 index 331de9a3..00000000 --- a/archive/SecurityService.Database/SecurityService.Database.csproj +++ /dev/null @@ -1,34 +0,0 @@ - - - - net10.0 - None - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - diff --git a/archive/SecurityService.IntegrationTesting.Helpers/ReqnrollExtensions.cs b/archive/SecurityService.IntegrationTesting.Helpers/ReqnrollExtensions.cs deleted file mode 100644 index abdcbac3..00000000 --- a/archive/SecurityService.IntegrationTesting.Helpers/ReqnrollExtensions.cs +++ /dev/null @@ -1,327 +0,0 @@ -namespace SecurityService.IntegrationTesting.Helpers{ - using DataTransferObjects.Requests; - using Microsoft.EntityFrameworkCore.Metadata.Internal; - using SecurityService.DataTransferObjects.Responses; - using Shared.IntegrationTesting; - using Shouldly; - using System.Collections.Generic; - using DataTransferObjects; - using Reqnroll; - - public static class ReqnrollExtensions{ - public static List ToCreateApiScopeRequests(this DataTableRows tableRows){ - List requests = new List(); - foreach (DataTableRow tableRow in tableRows){ - CreateApiScopeRequest createApiScopeRequest = new CreateApiScopeRequest{ - Name = ReqnrollTableHelper.GetStringRowValue(tableRow, "Name"), - Description = ReqnrollTableHelper.GetStringRowValue(tableRow, "Description"), - DisplayName = ReqnrollTableHelper.GetStringRowValue(tableRow, "DisplayName") - }; - requests.Add(createApiScopeRequest); - } - - return requests; - } - - public static List ToCreateApiResourceRequests(this DataTableRows tableRows, Guid? testId = null){ - List requests = new List(); - foreach (DataTableRow tableRow in tableRows){ - String resourceName = ReqnrollTableHelper.GetStringRowValue(tableRow, "Name"); - String displayName = ReqnrollTableHelper.GetStringRowValue(tableRow, "DisplayName"); - String description = ReqnrollTableHelper.GetStringRowValue(tableRow, "Description"); - String secret = ReqnrollTableHelper.GetStringRowValue(tableRow, "Secret"); - String scopes = ReqnrollTableHelper.GetStringRowValue(tableRow, "Scopes"); - String userClaims = ReqnrollTableHelper.GetStringRowValue(tableRow, "UserClaims"); - - if (testId.HasValue){ - scopes = scopes.Replace("[id]", testId.Value.ToString("N")); - resourceName = resourceName.Replace("[id]", testId.Value.ToString("N")); - } - - CreateApiResourceRequest createApiResourceRequest = new CreateApiResourceRequest{ - Description = description, - DisplayName = displayName, - Name = resourceName, - Scopes = new List(), - Secret = secret, - UserClaims = new List() - }; - createApiResourceRequest.Scopes = scopes.SplitString(); - createApiResourceRequest.UserClaims = userClaims.SplitString(); - - requests.Add(createApiResourceRequest); - } - - return requests; - } - - public static List ToCreateClientRequests(this DataTableRows tableRows, Guid? testId = null, Int32? testUIPort = null){ - List requests = new List(); - - foreach (DataTableRow tableRow in tableRows){ - String clientId = ReqnrollTableHelper.GetStringRowValue(tableRow, "ClientId"); - String clientName = ReqnrollTableHelper.GetStringRowValue(tableRow, "Name"); - String clientDescription = ReqnrollTableHelper.GetStringRowValue(tableRow, "Description"); - String secret = ReqnrollTableHelper.GetStringRowValue(tableRow, "Secret"); - String allowedScopes = ReqnrollTableHelper.GetStringRowValue(tableRow, "Scopes"); - String allowedGrantTypes = ReqnrollTableHelper.GetStringRowValue(tableRow, "GrantTypes"); - String redirectUris = ReqnrollTableHelper.GetStringRowValue(tableRow, "RedirectUris"); - String postLogoutRedirectUris = ReqnrollTableHelper.GetStringRowValue(tableRow, "PostLogoutRedirectUris"); - String clientUri = ReqnrollTableHelper.GetStringRowValue(tableRow, "ClientUri"); - Boolean requireConsent = ReqnrollTableHelper.GetBooleanValue(tableRow, "RequireConsent"); - Boolean allowOfflineAccess = ReqnrollTableHelper.GetBooleanValue(tableRow, "AllowOfflineAccess"); - - if (testId.HasValue){ - allowedScopes = allowedScopes.Replace("[id]", testId.Value.ToString("N")); - clientId = clientId.Replace("[id]", testId.Value.ToString("N")); - } - - if (testUIPort.HasValue){ - clientUri = clientUri.Replace("[url]", "localhost"); - clientUri = clientUri.Replace("[port]", testUIPort.ToString()); - - redirectUris = redirectUris.Replace("[url]", "localhost"); - redirectUris = redirectUris.Replace("[port]", testUIPort.ToString()); - postLogoutRedirectUris = postLogoutRedirectUris.Replace("[url]", "localhost"); - postLogoutRedirectUris = postLogoutRedirectUris.Replace("[port]", testUIPort.ToString()); - } - - CreateClientRequest createClientRequest = new CreateClientRequest{ - Secret = secret, - AllowedGrantTypes = new List(), - AllowedScopes = new List(), - ClientDescription = clientDescription, - ClientId = clientId, - ClientName = clientName, - RequireConsent = requireConsent, - AllowOfflineAccess = allowOfflineAccess, - ClientUri = clientUri - }; - createClientRequest.AllowedScopes = allowedScopes.SplitString(); - createClientRequest.AllowedGrantTypes = allowedGrantTypes.SplitString(); - createClientRequest.ClientRedirectUris = redirectUris.SplitString(); - createClientRequest.ClientPostLogoutRedirectUris = postLogoutRedirectUris.SplitString(); - - requests.Add(createClientRequest); - } - - return requests; - } - - public static List ToApiResourceDetails(this DataTableRows tableRows){ - List result = new List(); - foreach (DataTableRow tableRow in tableRows){ - ApiResourceDetails details = new ApiResourceDetails(); - details.Description = ReqnrollTableHelper.GetStringRowValue(tableRow, "Description"); - details.Name = ReqnrollTableHelper.GetStringRowValue(tableRow, "Name"); - details.DisplayName = ReqnrollTableHelper.GetStringRowValue(tableRow, "DisplayName"); - - String scopes = ReqnrollTableHelper.GetStringRowValue(tableRow, "Scopes"); - String userClaims = ReqnrollTableHelper.GetStringRowValue(tableRow, "UserClaims"); - - if (string.IsNullOrEmpty(scopes) == false){ - //List splitScopes = scopes.Split(",").ToList(); - details.Scopes = scopes.SplitString(); - - //splitScopes.ForEach(a => { details.Scopes.Add(a.Trim()); }); - } - - if (string.IsNullOrEmpty(userClaims) == false){ - //List splitUserClaims = userClaims.Split(",").ToList(); - - //splitUserClaims.ForEach(a => { details.UserClaims.Add(a.Trim());}); - details.UserClaims = userClaims.SplitString(); - } - - result.Add(details); - } - - return result; - } - - public static List ToApiScopeDetails(this DataTableRows tableRows){ - List result = new List(); - - foreach (DataTableRow tableRow in tableRows){ - ApiScopeDetails scopeDetails = new ApiScopeDetails(); - scopeDetails.Description = ReqnrollTableHelper.GetStringRowValue(tableRow, "Description"); - scopeDetails.Name = ReqnrollTableHelper.GetStringRowValue(tableRow, "Name"); - scopeDetails.DisplayName = ReqnrollTableHelper.GetStringRowValue(tableRow, "DisplayName"); - result.Add(scopeDetails); - } - - return result; - } - - public static List ToClientDetails(this DataTableRows tableRows){ - List result = new List(); - - foreach (DataTableRow tableRow in tableRows){ - ClientDetails clientDetails = new ClientDetails(); - - String scopes = ReqnrollTableHelper.GetStringRowValue(tableRow, "Scopes"); - String grantTypes = ReqnrollTableHelper.GetStringRowValue(tableRow, "GrantTypes"); - - clientDetails.ClientId = ReqnrollTableHelper.GetStringRowValue(tableRow, "ClientId"); - clientDetails.ClientDescription = ReqnrollTableHelper.GetStringRowValue(tableRow, "Description"); - clientDetails.ClientName = ReqnrollTableHelper.GetStringRowValue(tableRow, "Name"); - if (string.IsNullOrEmpty(scopes) == false){ - clientDetails.AllowedScopes = scopes.SplitString(); - } - - if (string.IsNullOrEmpty(grantTypes) == false){ - clientDetails.AllowedGrantTypes = grantTypes.SplitString(); - } - result.Add(clientDetails); - } - - return result; - } - - public static List ToCreateIdentityResourceRequest(this DataTableRows tableRows){ - List result = new List(); - foreach (DataTableRow tableRow in tableRows){ - String userClaims = ReqnrollTableHelper.GetStringRowValue(tableRow, "UserClaims"); - CreateIdentityResourceRequest createIdentityResourceRequest = new CreateIdentityResourceRequest{ - Name = ReqnrollTableHelper.GetStringRowValue(tableRow, "Name"), - Claims = string.IsNullOrEmpty(userClaims) ? null : userClaims.Split(",").ToList(), - Description = ReqnrollTableHelper.GetStringRowValue(tableRow, "Description"), - DisplayName = ReqnrollTableHelper.GetStringRowValue(tableRow, "DisplayName") - }; - result.Add(createIdentityResourceRequest); - } - - return result; - } - - public static List ToIdentityResourceDetails(this DataTableRows tableRows){ - List result = new List(); - - foreach (DataTableRow tableRow in tableRows){ - String userClaims = ReqnrollTableHelper.GetStringRowValue(tableRow, "UserClaims"); - - IdentityResourceDetails identityResourceDetails = new IdentityResourceDetails(); - - identityResourceDetails.Description = ReqnrollTableHelper.GetStringRowValue(tableRow, "Description"); - identityResourceDetails.Name = ReqnrollTableHelper.GetStringRowValue(tableRow, "Name"); - identityResourceDetails.DisplayName = ReqnrollTableHelper.GetStringRowValue(tableRow, "DisplayName"); - - if (string.IsNullOrEmpty(userClaims) == false){ - identityResourceDetails.Claims = userClaims.SplitString(); - } - - result.Add(identityResourceDetails); - } - - return result; - } - - public static List ToCreateRoleRequests(this DataTableRows tableRows){ - List requests = new List(); - - foreach (DataTableRow tableRow in tableRows){ - CreateRoleRequest request = new CreateRoleRequest{ - RoleName = ReqnrollTableHelper.GetStringRowValue(tableRow, "Role Name") - }; - requests.Add(request); - } - - return requests; - } - - public static List ToRoleDetails(this DataTableRows tableRows){ - List requests = new List(); - - foreach (DataTableRow tableRow in tableRows){ - RoleDetails roleDetails = new RoleDetails(){ - RoleName = ReqnrollTableHelper.GetStringRowValue(tableRow, "Role Name") - }; - requests.Add(roleDetails); - } - - return requests; - } - - public static List ToCreateUserRequests(this DataTableRows tableRows){ - List requests = new List(); - - foreach (DataTableRow tableRow in tableRows){ - Dictionary userClaims = null; - String claims = ReqnrollTableHelper.GetStringRowValue(tableRow, "Claims"); - if (string.IsNullOrEmpty(claims) == false){ - userClaims = new Dictionary(); - String[] claimList = claims.Split(","); - foreach (String claim in claimList){ - // Split into claim name and value - String[] c = claim.Split(":"); - userClaims.Add(c[0], c[1]); - } - } - - String roles = ReqnrollTableHelper.GetStringRowValue(tableRow, "Roles"); - - CreateUserRequest createUserRequest = new CreateUserRequest{ - EmailAddress = ReqnrollTableHelper.GetStringRowValue(tableRow, "Email Address"), - FamilyName = ReqnrollTableHelper.GetStringRowValue(tableRow, "Family Name"), - GivenName = ReqnrollTableHelper.GetStringRowValue(tableRow, "Given Name"), - PhoneNumber = ReqnrollTableHelper.GetStringRowValue(tableRow, "Phone Number"), - MiddleName = ReqnrollTableHelper.GetStringRowValue(tableRow, "Middle name"), - Claims = userClaims, - Roles = string.IsNullOrEmpty(roles) ? null : roles.Split(",").ToList(), - Password = ReqnrollTableHelper.GetStringRowValue(tableRow, "Password") - }; - - requests.Add(createUserRequest); - } - - return requests; - } - - public static List ToUserDetails(this DataTableRows tableRows){ - - List userDetailsList = new List(); - - foreach (DataTableRow tableRow in tableRows){ - UserDetails userDetails = new UserDetails(); - - userDetails.EmailAddress = ReqnrollTableHelper.GetStringRowValue(tableRow, "Email Address"); - userDetails.PhoneNumber = - ReqnrollTableHelper.GetStringRowValue(tableRow, "Phone Number"); - userDetails.UserName = ReqnrollTableHelper.GetStringRowValue(tableRow, "Email Address"); - - - Dictionary userClaims = new Dictionary(); - String claims = ReqnrollTableHelper.GetStringRowValue(tableRow, "Claims"); - String[] claimList = claims.Split(","); - foreach (String claim in claimList){ - // Split into claim name and value - String[] c = claim.Split(":"); - userClaims.Add(c[0].Trim(), c[1].Trim()); - } - - userDetails.Claims = userClaims; - - String roles = ReqnrollTableHelper.GetStringRowValue(tableRow, "Roles"); - - if (string.IsNullOrEmpty(roles) == false){ - userDetails.Roles = roles.SplitString(); - } - - DateTime dateTime = ReqnrollTableHelper.GetDateForDateString(ReqnrollTableHelper.GetStringRowValue(tableRow, "RegistrationDate"), DateTime.Now); - userDetails.RegistrationDateTime = dateTime; - userDetailsList.Add(userDetails); - } - return userDetailsList; - } - - private static List SplitString(this String stringToSplit){ - List result = new List(); - - List splitString = stringToSplit.Split(",").ToList(); - foreach (String split in splitString){ - result.Add(split.Trim()); - } - return result; - } - } -} \ No newline at end of file diff --git a/archive/SecurityService.IntegrationTesting.Helpers/SecurityService.IntegrationTesting.Helpers.csproj b/archive/SecurityService.IntegrationTesting.Helpers/SecurityService.IntegrationTesting.Helpers.csproj deleted file mode 100644 index 8adb39d4..00000000 --- a/archive/SecurityService.IntegrationTesting.Helpers/SecurityService.IntegrationTesting.Helpers.csproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - net10.0 - enable - enable - - - - - - - - - - - - - - - - - - - diff --git a/archive/SecurityService.IntegrationTesting.Helpers/SecurityServiceSteps.cs b/archive/SecurityService.IntegrationTesting.Helpers/SecurityServiceSteps.cs deleted file mode 100644 index af9bf673..00000000 --- a/archive/SecurityService.IntegrationTesting.Helpers/SecurityServiceSteps.cs +++ /dev/null @@ -1,343 +0,0 @@ -using SimpleResults; - -namespace SecurityService.IntegrationTesting.Helpers; - -using Client; -using DataTransferObjects; -using DataTransferObjects.Requests; -using DataTransferObjects.Responses; -using Shared.IntegrationTesting; -using Shouldly; -using System.Collections.Generic; -using System.Threading; -using Reqnroll; - -public class SecurityServiceSteps{ - private readonly ISecurityServiceClient SecurityServiceClient; - - public SecurityServiceSteps(ISecurityServiceClient securityServiceClient){ - this.SecurityServiceClient = securityServiceClient; - } - - private async Task CreateApiScope(CreateApiScopeRequest createApiScopeRequest, - CancellationToken cancellationToken){ - Result? result = await this.SecurityServiceClient - .CreateApiScope(createApiScopeRequest, cancellationToken).ConfigureAwait(false); - result.IsSuccess.ShouldBeTrue(); - } - - public async Task GivenICreateTheFollowingApiScopes(List createApiScopeRequests){ - foreach (CreateApiScopeRequest createApiScopeRequest in createApiScopeRequests){ - await this.CreateApiScope(createApiScopeRequest, CancellationToken.None).ConfigureAwait(false); - - // TODO: can do a get in here to verify really created... - } - } - - public async Task GivenTheFollowingApiResourcesExist(DataTable table){ - foreach (DataTableRow tableRow in table.Rows){ - String resourceName = ReqnrollTableHelper.GetStringRowValue(tableRow, "ResourceName"); - String displayName = ReqnrollTableHelper.GetStringRowValue(tableRow, "DisplayName"); - String secret = ReqnrollTableHelper.GetStringRowValue(tableRow, "Secret"); - String scopes = ReqnrollTableHelper.GetStringRowValue(tableRow, "Scopes"); - String userClaims = ReqnrollTableHelper.GetStringRowValue(tableRow, "UserClaims"); - - List splitScopes = scopes.Split(",").ToList(); - List splitUserClaims = userClaims.Split(",").ToList(); - - CreateApiResourceRequest createApiResourceRequest = new CreateApiResourceRequest{ - Description = String.Empty, - DisplayName = displayName, - Name = resourceName, - Scopes = new List(), - Secret = secret, - UserClaims = new List() - }; - splitScopes.ForEach(a => { createApiResourceRequest.Scopes.Add(a.Trim()); }); - splitUserClaims.ForEach(a => { createApiResourceRequest.UserClaims.Add(a.Trim()); }); - - Result? result = await this.SecurityServiceClient.CreateApiResource(createApiResourceRequest, CancellationToken.None).ConfigureAwait(false); - result.IsSuccess.ShouldBeTrue(); - } - } - - public async Task allowedGrantTypes)>> GivenTheFollowingClientsExist(List createClientRequests){ - List<(String clientId, String secret, List allowedGrantTypes)> clients = new List<(String clientId, String secret, List allowedGrantTypes)>(); - foreach (CreateClientRequest createClientRequest in createClientRequests){ - Result? result = await this.SecurityServiceClient.CreateClient(createClientRequest, CancellationToken.None).ConfigureAwait(false); - result.IsSuccess.ShouldBeTrue(); - - // TODO: What do i do here.... - clients.Add((createClientRequest.ClientId, createClientRequest.Secret, createClientRequest.AllowedGrantTypes)); - } - - return clients; - } - - public async Task GivenTheFollowingApiResourcesExist(List requests){ - foreach (CreateApiResourceRequest createApiResourceRequest in requests){ - Result? result = await this.SecurityServiceClient.CreateApiResource(createApiResourceRequest, CancellationToken.None).ConfigureAwait(false); - result.IsSuccess.ShouldBeTrue(); - } - } - - public async Task GetClientToken(String clientId, String secret, CancellationToken cancellationToken){ - Result? tokenResponseResult = await this.SecurityServiceClient.GetToken(clientId, secret, cancellationToken).ConfigureAwait(false); - tokenResponseResult.IsSuccess.ShouldBeTrue(); - - return tokenResponseResult.Data.AccessToken; - } - - public async Task GetPasswordToken(String clientId, String secret, String userName, String password, CancellationToken cancellationToken) - { - Result? tokenResponseResult = await this.SecurityServiceClient.GetToken(userName,password, clientId, secret, cancellationToken).ConfigureAwait(false); - tokenResponseResult.IsSuccess.ShouldBeTrue(); - return tokenResponseResult.Data.AccessToken; - } - - public async Task WhenIGetTheApiResourcesApiResourceDetailsAreReturnedAsFollows(List expectedDetails, CancellationToken cancellationToken){ - Result>? apiResourceDetailsListResult = await this.SecurityServiceClient.GetApiResources(cancellationToken).ConfigureAwait(false); - apiResourceDetailsListResult.IsSuccess.ShouldBeTrue(); - List apiResourceDetailsList = apiResourceDetailsListResult.Data; - foreach (ApiResourceDetails apiResourceDetails in expectedDetails){ - ApiResourceDetails? foundRecord = apiResourceDetailsList.SingleOrDefault(a => a.Name == apiResourceDetails.Name); - foundRecord.ShouldNotBeNull(); - foundRecord.Description.ShouldBe(apiResourceDetails.Description); - foundRecord.DisplayName.ShouldBe(apiResourceDetails.DisplayName); - foreach (String? scope in apiResourceDetails.Scopes){ - foundRecord.Scopes.ShouldContain(scope); - } - - foreach (String? userClaim in apiResourceDetails.UserClaims){ - foundRecord.UserClaims.ShouldContain(userClaim); - } - } - } - - public async Task WhenIGetTheApiResourceWithNameTheApiResourceDetailsAreReturnedAsFollows(List expectedDetails, String apiResourceName, CancellationToken cancellationToken){ - Result? apiResourceDetailsResult = await this.SecurityServiceClient.GetApiResource(apiResourceName, cancellationToken).ConfigureAwait(false); - apiResourceDetailsResult.IsSuccess.ShouldBeTrue(); - - ApiResourceDetails? apiResourceDetails = apiResourceDetailsResult.Data; - ApiResourceDetails expectedRecord = expectedDetails.Single(); - - apiResourceDetails.ShouldNotBeNull(); - apiResourceDetails.Description.ShouldBe(expectedRecord.Description); - apiResourceDetails.DisplayName.ShouldBe(expectedRecord.DisplayName); - foreach (String? scope in expectedRecord.Scopes){ - apiResourceDetails.Scopes.ShouldContain(scope); - } - - foreach (String? userClaim in expectedRecord.UserClaims){ - apiResourceDetails.UserClaims.ShouldContain(userClaim); - } - } - - public async Task WhenIGetTheApiScopesApiScopeDetailsAreReturnedAsFollows(List expectedDetails, CancellationToken cancellationToken){ - Result>? apiScopeDetailsListResult = await this.SecurityServiceClient.GetApiScopes(cancellationToken).ConfigureAwait(false); - apiScopeDetailsListResult.IsSuccess.ShouldBeTrue(); - - List? apiScopeDetailsList = apiScopeDetailsListResult.Data; - foreach (ApiScopeDetails apiScopeDetails in expectedDetails){ - ApiScopeDetails? foundRecord = apiScopeDetailsList.SingleOrDefault(a => a.Name == apiScopeDetails.Name); - foundRecord.ShouldNotBeNull(); - foundRecord.Description.ShouldBe(apiScopeDetails.Description); - foundRecord.DisplayName.ShouldBe(apiScopeDetails.DisplayName); - } - } - - public async Task WhenIGetTheApiScopeWithNameTheApiScopeDetailsAreReturnedAsFollows(List expectedDetails, String apiScopeName, CancellationToken cancellationToken){ - Result? apiScopeDetailsResult = await this.SecurityServiceClient.GetApiScope(apiScopeName, cancellationToken).ConfigureAwait(false); - apiScopeDetailsResult.IsSuccess.ShouldBeTrue(); - ApiScopeDetails? apiScopeDetails = apiScopeDetailsResult.Data; - - ApiScopeDetails expectedRecord = expectedDetails.Single(); - - apiScopeDetails.ShouldNotBeNull(); - apiScopeDetails.Description.ShouldBe(expectedRecord.Description); - apiScopeDetails.DisplayName.ShouldBe(expectedRecord.DisplayName); - } - - public async Task WhenIGetTheClientWithClientIdTheClientDetailsAreReturnedAsFollows(List expectedDetails, String clientId, CancellationToken cancellationToken){ - Result? clientDetailsResult = await this.SecurityServiceClient.GetClient(clientId, CancellationToken.None).ConfigureAwait(false); - clientDetailsResult.IsSuccess.ShouldBeTrue(); - ClientDetails clientDetails = clientDetailsResult.Data; - ClientDetails expectedRecord = expectedDetails.Single(); - - clientDetails.ShouldNotBeNull(); - clientDetails.ClientId.ShouldBe(expectedRecord.ClientId); - clientDetails.ClientName.ShouldBe(expectedRecord.ClientName); - clientDetails.ClientDescription.ShouldBe(expectedRecord.ClientDescription); - foreach (String expectedRecordAllowedGrantType in expectedRecord.AllowedGrantTypes){ - clientDetails.AllowedGrantTypes.ShouldContain(expectedRecordAllowedGrantType); - } - - foreach (String expectedRecordAllowedScope in expectedRecord.AllowedScopes){ - clientDetails.AllowedScopes.ShouldContain(expectedRecordAllowedScope); - } - } - - public async Task WhenIGetTheClientsClientsDetailsAreReturnedAsFollows(List expectedDetails, CancellationToken cancellationToken){ - Result>? clientDetailsListResult = await this.SecurityServiceClient.GetClients(CancellationToken.None).ConfigureAwait(false); - clientDetailsListResult.IsSuccess.ShouldBeTrue(); - List? clientDetailsList = clientDetailsListResult.Data; - foreach (ClientDetails expectedRecord in expectedDetails){ - ClientDetails? foundRecord = clientDetailsList.SingleOrDefault(a => a.ClientId == expectedRecord.ClientId); - foundRecord.ShouldNotBeNull(); - - foundRecord.ClientId.ShouldBe(expectedRecord.ClientId); - foundRecord.ClientName.ShouldBe(expectedRecord.ClientName); - foundRecord.ClientDescription.ShouldBe(expectedRecord.ClientDescription); - foreach (String expectedRecordAllowedGrantType in expectedRecord.AllowedGrantTypes){ - foundRecord.AllowedGrantTypes.ShouldContain(expectedRecordAllowedGrantType); - } - - foreach (String expectedRecordAllowedScope in expectedRecord.AllowedScopes){ - foundRecord.AllowedScopes.ShouldContain(expectedRecordAllowedScope); - } - } - } - - public async Task GivenICreateTheFollowingIdentityResources(List requests, CancellationToken cancellationToken){ - foreach (CreateIdentityResourceRequest createIdentityResourceRequest in requests){ - Result? result = await this.SecurityServiceClient.CreateIdentityResource(createIdentityResourceRequest, cancellationToken).ConfigureAwait(false); - result.IsSuccess.ShouldBeTrue(); - } - } - - public async Task WhenIGetTheIdentityResourceWithNameTheIdentityResourceDetailsAreReturnedAsFollows(List expectedDetails, String identityResourceName, CancellationToken cancellationToken) - { - Result? identityResourceDetailsResult = await this.SecurityServiceClient.GetIdentityResource(identityResourceName, cancellationToken).ConfigureAwait(false); - identityResourceDetailsResult.IsSuccess.ShouldBeTrue(); - IdentityResourceDetails identityResourceDetails = identityResourceDetailsResult.Data; - IdentityResourceDetails expectedRecord = expectedDetails.Single(); - - identityResourceDetails.Name.ShouldBe(expectedRecord.Name); - identityResourceDetails.Description.ShouldBe(expectedRecord.Description); - identityResourceDetails.DisplayName.ShouldBe(expectedRecord.DisplayName); - - foreach (String expectedRecordClaim in expectedRecord.Claims){ - identityResourceDetails.Claims.ShouldContain(expectedRecordClaim); - } - } - - public async Task WhenIGetTheIdentityResourcesIdentityResourceDetailsAreReturnedAsFollows(List expectedDetails, CancellationToken cancellationToken){ - Result>? getIdentityResourcesResult = await this.SecurityServiceClient.GetIdentityResources(CancellationToken.None).ConfigureAwait(false); - getIdentityResourcesResult.IsSuccess.ShouldBeTrue(); - List? identityResourceDetailsList = getIdentityResourcesResult.Data; - foreach (IdentityResourceDetails expectedRecord in expectedDetails){ - IdentityResourceDetails? foundRecord = identityResourceDetailsList.SingleOrDefault(a => a.Name == expectedRecord.Name); - foundRecord.ShouldNotBeNull(); - foundRecord.Name.ShouldBe(expectedRecord.Name); - foundRecord.Description.ShouldBe(expectedRecord.Description); - foundRecord.DisplayName.ShouldBe(expectedRecord.DisplayName); - - foreach (String expectedRecordClaim in expectedRecord.Claims) - { - foundRecord.Claims.ShouldContain(expectedRecordClaim); - } - - } - } - - public async Task> GivenICreateTheFollowingRoles(List requests, CancellationToken cancellationToken) { - List<(String, Guid)> roleList = new List<(String, Guid)>(); - foreach (CreateRoleRequest request in requests){ - Result? result = await this.SecurityServiceClient.CreateRole(request, cancellationToken).ConfigureAwait(false); - result.IsSuccess.ShouldBeTrue(); - } - - Result>? roles = await this.SecurityServiceClient.GetRoles(cancellationToken); - roles.IsSuccess.ShouldBeTrue(); - - foreach (CreateRoleRequest request in requests) { - RoleDetails r = roles.Data.Single(r => r.RoleName == request.RoleName); - roleList.Add((r.RoleName, r.RoleId)); - } - - return roleList; - } - - public async Task WhenIGetTheRoleWithNameTheRoleDetailsAreReturnedAsFollows(List expectedDetails, Guid roleId, CancellationToken cancellationToken) - { - Result? getRoleResult = await this.SecurityServiceClient.GetRole(roleId, cancellationToken).ConfigureAwait(false); - getRoleResult.IsSuccess.ShouldBeTrue(); - RoleDetails roleDetails =getRoleResult.Data; - RoleDetails expectedRecord = expectedDetails.Single(); - - roleDetails.RoleName.ShouldBe(expectedRecord.RoleName); - } - - public async Task WhenIGetTheRolesRolesDetailsAreReturnedAsFollows(List expectedDetails, CancellationToken cancellationToken) - { - Result>? getRolesResult = await this.SecurityServiceClient.GetRoles(CancellationToken.None).ConfigureAwait(false); - getRolesResult.IsSuccess.ShouldBeTrue(); - List? rolesList = getRolesResult.Data; - foreach (RoleDetails expectedRecord in expectedDetails) - { - RoleDetails? foundRecord = rolesList.SingleOrDefault(a => a.RoleName == expectedRecord.RoleName); - foundRecord.ShouldNotBeNull(); - foundRecord.RoleName.ShouldBe(expectedRecord.RoleName); - } - } - - public async Task> GivenICreateTheFollowingUsers(List requests, CancellationToken cancellationToken){ - List<(String, Guid)> results = new List<(String, Guid)>(); - foreach (CreateUserRequest createUserRequest in requests){ - Result? result = await this.SecurityServiceClient.CreateUser(createUserRequest, cancellationToken).ConfigureAwait(false); - result.IsSuccess.ShouldBeTrue(); - - Result>? user = await this.SecurityServiceClient.GetUsers(createUserRequest.EmailAddress, cancellationToken); - user.IsSuccess.ShouldBeTrue(); - - results.Add((createUserRequest.EmailAddress, user.Data.Single().UserId)); - } - return results; - } - - public async Task WhenIGetTheUsersUsersDetailsAreReturnedAsFollows(List expectedDetails, CancellationToken cancellationToken) - { - Result>? getUsersResult = await this.SecurityServiceClient.GetUsers(String.Empty, CancellationToken.None).ConfigureAwait(false); - getUsersResult.IsSuccess.ShouldBeTrue(); - List? usersList = getUsersResult.Data; - foreach (UserDetails expectedRecord in expectedDetails) - { - UserDetails? foundRecord = usersList.SingleOrDefault(a => a.UserName == expectedRecord.UserName); - foundRecord.ShouldNotBeNull(); - foundRecord.UserName.ShouldBe(expectedRecord.UserName); - foundRecord.EmailAddress.ShouldBe(expectedRecord.EmailAddress); - foundRecord.PhoneNumber.ShouldBe(expectedRecord.PhoneNumber); - foreach (String expectedRecordRole in expectedRecord.Roles){ - foundRecord.Roles.ShouldContain(expectedRecordRole); - } - - foreach (KeyValuePair expectedRecordClaim in expectedRecord.Claims){ - foundRecord.Claims.ContainsKey(expectedRecordClaim.Key).ShouldBeTrue(); - String? claim = foundRecord.Claims[expectedRecordClaim.Key]; - claim.ShouldBe(expectedRecordClaim.Value); - } - } - } - - public async Task WhenIGetTheUserWithUserNameTheUserDetailsAreReturnedAsFollows(List expectedDetails, Guid userId, CancellationToken cancellationToken){ - var userDetails = await this.SecurityServiceClient.GetUser(userId, CancellationToken.None).ConfigureAwait(false); - var expectedRecord = expectedDetails.Single(); - - userDetails.IsSuccess.ShouldBeTrue(); - userDetails.Data.ShouldNotBeNull(); - userDetails.Data.UserName.ShouldBe(expectedRecord.UserName); - userDetails.Data.EmailAddress.ShouldBe(expectedRecord.EmailAddress); - userDetails.Data.PhoneNumber.ShouldBe(expectedRecord.PhoneNumber); - foreach (String expectedRecordRole in expectedRecord.Roles){ - userDetails.Data.Roles.ShouldContain(expectedRecordRole); - } - - foreach (KeyValuePair expectedRecordClaim in expectedRecord.Claims){ - userDetails.Data.Claims.ContainsKey(expectedRecordClaim.Key).ShouldBeTrue(); - String? claim = userDetails.Data.Claims[expectedRecordClaim.Key]; - claim.ShouldBe(expectedRecordClaim.Value); - } - userDetails.Data.RegistrationDateTime.Date.ShouldBe(expectedRecord.RegistrationDateTime.Date); - } - -} \ No newline at end of file diff --git a/archive/SecurityService.IntegrationTests/ApiResource/ApiResource.feature b/archive/SecurityService.IntegrationTests/ApiResource/ApiResource.feature deleted file mode 100644 index 39956ef9..00000000 --- a/archive/SecurityService.IntegrationTests/ApiResource/ApiResource.feature +++ /dev/null @@ -1,19 +0,0 @@ -@base @apiresources -Feature: ApiResource - -@PRTest -Scenario: Get Api Resources -Given I create the following api resources -| Name | DisplayName | Description | Secret | Scopes | UserClaims | -| testresource1 | Test Resource1 | A resource for testing 1 | secret1 | Scope1,Scope2 | Claim1,Claim2 | -| testresource2 | Test Resource2 | A resource for testing 2 | secret2 | Scope1,Scope2 | Claim1,Claim2 | -When I get the api resource with name 'testresource1' the api resource details are returned as follows -| Name | DisplayName | Description | Scopes | UserClaims | -| testresource1 | Test Resource1 | A resource for testing 1 | Scope1,Scope2 | Claim1,Claim2 | -When I get the api resource with name 'testresource2' the api resource details are returned as follows -| Name | DisplayName | Description | Scopes | UserClaims | -| testresource2 | Test Resource2 | A resource for testing 2 | Scope1,Scope2 | Claim1,Claim2 | -When I get the api resources 2 api resource details are returned as follows -| Name | DisplayName | Description | Scopes | UserClaims | -| testresource1 | Test Resource1 | A resource for testing 1 | Scope1,Scope2 | Claim1,Claim2 | -| testresource2 | Test Resource2 | A resource for testing 2 | Scope1,Scope2 | Claim1,Claim2 | \ No newline at end of file diff --git a/archive/SecurityService.IntegrationTests/ApiResource/ApiResource.feature.cs b/archive/SecurityService.IntegrationTests/ApiResource/ApiResource.feature.cs deleted file mode 100644 index 974e044f..00000000 --- a/archive/SecurityService.IntegrationTests/ApiResource/ApiResource.feature.cs +++ /dev/null @@ -1,220 +0,0 @@ -// ------------------------------------------------------------------------------ -// -// This code was generated by Reqnroll (https://reqnroll.net/). -// Reqnroll Version:3.0.0.0 -// Reqnroll Generator Version:3.0.0.0 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -// ------------------------------------------------------------------------------ -#region Designer generated code -#pragma warning disable -using Reqnroll; -namespace SecurityService.IntegrationTests.ApiResource -{ - - - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Reqnroll", "3.0.0.0")] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::NUnit.Framework.TestFixtureAttribute()] - [global::NUnit.Framework.DescriptionAttribute("ApiResource")] - [global::NUnit.Framework.FixtureLifeCycleAttribute(global::NUnit.Framework.LifeCycle.InstancePerTestCase)] - [global::NUnit.Framework.CategoryAttribute("base")] - [global::NUnit.Framework.CategoryAttribute("apiresources")] - public partial class ApiResourceFeature - { - - private global::Reqnroll.ITestRunner testRunner; - - private static string[] featureTags = new string[] { - "base", - "apiresources"}; - - private static global::Reqnroll.FeatureInfo featureInfo = new global::Reqnroll.FeatureInfo(new global::System.Globalization.CultureInfo("en-US"), "ApiResource", "ApiResource", null, global::Reqnroll.ProgrammingLanguage.CSharp, featureTags, InitializeCucumberMessages()); - -#line 1 "ApiResource.feature" -#line hidden - - [global::NUnit.Framework.OneTimeSetUpAttribute()] - public static async global::System.Threading.Tasks.Task FeatureSetupAsync() - { - } - - [global::NUnit.Framework.OneTimeTearDownAttribute()] - public static async global::System.Threading.Tasks.Task FeatureTearDownAsync() - { - await global::Reqnroll.TestRunnerManager.ReleaseFeatureAsync(featureInfo); - } - - [global::NUnit.Framework.SetUpAttribute()] - public async global::System.Threading.Tasks.Task TestInitializeAsync() - { - testRunner = global::Reqnroll.TestRunnerManager.GetTestRunnerForAssembly(featureHint: featureInfo); - try - { - if (((testRunner.FeatureContext != null) - && (testRunner.FeatureContext.FeatureInfo.Equals(featureInfo) == false))) - { - await testRunner.OnFeatureEndAsync(); - } - } - finally - { - if (((testRunner.FeatureContext != null) - && testRunner.FeatureContext.BeforeFeatureHookFailed)) - { - throw new global::Reqnroll.ReqnrollException("Scenario skipped because of previous before feature hook error"); - } - if ((testRunner.FeatureContext == null)) - { - await testRunner.OnFeatureStartAsync(featureInfo); - } - } - } - - [global::NUnit.Framework.TearDownAttribute()] - public async global::System.Threading.Tasks.Task TestTearDownAsync() - { - if ((testRunner == null)) - { - return; - } - try - { - await testRunner.OnScenarioEndAsync(); - } - finally - { - global::Reqnroll.TestRunnerManager.ReleaseTestRunner(testRunner); - testRunner = null; - } - } - - public void ScenarioInitialize(global::Reqnroll.ScenarioInfo scenarioInfo, global::Reqnroll.RuleInfo ruleInfo) - { - testRunner.OnScenarioInitialize(scenarioInfo, ruleInfo); - testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(global::NUnit.Framework.TestContext.CurrentContext); - } - - public async global::System.Threading.Tasks.Task ScenarioStartAsync() - { - await testRunner.OnScenarioStartAsync(); - } - - public async global::System.Threading.Tasks.Task ScenarioCleanupAsync() - { - await testRunner.CollectScenarioErrorsAsync(); - } - - private static global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages InitializeCucumberMessages() - { - return new global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages("ApiResource/ApiResource.feature.ndjson", 3); - } - - [global::NUnit.Framework.TestAttribute()] - [global::NUnit.Framework.DescriptionAttribute("Get Api Resources")] - [global::NUnit.Framework.CategoryAttribute("PRTest")] - public async global::System.Threading.Tasks.Task GetApiResources() - { - string[] tagsOfScenario = new string[] { - "PRTest"}; - global::System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new global::System.Collections.Specialized.OrderedDictionary(); - string pickleIndex = "0"; - global::Reqnroll.ScenarioInfo scenarioInfo = new global::Reqnroll.ScenarioInfo("Get Api Resources", null, tagsOfScenario, argumentsOfScenario, featureTags, pickleIndex); - string[] tagsOfRule = ((string[])(null)); - global::Reqnroll.RuleInfo ruleInfo = null; -#line 5 -this.ScenarioInitialize(scenarioInfo, ruleInfo); -#line hidden - if ((global::Reqnroll.TagHelper.ContainsIgnoreTag(scenarioInfo.CombinedTags) || global::Reqnroll.TagHelper.ContainsIgnoreTag(featureTags))) - { - await testRunner.SkipScenarioAsync(); - } - else - { - await this.ScenarioStartAsync(); - global::Reqnroll.Table table1 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Description", - "Secret", - "Scopes", - "UserClaims"}); - table1.AddRow(new string[] { - "testresource1", - "Test Resource1", - "A resource for testing 1", - "secret1", - "Scope1,Scope2", - "Claim1,Claim2"}); - table1.AddRow(new string[] { - "testresource2", - "Test Resource2", - "A resource for testing 2", - "secret2", - "Scope1,Scope2", - "Claim1,Claim2"}); -#line 6 -await testRunner.GivenAsync("I create the following api resources", ((string)(null)), table1, "Given "); -#line hidden - global::Reqnroll.Table table2 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Description", - "Scopes", - "UserClaims"}); - table2.AddRow(new string[] { - "testresource1", - "Test Resource1", - "A resource for testing 1", - "Scope1,Scope2", - "Claim1,Claim2"}); -#line 10 -await testRunner.WhenAsync("I get the api resource with name \'testresource1\' the api resource details are ret" + - "urned as follows", ((string)(null)), table2, "When "); -#line hidden - global::Reqnroll.Table table3 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Description", - "Scopes", - "UserClaims"}); - table3.AddRow(new string[] { - "testresource2", - "Test Resource2", - "A resource for testing 2", - "Scope1,Scope2", - "Claim1,Claim2"}); -#line 13 -await testRunner.WhenAsync("I get the api resource with name \'testresource2\' the api resource details are ret" + - "urned as follows", ((string)(null)), table3, "When "); -#line hidden - global::Reqnroll.Table table4 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Description", - "Scopes", - "UserClaims"}); - table4.AddRow(new string[] { - "testresource1", - "Test Resource1", - "A resource for testing 1", - "Scope1,Scope2", - "Claim1,Claim2"}); - table4.AddRow(new string[] { - "testresource2", - "Test Resource2", - "A resource for testing 2", - "Scope1,Scope2", - "Claim1,Claim2"}); -#line 16 -await testRunner.WhenAsync("I get the api resources 2 api resource details are returned as follows", ((string)(null)), table4, "When "); -#line hidden - } - await this.ScenarioCleanupAsync(); - } - } -} -#pragma warning restore -#endregion diff --git a/archive/SecurityService.IntegrationTests/ApiResource/ApiResourceSteps.cs b/archive/SecurityService.IntegrationTests/ApiResource/ApiResourceSteps.cs deleted file mode 100644 index 5090b4da..00000000 --- a/archive/SecurityService.IntegrationTests/ApiResource/ApiResourceSteps.cs +++ /dev/null @@ -1,94 +0,0 @@ -namespace SecurityService.IntegrationTests.ApiResource -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Net.Http; - using System.Text; - using System.Threading; - using System.Threading.Tasks; - using Clients; - using DataTransferObjects.Requests; - using DataTransferObjects.Responses; - using IntegrationTesting.Helpers; - using IntergrationTests.Common; - using Newtonsoft.Json; - using Reqnroll; - using Shouldly; - - /// - /// - /// - [Binding] - [Scope(Tag = "apiresources")] - public class ApiResourceSteps - { - #region Fields - - /// - /// The testing context - /// - private readonly TestingContext TestingContext; - - private readonly SecurityServiceSteps SecurityServiceSteps; - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The testing context. - public ApiResourceSteps(TestingContext testingContext) - { - this.TestingContext = testingContext; - this.SecurityServiceSteps = new SecurityServiceSteps(this.TestingContext.DockerHelper.SecurityServiceClient); - } - - #endregion - - #region Methods - - /// - /// Givens the i create the following API resources. - /// - /// The table. - [Given(@"I create the following api resources")] - public async Task GivenICreateTheFollowingApiResources(Table table) - { - List requests = table.Rows.ToCreateApiResourceRequests(); - await this.SecurityServiceSteps.GivenTheFollowingApiResourcesExist(requests); - } - - /// - /// Whens the i get the API resources API resource details are returned as follows. - /// - /// The number of API resources. - /// The table. - [When(@"I get the api resources (.*) api resource details are returned as follows")] - public async Task WhenIGetTheApiResourcesApiResourceDetailsAreReturnedAsFollows(Int32 numberOfApiResources, - Table table){ - List expectedDetails = table.Rows.ToApiResourceDetails(); - await this.SecurityServiceSteps.WhenIGetTheApiResourcesApiResourceDetailsAreReturnedAsFollows(expectedDetails, CancellationToken.None); - } - - /// - /// Whens the i get the API resource with name the API resource details are returned as follows. - /// - /// Name of the API resource. - /// The table. - [When(@"I get the api resource with name '(.*)' the api resource details are returned as follows")] - public async Task WhenIGetTheApiResourceWithNameTheApiResourceDetailsAreReturnedAsFollows(String apiResourceName, - Table table) - { - List expectedDetails = table.Rows.ToApiResourceDetails(); - await this.SecurityServiceSteps.WhenIGetTheApiResourceWithNameTheApiResourceDetailsAreReturnedAsFollows(expectedDetails, apiResourceName, CancellationToken.None); - } - - - - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.IntegrationTests/ApiScopes/ApiScope.feature b/archive/SecurityService.IntegrationTests/ApiScopes/ApiScope.feature deleted file mode 100644 index b21719d3..00000000 --- a/archive/SecurityService.IntegrationTests/ApiScopes/ApiScope.feature +++ /dev/null @@ -1,19 +0,0 @@ -@base @apiscopes -Feature: ApiScope - -@PRTest -Scenario: Get Api Scopes - Given I create the following api scopes - | Name | DisplayName | Description | - | testscope1 | Test Scope1 | A scope for testing 1 | - | testscope2 | Test Scope2 | A scope for testing 2 | - When I get the api scope with name 'testscope1' the api scope details are returned as follows - | Name | DisplayName | Description | - | testscope1 | Test Scope1 | A scope for testing 1 | - When I get the api scope with name 'testscope2' the api scope details are returned as follows - | Name | DisplayName | Description | - | testscope2 | Test Scope2 | A scope for testing 2 | - When I get the api scopes 2 api scope details are returned as follows - | Name | DisplayName | Description | - | testscope1 | Test Scope1 | A scope for testing 1 | - | testscope2 | Test Scope2 | A scope for testing 2 | \ No newline at end of file diff --git a/archive/SecurityService.IntegrationTests/ApiScopes/ApiScope.feature.cs b/archive/SecurityService.IntegrationTests/ApiScopes/ApiScope.feature.cs deleted file mode 100644 index 69a75944..00000000 --- a/archive/SecurityService.IntegrationTests/ApiScopes/ApiScope.feature.cs +++ /dev/null @@ -1,197 +0,0 @@ -// ------------------------------------------------------------------------------ -// -// This code was generated by Reqnroll (https://reqnroll.net/). -// Reqnroll Version:3.0.0.0 -// Reqnroll Generator Version:3.0.0.0 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -// ------------------------------------------------------------------------------ -#region Designer generated code -#pragma warning disable -using Reqnroll; -namespace SecurityService.IntegrationTests.ApiScopes -{ - - - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Reqnroll", "3.0.0.0")] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::NUnit.Framework.TestFixtureAttribute()] - [global::NUnit.Framework.DescriptionAttribute("ApiScope")] - [global::NUnit.Framework.FixtureLifeCycleAttribute(global::NUnit.Framework.LifeCycle.InstancePerTestCase)] - [global::NUnit.Framework.CategoryAttribute("base")] - [global::NUnit.Framework.CategoryAttribute("apiscopes")] - public partial class ApiScopeFeature - { - - private global::Reqnroll.ITestRunner testRunner; - - private static string[] featureTags = new string[] { - "base", - "apiscopes"}; - - private static global::Reqnroll.FeatureInfo featureInfo = new global::Reqnroll.FeatureInfo(new global::System.Globalization.CultureInfo("en-US"), "ApiScopes", "ApiScope", null, global::Reqnroll.ProgrammingLanguage.CSharp, featureTags, InitializeCucumberMessages()); - -#line 1 "ApiScope.feature" -#line hidden - - [global::NUnit.Framework.OneTimeSetUpAttribute()] - public static async global::System.Threading.Tasks.Task FeatureSetupAsync() - { - } - - [global::NUnit.Framework.OneTimeTearDownAttribute()] - public static async global::System.Threading.Tasks.Task FeatureTearDownAsync() - { - await global::Reqnroll.TestRunnerManager.ReleaseFeatureAsync(featureInfo); - } - - [global::NUnit.Framework.SetUpAttribute()] - public async global::System.Threading.Tasks.Task TestInitializeAsync() - { - testRunner = global::Reqnroll.TestRunnerManager.GetTestRunnerForAssembly(featureHint: featureInfo); - try - { - if (((testRunner.FeatureContext != null) - && (testRunner.FeatureContext.FeatureInfo.Equals(featureInfo) == false))) - { - await testRunner.OnFeatureEndAsync(); - } - } - finally - { - if (((testRunner.FeatureContext != null) - && testRunner.FeatureContext.BeforeFeatureHookFailed)) - { - throw new global::Reqnroll.ReqnrollException("Scenario skipped because of previous before feature hook error"); - } - if ((testRunner.FeatureContext == null)) - { - await testRunner.OnFeatureStartAsync(featureInfo); - } - } - } - - [global::NUnit.Framework.TearDownAttribute()] - public async global::System.Threading.Tasks.Task TestTearDownAsync() - { - if ((testRunner == null)) - { - return; - } - try - { - await testRunner.OnScenarioEndAsync(); - } - finally - { - global::Reqnroll.TestRunnerManager.ReleaseTestRunner(testRunner); - testRunner = null; - } - } - - public void ScenarioInitialize(global::Reqnroll.ScenarioInfo scenarioInfo, global::Reqnroll.RuleInfo ruleInfo) - { - testRunner.OnScenarioInitialize(scenarioInfo, ruleInfo); - testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(global::NUnit.Framework.TestContext.CurrentContext); - } - - public async global::System.Threading.Tasks.Task ScenarioStartAsync() - { - await testRunner.OnScenarioStartAsync(); - } - - public async global::System.Threading.Tasks.Task ScenarioCleanupAsync() - { - await testRunner.CollectScenarioErrorsAsync(); - } - - private static global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages InitializeCucumberMessages() - { - return new global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages("ApiScopes/ApiScope.feature.ndjson", 3); - } - - [global::NUnit.Framework.TestAttribute()] - [global::NUnit.Framework.DescriptionAttribute("Get Api Scopes")] - [global::NUnit.Framework.CategoryAttribute("PRTest")] - public async global::System.Threading.Tasks.Task GetApiScopes() - { - string[] tagsOfScenario = new string[] { - "PRTest"}; - global::System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new global::System.Collections.Specialized.OrderedDictionary(); - string pickleIndex = "0"; - global::Reqnroll.ScenarioInfo scenarioInfo = new global::Reqnroll.ScenarioInfo("Get Api Scopes", null, tagsOfScenario, argumentsOfScenario, featureTags, pickleIndex); - string[] tagsOfRule = ((string[])(null)); - global::Reqnroll.RuleInfo ruleInfo = null; -#line 5 -this.ScenarioInitialize(scenarioInfo, ruleInfo); -#line hidden - if ((global::Reqnroll.TagHelper.ContainsIgnoreTag(scenarioInfo.CombinedTags) || global::Reqnroll.TagHelper.ContainsIgnoreTag(featureTags))) - { - await testRunner.SkipScenarioAsync(); - } - else - { - await this.ScenarioStartAsync(); - global::Reqnroll.Table table5 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Description"}); - table5.AddRow(new string[] { - "testscope1", - "Test Scope1", - "A scope for testing 1"}); - table5.AddRow(new string[] { - "testscope2", - "Test Scope2", - "A scope for testing 2"}); -#line 6 - await testRunner.GivenAsync("I create the following api scopes", ((string)(null)), table5, "Given "); -#line hidden - global::Reqnroll.Table table6 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Description"}); - table6.AddRow(new string[] { - "testscope1", - "Test Scope1", - "A scope for testing 1"}); -#line 10 - await testRunner.WhenAsync("I get the api scope with name \'testscope1\' the api scope details are returned as " + - "follows", ((string)(null)), table6, "When "); -#line hidden - global::Reqnroll.Table table7 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Description"}); - table7.AddRow(new string[] { - "testscope2", - "Test Scope2", - "A scope for testing 2"}); -#line 13 - await testRunner.WhenAsync("I get the api scope with name \'testscope2\' the api scope details are returned as " + - "follows", ((string)(null)), table7, "When "); -#line hidden - global::Reqnroll.Table table8 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Description"}); - table8.AddRow(new string[] { - "testscope1", - "Test Scope1", - "A scope for testing 1"}); - table8.AddRow(new string[] { - "testscope2", - "Test Scope2", - "A scope for testing 2"}); -#line 16 - await testRunner.WhenAsync("I get the api scopes 2 api scope details are returned as follows", ((string)(null)), table8, "When "); -#line hidden - } - await this.ScenarioCleanupAsync(); - } - } -} -#pragma warning restore -#endregion diff --git a/archive/SecurityService.IntegrationTests/ApiScopes/ApiScopeSteps.cs b/archive/SecurityService.IntegrationTests/ApiScopes/ApiScopeSteps.cs deleted file mode 100644 index 80127094..00000000 --- a/archive/SecurityService.IntegrationTests/ApiScopes/ApiScopeSteps.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; - -namespace SecurityService.IntegrationTests.ApiScopes -{ - using System.Collections.Generic; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - using Clients; - using DataTransferObjects.Requests; - using DataTransferObjects.Responses; - using IntegrationTesting.Helpers; - using IntergrationTests.Common; - using Reqnroll; - using Shouldly; - - /// - /// - /// - [Binding] - public class ApiScopeSteps - { - #region Fields - - /// - /// The testing context - /// - private readonly TestingContext TestingContext; - - #endregion - - private readonly SecurityServiceSteps SecurityServiceSteps; - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The testing context. - public ApiScopeSteps(TestingContext testingContext) - { - this.TestingContext = testingContext; - this.SecurityServiceSteps = new SecurityServiceSteps(this.TestingContext.DockerHelper.SecurityServiceClient); - } - - #endregion - - /// - /// Givens the i create the following API scopes. - /// - /// The table. - [Given(@"I create the following api scopes")] - public async Task GivenICreateTheFollowingApiScopes(DataTable table) - { - List requests = table.Rows.ToCreateApiScopeRequests(); - await this.SecurityServiceSteps.GivenICreateTheFollowingApiScopes(requests); - } - - /// - /// Whens the i get the API scope with name the API scope details are returned as follows. - /// - /// Name of the API scope. - /// The table. - [When(@"I get the api scope with name '(.*)' the api scope details are returned as follows")] - public async Task WhenIGetTheApiScopeWithNameTheApiScopeDetailsAreReturnedAsFollows(String apiScopeName, DataTable table) - { - List expectedDetails = table.Rows.ToApiScopeDetails(); - await this.SecurityServiceSteps.WhenIGetTheApiScopeWithNameTheApiScopeDetailsAreReturnedAsFollows(expectedDetails,apiScopeName, CancellationToken.None); - - } - - /// - /// Whens the i get the API scopes API scope details are returned as follows. - /// - /// The number of API scopes. - /// The table. - [When(@"I get the api scopes (.*) api scope details are returned as follows")] - public async Task WhenIGetTheApiScopesApiScopeDetailsAreReturnedAsFollows(Int32 numberOfApiScopes, DataTable table) - { - List expectedDetails = table.Rows.ToApiScopeDetails(); - await this.SecurityServiceSteps.WhenIGetTheApiScopesApiScopeDetailsAreReturnedAsFollows(expectedDetails, CancellationToken.None); - } - } -} diff --git a/archive/SecurityService.IntegrationTests/AssemblyInfo.cs b/archive/SecurityService.IntegrationTests/AssemblyInfo.cs deleted file mode 100644 index c2a40fbb..00000000 --- a/archive/SecurityService.IntegrationTests/AssemblyInfo.cs +++ /dev/null @@ -1,20 +0,0 @@ -using NUnit.Framework; -using System.Runtime.InteropServices; - -// In SDK-style projects such as this one, several assembly attributes that were historically -// defined in this file are now automatically added during build and populated with -// values defined in project properties. For details of which attributes are included -// and how to customise this process see: https://aka.ms/assembly-info-properties - - -// Setting ComVisible to false makes the types in this assembly not visible to COM -// components. If you need to access a type in this assembly from COM, set the ComVisible -// attribute to true on that type. - -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM. - -[assembly: Guid("70c8d747-842f-4d4d-8c60-f7c46bf81088")] -[assembly: LevelOfParallelism(2)] -[assembly: Parallelizable(ParallelScope.Fixtures)] diff --git a/archive/SecurityService.IntegrationTests/Clients/Clients.feature b/archive/SecurityService.IntegrationTests/Clients/Clients.feature deleted file mode 100644 index 2f5e2385..00000000 --- a/archive/SecurityService.IntegrationTests/Clients/Clients.feature +++ /dev/null @@ -1,23 +0,0 @@ -@base @clients -Feature: Clients - -@PRTest -Scenario: Get Clients - Given I create the following clients - | ClientId | Name | Description | Secret | Scopes | GrantTypes | RedirectUris | PostLogoutRedirectUris | RequireConsent | - | testclient1 | Test Client 1 | A test client 1 | secret1 | Scope1, Scope2 | client_credentials | | | | - | testclient2 | Test Client 2 | A second test client | Secret2 | Scope1, Scope2 | hybrid | http://localhost/signin-oidc | http://localhost/signout-oidc | true | - - When I get the client with client id 'testclient1' the client details are returned as follows - | ClientId | Name | Description | Scopes | GrantTypes | RedirectUris | PostLogoutRedirectUris | RequireConsent | - | testclient1 | Test Client 1 | A test client 1 | Scope1, Scope2 | client_credentials | | | | - - When I get the client with client id 'testclient2' the client details are returned as follows - | ClientId | Name | Description | Scopes | GrantTypes | RedirectUris | PostLogoutRedirectUris | RequireConsent | - | testclient2 | Test Client 2 | A second test client | Scope1, Scope2 | hybrid | http://localhost/signin-oidc | http://localhost/signout-oidc | true | - - - When I get the clients 2 clients details are returned as follows - | ClientId | Name | Description | Scopes | GrantTypes | RedirectUris | PostLogoutRedirectUris | RequireConsent | - | testclient1 | Test Client 1 | A test client 1 | Scope1, Scope2 | client_credentials | | | | - | testclient2 | Test Client 2 | A second test client | Scope1, Scope2 | hybrid | http://localhost/signin-oidc | http://localhost/signout-oidc | true | \ No newline at end of file diff --git a/archive/SecurityService.IntegrationTests/Clients/Clients.feature.cs b/archive/SecurityService.IntegrationTests/Clients/Clients.feature.cs deleted file mode 100644 index 162235ff..00000000 --- a/archive/SecurityService.IntegrationTests/Clients/Clients.feature.cs +++ /dev/null @@ -1,250 +0,0 @@ -// ------------------------------------------------------------------------------ -// -// This code was generated by Reqnroll (https://reqnroll.net/). -// Reqnroll Version:3.0.0.0 -// Reqnroll Generator Version:3.0.0.0 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -// ------------------------------------------------------------------------------ -#region Designer generated code -#pragma warning disable -using Reqnroll; -namespace SecurityService.IntegrationTests.Clients -{ - - - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Reqnroll", "3.0.0.0")] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::NUnit.Framework.TestFixtureAttribute()] - [global::NUnit.Framework.DescriptionAttribute("Clients")] - [global::NUnit.Framework.FixtureLifeCycleAttribute(global::NUnit.Framework.LifeCycle.InstancePerTestCase)] - [global::NUnit.Framework.CategoryAttribute("base")] - [global::NUnit.Framework.CategoryAttribute("clients")] - public partial class ClientsFeature - { - - private global::Reqnroll.ITestRunner testRunner; - - private static string[] featureTags = new string[] { - "base", - "clients"}; - - private static global::Reqnroll.FeatureInfo featureInfo = new global::Reqnroll.FeatureInfo(new global::System.Globalization.CultureInfo("en-US"), "Clients", "Clients", null, global::Reqnroll.ProgrammingLanguage.CSharp, featureTags, InitializeCucumberMessages()); - -#line 1 "Clients.feature" -#line hidden - - [global::NUnit.Framework.OneTimeSetUpAttribute()] - public static async global::System.Threading.Tasks.Task FeatureSetupAsync() - { - } - - [global::NUnit.Framework.OneTimeTearDownAttribute()] - public static async global::System.Threading.Tasks.Task FeatureTearDownAsync() - { - await global::Reqnroll.TestRunnerManager.ReleaseFeatureAsync(featureInfo); - } - - [global::NUnit.Framework.SetUpAttribute()] - public async global::System.Threading.Tasks.Task TestInitializeAsync() - { - testRunner = global::Reqnroll.TestRunnerManager.GetTestRunnerForAssembly(featureHint: featureInfo); - try - { - if (((testRunner.FeatureContext != null) - && (testRunner.FeatureContext.FeatureInfo.Equals(featureInfo) == false))) - { - await testRunner.OnFeatureEndAsync(); - } - } - finally - { - if (((testRunner.FeatureContext != null) - && testRunner.FeatureContext.BeforeFeatureHookFailed)) - { - throw new global::Reqnroll.ReqnrollException("Scenario skipped because of previous before feature hook error"); - } - if ((testRunner.FeatureContext == null)) - { - await testRunner.OnFeatureStartAsync(featureInfo); - } - } - } - - [global::NUnit.Framework.TearDownAttribute()] - public async global::System.Threading.Tasks.Task TestTearDownAsync() - { - if ((testRunner == null)) - { - return; - } - try - { - await testRunner.OnScenarioEndAsync(); - } - finally - { - global::Reqnroll.TestRunnerManager.ReleaseTestRunner(testRunner); - testRunner = null; - } - } - - public void ScenarioInitialize(global::Reqnroll.ScenarioInfo scenarioInfo, global::Reqnroll.RuleInfo ruleInfo) - { - testRunner.OnScenarioInitialize(scenarioInfo, ruleInfo); - testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(global::NUnit.Framework.TestContext.CurrentContext); - } - - public async global::System.Threading.Tasks.Task ScenarioStartAsync() - { - await testRunner.OnScenarioStartAsync(); - } - - public async global::System.Threading.Tasks.Task ScenarioCleanupAsync() - { - await testRunner.CollectScenarioErrorsAsync(); - } - - private static global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages InitializeCucumberMessages() - { - return new global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages("Clients/Clients.feature.ndjson", 3); - } - - [global::NUnit.Framework.TestAttribute()] - [global::NUnit.Framework.DescriptionAttribute("Get Clients")] - [global::NUnit.Framework.CategoryAttribute("PRTest")] - public async global::System.Threading.Tasks.Task GetClients() - { - string[] tagsOfScenario = new string[] { - "PRTest"}; - global::System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new global::System.Collections.Specialized.OrderedDictionary(); - string pickleIndex = "0"; - global::Reqnroll.ScenarioInfo scenarioInfo = new global::Reqnroll.ScenarioInfo("Get Clients", null, tagsOfScenario, argumentsOfScenario, featureTags, pickleIndex); - string[] tagsOfRule = ((string[])(null)); - global::Reqnroll.RuleInfo ruleInfo = null; -#line 5 -this.ScenarioInitialize(scenarioInfo, ruleInfo); -#line hidden - if ((global::Reqnroll.TagHelper.ContainsIgnoreTag(scenarioInfo.CombinedTags) || global::Reqnroll.TagHelper.ContainsIgnoreTag(featureTags))) - { - await testRunner.SkipScenarioAsync(); - } - else - { - await this.ScenarioStartAsync(); - global::Reqnroll.Table table9 = new global::Reqnroll.Table(new string[] { - "ClientId", - "Name", - "Description", - "Secret", - "Scopes", - "GrantTypes", - "RedirectUris", - "PostLogoutRedirectUris", - "RequireConsent"}); - table9.AddRow(new string[] { - "testclient1", - "Test Client 1", - "A test client 1", - "secret1", - "Scope1, Scope2", - "client_credentials", - "", - "", - ""}); - table9.AddRow(new string[] { - "testclient2", - "Test Client 2", - "A second test client", - "Secret2", - "Scope1, Scope2", - "hybrid", - "http://localhost/signin-oidc", - "http://localhost/signout-oidc", - "true"}); -#line 6 - await testRunner.GivenAsync("I create the following clients", ((string)(null)), table9, "Given "); -#line hidden - global::Reqnroll.Table table10 = new global::Reqnroll.Table(new string[] { - "ClientId", - "Name", - "Description", - "Scopes", - "GrantTypes", - "RedirectUris", - "PostLogoutRedirectUris", - "RequireConsent"}); - table10.AddRow(new string[] { - "testclient1", - "Test Client 1", - "A test client 1", - "Scope1, Scope2", - "client_credentials", - "", - "", - ""}); -#line 11 - await testRunner.WhenAsync("I get the client with client id \'testclient1\' the client details are returned as " + - "follows", ((string)(null)), table10, "When "); -#line hidden - global::Reqnroll.Table table11 = new global::Reqnroll.Table(new string[] { - "ClientId", - "Name", - "Description", - "Scopes", - "GrantTypes", - "RedirectUris", - "PostLogoutRedirectUris", - "RequireConsent"}); - table11.AddRow(new string[] { - "testclient2", - "Test Client 2", - "A second test client", - "Scope1, Scope2", - "hybrid", - "http://localhost/signin-oidc", - "http://localhost/signout-oidc", - "true"}); -#line 15 - await testRunner.WhenAsync("I get the client with client id \'testclient2\' the client details are returned as " + - "follows", ((string)(null)), table11, "When "); -#line hidden - global::Reqnroll.Table table12 = new global::Reqnroll.Table(new string[] { - "ClientId", - "Name", - "Description", - "Scopes", - "GrantTypes", - "RedirectUris", - "PostLogoutRedirectUris", - "RequireConsent"}); - table12.AddRow(new string[] { - "testclient1", - "Test Client 1", - "A test client 1", - "Scope1, Scope2", - "client_credentials", - "", - "", - ""}); - table12.AddRow(new string[] { - "testclient2", - "Test Client 2", - "A second test client", - "Scope1, Scope2", - "hybrid", - "http://localhost/signin-oidc", - "http://localhost/signout-oidc", - "true"}); -#line 20 - await testRunner.WhenAsync("I get the clients 2 clients details are returned as follows", ((string)(null)), table12, "When "); -#line hidden - } - await this.ScenarioCleanupAsync(); - } - } -} -#pragma warning restore -#endregion diff --git a/archive/SecurityService.IntegrationTests/Clients/ClientsSteps.cs b/archive/SecurityService.IntegrationTests/Clients/ClientsSteps.cs deleted file mode 100644 index 11481c3d..00000000 --- a/archive/SecurityService.IntegrationTests/Clients/ClientsSteps.cs +++ /dev/null @@ -1,91 +0,0 @@ -namespace SecurityService.IntegrationTests.Clients -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Net.Http; - using System.Text; - using System.Threading; - using System.Threading.Tasks; - using DataTransferObjects; - using DataTransferObjects.Requests; - using DataTransferObjects.Responses; - using IntegrationTesting.Helpers; - using IntergrationTests.Common; - using Reqnroll; - - /// - /// - /// - [Binding] - [Scope(Tag = "clients")] - public class ClientsSteps - { - #region Fields - - /// - /// The testing context - /// - private readonly TestingContext TestingContext; - - private readonly SecurityServiceSteps SecurityServiceSteps; - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The testing context. - public ClientsSteps(TestingContext testingContext) - { - this.TestingContext = testingContext; - this.SecurityServiceSteps = new SecurityServiceSteps(this.TestingContext.DockerHelper.SecurityServiceClient); - } - - #endregion - - #region Methods - - /// - /// Givens the i create the following clients. - /// - /// The table. - [Given(@"I create the following clients")] - public async Task GivenICreateTheFollowingClients(DataTable table) - { - List requests = table.Rows.ToCreateClientRequests(); - List<(String clientId, String secret, List allowedGrantTypes)> clients = await this.SecurityServiceSteps.GivenTheFollowingClientsExist(requests); - - foreach ((String clientId, String secret, List allowedGrantTypes) client in clients){ - this.TestingContext.Clients.Add(client.clientId); - } - } - - /// - /// Whens the i get the clients clients details are returned as follows. - /// - /// The number of clients. - /// The table. - [When(@"I get the clients (.*) clients details are returned as follows")] - public async Task WhenIGetTheClientsClientsDetailsAreReturnedAsFollows(Int32 numberOfClients, - DataTable table){ - List expectedClientDetails = table.Rows.ToClientDetails(); - await this.SecurityServiceSteps.WhenIGetTheClientsClientsDetailsAreReturnedAsFollows(expectedClientDetails, CancellationToken.None); - } - - /// - /// Whens the i get the client with client identifier the client details are returned as follows. - /// - /// The client identifier. - /// The table. - [When(@"I get the client with client id '(.*)' the client details are returned as follows")] - public async Task WhenIGetTheClientWithClientIdTheClientDetailsAreReturnedAsFollows(String clientId, - DataTable table){ - List expectedClientDetails = table.Rows.ToClientDetails(); - await this.SecurityServiceSteps.WhenIGetTheClientWithClientIdTheClientDetailsAreReturnedAsFollows(expectedClientDetails, clientId, CancellationToken.None); - } - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.IntegrationTests/Common/DockerHelper.cs b/archive/SecurityService.IntegrationTests/Common/DockerHelper.cs deleted file mode 100644 index e830d4d6..00000000 --- a/archive/SecurityService.IntegrationTests/Common/DockerHelper.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace SecurityService.IntergrationTests.Common -{ - using System.Data.SqlClient; - using System.Linq; - using System.Net; - using System.Net.Http; - using System.Net.Security; - using System.Security.Cryptography.X509Certificates; - using System.Threading; - using System.Threading.Tasks; - using Client; - using Ductus.FluentDocker; - using Ductus.FluentDocker.Builders; - using Ductus.FluentDocker.Commands; - using Ductus.FluentDocker.Common; - using Ductus.FluentDocker.Model.Builders; - using Ductus.FluentDocker.Services; - using Ductus.FluentDocker.Services.Extensions; - using Microsoft.EntityFrameworkCore; - using Shared.IntegrationTesting; - - public class DockerHelper : Shared.IntegrationTesting.TestContainers.DockerHelper - { - public ISecurityServiceClient SecurityServiceClient; - - public async Task StartContainersForScenarioRun(String scenarioName, DockerServices dockerServices) - { - await base.StartContainersForScenarioRun(scenarioName, dockerServices); - - Func securityServiceBaseAddressResolver = api => $"https://localhost:{this.SecurityServicePort}"; - HttpClient httpClient = new HttpClient(); - this.SecurityServiceClient = new SecurityServiceClient(securityServiceBaseAddressResolver,httpClient); - - ServicePointManager.SecurityProtocol = SecurityProtocolType.SystemDefault; - } - - /*public override DotNet.Testcontainers.Builders.ContainerBuilder SetupSecurityServiceContainer() - { - - this.Trace("About to Start Security Container"); - - List environmentVariables = this.GetCommonEnvironmentVariables(); - environmentVariables.Add($"ServiceOptions:PublicOrigin=https://{this.SecurityServiceContainerName}:{DockerPorts.SecurityServiceDockerPort}"); - environmentVariables.Add($"ServiceOptions:IssuerUrl=https://{this.SecurityServiceContainerName}:{DockerPorts.SecurityServiceDockerPort}"); - environmentVariables.Add("ASPNETCORE_ENVIRONMENT=IntegrationTest"); - environmentVariables.Add($"urls=https://*:{DockerPorts.SecurityServiceDockerPort}"); - - environmentVariables.Add("ServiceOptions:PasswordOptions:RequiredLength=6"); - environmentVariables.Add("ServiceOptions:PasswordOptions:RequireDigit=false"); - environmentVariables.Add("ServiceOptions:PasswordOptions:RequireUpperCase=false"); - environmentVariables.Add("ServiceOptions:UserOptions:RequireUniqueEmail=false"); - environmentVariables.Add("ServiceOptions:SignInOptions:RequireConfirmedEmail=false"); - - environmentVariables.Add(this.SetConnectionString("ConnectionStrings:PersistedGrantDbContext", $"PersistedGrantStore-{this.TestId}", this.UseSecureSqlServerDatabase)); - environmentVariables.Add(this.SetConnectionString("ConnectionStrings:ConfigurationDbContext", $"Configuration-{this.TestId}", this.UseSecureSqlServerDatabase)); - environmentVariables.Add(this.SetConnectionString("ConnectionStrings:AuthenticationDbContext", $"Authentication-{this.TestId}", this.UseSecureSqlServerDatabase)); - - List additionalEnvironmentVariables = this.GetAdditionalVariables(ContainerType.SecurityService); - - if (additionalEnvironmentVariables != null) - { - environmentVariables.AddRange(additionalEnvironmentVariables); - } - - SimpleResults.Result<(String imageName, Boolean useLatest)> imageDetailsResult = this.GetImageDetails(ContainerType.SecurityService); - if (imageDetailsResult.IsFailed) - throw new Exception($"Image details not found for {ContainerType.SecurityService}"); - - ContainerBuilder securityServiceContainer = new Builder().UseContainer().WithName(this.SecurityServiceContainerName) - .WithEnvironment(environmentVariables.ToArray()) - .UseImageDetails(imageDetailsResult.Data) - .MountHostFolder(this.DockerPlatform, this.HostTraceFolder) - .SetDockerCredentials(this.DockerCredentials); - - Int32? hostPort = this.GetHostPort(ContainerType.SecurityService); - if (hostPort == null) - { - securityServiceContainer = securityServiceContainer.ExposePort(DockerPorts.SecurityServiceDockerPort); - } - else - { - securityServiceContainer = securityServiceContainer.ExposePort(hostPort.Value, DockerPorts.SecurityServiceDockerPort); - } - - // Now build and return the container - return securityServiceContainer; - }*/ - - public override async Task CreateSubscriptions(){ - // No subscriptions needed - } - } -} diff --git a/archive/SecurityService.IntegrationTests/Common/GenericSteps.cs b/archive/SecurityService.IntegrationTests/Common/GenericSteps.cs deleted file mode 100644 index cabf07d0..00000000 --- a/archive/SecurityService.IntegrationTests/Common/GenericSteps.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace SecurityService.IntergrationTests.Common -{ - using NLog; - using Shared.IntegrationTesting; - using Shared.Logger; - using System.Threading.Tasks; - using Ductus.FluentDocker.Services; - using Ductus.FluentDocker.Model.Builders; - using Ductus.FluentDocker.Services.Extensions; - using System.IO; - using Ductus.FluentDocker.Builders; - using Ductus.FluentDocker.Common; - using Reqnroll; - - [Binding] - [Scope(Tag = "base")] - public class GenericSteps - { - private readonly ScenarioContext ScenarioContext; - - private readonly TestingContext TestingContext; - - public GenericSteps(ScenarioContext scenarioContext, - TestingContext testingContext) - { - this.ScenarioContext = scenarioContext; - this.TestingContext = testingContext; - } - - [BeforeScenario] - public async Task StartSystem() - { - // Initialise a logger - String scenarioName = this.ScenarioContext.ScenarioInfo.Title.Replace(" ", ""); - NlogLogger logger = new NlogLogger(); - logger.Initialise(LogManager.GetLogger(scenarioName), scenarioName); - LogManager.AddHiddenAssembly(typeof(NlogLogger).Assembly); - - DockerServices dockerServices = DockerServices.SecurityService | DockerServices.SqlServer; - - this.TestingContext.DockerHelper = new DockerHelper(); - this.TestingContext.DockerHelper.Logger = logger; - this.TestingContext.Logger = logger; - this.TestingContext.DockerHelper.RequiredDockerServices = dockerServices; - this.TestingContext.Logger.LogInformation("About to Start Global Setup"); - - await Setup.GlobalSetup(this.TestingContext.DockerHelper); - - this.TestingContext.DockerHelper.DockerCredentials = Setup.DockerCredentials; - this.TestingContext.DockerHelper.SqlCredentials = Setup.SqlCredentials; - this.TestingContext.DockerHelper.SqlServerContainerName = "sharedsqlserver"; - - this.TestingContext.DockerHelper.SetImageDetails(ContainerType.SecurityService, ("securityservice", false)); - - this.TestingContext.Logger = logger; - this.TestingContext.Logger.LogInformation("About to Start Containers for Scenario Run"); - await this.TestingContext.DockerHelper.StartContainersForScenarioRun(scenarioName, dockerServices).ConfigureAwait(false); - this.TestingContext.Logger.LogInformation("Containers for Scenario Run Started"); - } - - [AfterScenario] - public async Task StopSystem(){ - DockerServices sharedDockerServices = DockerServices.SqlServer; - this.TestingContext.Logger.LogInformation("About to Stop Containers for Scenario Run"); - await this.TestingContext.DockerHelper.StopContainersForScenarioRun(sharedDockerServices).ConfigureAwait(false); - this.TestingContext.Logger.LogInformation("Containers for Scenario Run Stopped"); - } - } -} diff --git a/archive/SecurityService.IntegrationTests/Common/Setup.cs b/archive/SecurityService.IntegrationTests/Common/Setup.cs deleted file mode 100644 index 2055d222..00000000 --- a/archive/SecurityService.IntegrationTests/Common/Setup.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; - -namespace SecurityService.IntergrationTests.Common -{ - using Ductus.FluentDocker.Services; - using Ductus.FluentDocker.Services.Extensions; - using NLog; - using Shared.IntegrationTesting; - using Shared.Logger; - using Shouldly; - using System.Linq.Expressions; - using System.Runtime.CompilerServices; - using System.Threading.Tasks; - using Reqnroll; - - [Binding] - public class Setup - { - public static IContainerService DatabaseServerContainer; - public static INetworkService DatabaseServerNetwork; - public static (String usename, String password) SqlCredentials = ("sa", "thisisalongpassword123!"); - public static (String url, String username, String password) DockerCredentials = ("https://www.docker.com", "stuartferguson", "Sc0tland"); - static object padLock = new object(); // Object to lock on - - public static async Task GlobalSetup(DockerHelper dockerHelper) - { - ShouldlyConfiguration.DefaultTaskTimeout = TimeSpan.FromMinutes(1); - } - } -} diff --git a/archive/SecurityService.IntegrationTests/Common/TestingContext.cs b/archive/SecurityService.IntegrationTests/Common/TestingContext.cs deleted file mode 100644 index 63f01e4b..00000000 --- a/archive/SecurityService.IntegrationTests/Common/TestingContext.cs +++ /dev/null @@ -1,72 +0,0 @@ -namespace SecurityService.IntergrationTests.Common -{ - using System; - using System.Collections.Generic; - using DataTransferObjects.Responses; - using Microsoft.EntityFrameworkCore.Query.Internal; - using Shared.Logger; - - /// - /// - /// - public class TestingContext - { - /// - /// Gets or sets the docker helper. - /// - /// - /// The docker helper. - /// - public DockerHelper DockerHelper { get; set; } - - /// - /// The users - /// - public Dictionary Users; - /// - /// The roles - /// - public Dictionary Roles; - - /// - /// The clients - /// - public List Clients; - - /// - /// The API resources - /// - public List ApiResources; - - /// - /// The API scopes - /// - public List ApiScopes; - - /// - /// The identity resources - /// - public List IdentityResources; - - /// - /// The token response - /// - public TokenResponse TokenResponse; - public String AccessToken; - - public NlogLogger Logger; - - /// - /// Initializes a new instance of the class. - /// - public TestingContext() - { - this.Users = new Dictionary(); - this.Roles= new Dictionary(); - this.Clients=new List(); - this.ApiScopes = new List(); - this.ApiResources=new List(); - this.IdentityResources = new List(); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService.IntegrationTests/IdentityResource/IdentityResource.feature b/archive/SecurityService.IntegrationTests/IdentityResource/IdentityResource.feature deleted file mode 100644 index b4c15b60..00000000 --- a/archive/SecurityService.IntegrationTests/IdentityResource/IdentityResource.feature +++ /dev/null @@ -1,19 +0,0 @@ -@base @identityresources -Feature: IdentityResource - -@PRTest -Scenario: Get Identity Resources - Given I create the following identity resources - | Name | DisplayName | Description | UserClaims | - | testresource1 | Test Resource1 | A resource for testing 1 | Claim1,Claim2 | - | testresource2 | Test Resource2 | A resource for testing 2 | Claim1,Claim2 | - When I get the identity resource with name 'testresource1' the identity resource details are returned as follows - | Name | DisplayName | Description | UserClaims | - | testresource1 | Test Resource1 | A resource for testing 1 | Claim1,Claim2 | - When I get the identity resource with name 'testresource2' the identity resource details are returned as follows - | Name | DisplayName | Description | UserClaims | - | testresource2 | Test Resource2 | A resource for testing 2 | Claim1,Claim2 | - When I get the identity resources 2 identity resource details are returned as follows - | Name | DisplayName | Description | UserClaims | - | testresource1 | Test Resource1 | A resource for testing 1 | Claim1,Claim2 | - | testresource2 | Test Resource2 | A resource for testing 2 | Claim1,Claim2 | \ No newline at end of file diff --git a/archive/SecurityService.IntegrationTests/IdentityResource/IdentityResource.feature.cs b/archive/SecurityService.IntegrationTests/IdentityResource/IdentityResource.feature.cs deleted file mode 100644 index b3cea1ab..00000000 --- a/archive/SecurityService.IntegrationTests/IdentityResource/IdentityResource.feature.cs +++ /dev/null @@ -1,207 +0,0 @@ -// ------------------------------------------------------------------------------ -// -// This code was generated by Reqnroll (https://reqnroll.net/). -// Reqnroll Version:3.0.0.0 -// Reqnroll Generator Version:3.0.0.0 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -// ------------------------------------------------------------------------------ -#region Designer generated code -#pragma warning disable -using Reqnroll; -namespace SecurityService.IntegrationTests.IdentityResource -{ - - - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Reqnroll", "3.0.0.0")] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::NUnit.Framework.TestFixtureAttribute()] - [global::NUnit.Framework.DescriptionAttribute("IdentityResource")] - [global::NUnit.Framework.FixtureLifeCycleAttribute(global::NUnit.Framework.LifeCycle.InstancePerTestCase)] - [global::NUnit.Framework.CategoryAttribute("base")] - [global::NUnit.Framework.CategoryAttribute("identityresources")] - public partial class IdentityResourceFeature - { - - private global::Reqnroll.ITestRunner testRunner; - - private static string[] featureTags = new string[] { - "base", - "identityresources"}; - - private static global::Reqnroll.FeatureInfo featureInfo = new global::Reqnroll.FeatureInfo(new global::System.Globalization.CultureInfo("en-US"), "IdentityResource", "IdentityResource", null, global::Reqnroll.ProgrammingLanguage.CSharp, featureTags, InitializeCucumberMessages()); - -#line 1 "IdentityResource.feature" -#line hidden - - [global::NUnit.Framework.OneTimeSetUpAttribute()] - public static async global::System.Threading.Tasks.Task FeatureSetupAsync() - { - } - - [global::NUnit.Framework.OneTimeTearDownAttribute()] - public static async global::System.Threading.Tasks.Task FeatureTearDownAsync() - { - await global::Reqnroll.TestRunnerManager.ReleaseFeatureAsync(featureInfo); - } - - [global::NUnit.Framework.SetUpAttribute()] - public async global::System.Threading.Tasks.Task TestInitializeAsync() - { - testRunner = global::Reqnroll.TestRunnerManager.GetTestRunnerForAssembly(featureHint: featureInfo); - try - { - if (((testRunner.FeatureContext != null) - && (testRunner.FeatureContext.FeatureInfo.Equals(featureInfo) == false))) - { - await testRunner.OnFeatureEndAsync(); - } - } - finally - { - if (((testRunner.FeatureContext != null) - && testRunner.FeatureContext.BeforeFeatureHookFailed)) - { - throw new global::Reqnroll.ReqnrollException("Scenario skipped because of previous before feature hook error"); - } - if ((testRunner.FeatureContext == null)) - { - await testRunner.OnFeatureStartAsync(featureInfo); - } - } - } - - [global::NUnit.Framework.TearDownAttribute()] - public async global::System.Threading.Tasks.Task TestTearDownAsync() - { - if ((testRunner == null)) - { - return; - } - try - { - await testRunner.OnScenarioEndAsync(); - } - finally - { - global::Reqnroll.TestRunnerManager.ReleaseTestRunner(testRunner); - testRunner = null; - } - } - - public void ScenarioInitialize(global::Reqnroll.ScenarioInfo scenarioInfo, global::Reqnroll.RuleInfo ruleInfo) - { - testRunner.OnScenarioInitialize(scenarioInfo, ruleInfo); - testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(global::NUnit.Framework.TestContext.CurrentContext); - } - - public async global::System.Threading.Tasks.Task ScenarioStartAsync() - { - await testRunner.OnScenarioStartAsync(); - } - - public async global::System.Threading.Tasks.Task ScenarioCleanupAsync() - { - await testRunner.CollectScenarioErrorsAsync(); - } - - private static global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages InitializeCucumberMessages() - { - return new global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages("IdentityResource/IdentityResource.feature.ndjson", 3); - } - - [global::NUnit.Framework.TestAttribute()] - [global::NUnit.Framework.DescriptionAttribute("Get Identity Resources")] - [global::NUnit.Framework.CategoryAttribute("PRTest")] - public async global::System.Threading.Tasks.Task GetIdentityResources() - { - string[] tagsOfScenario = new string[] { - "PRTest"}; - global::System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new global::System.Collections.Specialized.OrderedDictionary(); - string pickleIndex = "0"; - global::Reqnroll.ScenarioInfo scenarioInfo = new global::Reqnroll.ScenarioInfo("Get Identity Resources", null, tagsOfScenario, argumentsOfScenario, featureTags, pickleIndex); - string[] tagsOfRule = ((string[])(null)); - global::Reqnroll.RuleInfo ruleInfo = null; -#line 5 -this.ScenarioInitialize(scenarioInfo, ruleInfo); -#line hidden - if ((global::Reqnroll.TagHelper.ContainsIgnoreTag(scenarioInfo.CombinedTags) || global::Reqnroll.TagHelper.ContainsIgnoreTag(featureTags))) - { - await testRunner.SkipScenarioAsync(); - } - else - { - await this.ScenarioStartAsync(); - global::Reqnroll.Table table13 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Description", - "UserClaims"}); - table13.AddRow(new string[] { - "testresource1", - "Test Resource1", - "A resource for testing 1", - "Claim1,Claim2"}); - table13.AddRow(new string[] { - "testresource2", - "Test Resource2", - "A resource for testing 2", - "Claim1,Claim2"}); -#line 6 - await testRunner.GivenAsync("I create the following identity resources", ((string)(null)), table13, "Given "); -#line hidden - global::Reqnroll.Table table14 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Description", - "UserClaims"}); - table14.AddRow(new string[] { - "testresource1", - "Test Resource1", - "A resource for testing 1", - "Claim1,Claim2"}); -#line 10 - await testRunner.WhenAsync("I get the identity resource with name \'testresource1\' the identity resource detai" + - "ls are returned as follows", ((string)(null)), table14, "When "); -#line hidden - global::Reqnroll.Table table15 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Description", - "UserClaims"}); - table15.AddRow(new string[] { - "testresource2", - "Test Resource2", - "A resource for testing 2", - "Claim1,Claim2"}); -#line 13 - await testRunner.WhenAsync("I get the identity resource with name \'testresource2\' the identity resource detai" + - "ls are returned as follows", ((string)(null)), table15, "When "); -#line hidden - global::Reqnroll.Table table16 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Description", - "UserClaims"}); - table16.AddRow(new string[] { - "testresource1", - "Test Resource1", - "A resource for testing 1", - "Claim1,Claim2"}); - table16.AddRow(new string[] { - "testresource2", - "Test Resource2", - "A resource for testing 2", - "Claim1,Claim2"}); -#line 16 - await testRunner.WhenAsync("I get the identity resources 2 identity resource details are returned as follows", ((string)(null)), table16, "When "); -#line hidden - } - await this.ScenarioCleanupAsync(); - } - } -} -#pragma warning restore -#endregion diff --git a/archive/SecurityService.IntegrationTests/IdentityResource/IdentityResourceSteps.cs b/archive/SecurityService.IntegrationTests/IdentityResource/IdentityResourceSteps.cs deleted file mode 100644 index f065a449..00000000 --- a/archive/SecurityService.IntegrationTests/IdentityResource/IdentityResourceSteps.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; - -namespace SecurityService.IntegrationTests.IdentityResource -{ - using System.Collections.Generic; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - using Clients; - using DataTransferObjects.Responses; - using IntergrationTests.Common; - using Reqnroll; - using SecurityService.DataTransferObjects.Requests; - using SecurityService.IntegrationTesting.Helpers; - using Shouldly; - - [Binding] - [Scope(Tag = "identityresources")] - public class IdentityResourceSteps - { - #region Fields - - /// - /// The testing context - /// - private readonly TestingContext TestingContext; - - private readonly SecurityServiceSteps SecurityServiceSteps; - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The testing context. - public IdentityResourceSteps(TestingContext testingContext) - { - this.TestingContext = testingContext; - this.SecurityServiceSteps = new SecurityServiceSteps(this.TestingContext.DockerHelper.SecurityServiceClient); - } - #endregion - - [Given(@"I create the following identity resources")] - public async Task GivenICreateTheFollowingIdentityResources(DataTable table){ - List requests = table.Rows.ToCreateIdentityResourceRequest(); - await this.SecurityServiceSteps.GivenICreateTheFollowingIdentityResources(requests, CancellationToken.None); - - foreach (var request in requests){ - this.TestingContext.ApiResources.Add(request.Name); - } - } - - [When(@"I get the identity resource with name '(.*)' the identity resource details are returned as follows")] - public async Task WhenIGetTheIdentityResourceWithNameTheIdentityResourceDetailsAreReturnedAsFollows(String identityResourceName, DataTable table) - { - List expectedIdentityResourceDetailsList = table.Rows.ToIdentityResourceDetails(); - await this.SecurityServiceSteps.WhenIGetTheIdentityResourceWithNameTheIdentityResourceDetailsAreReturnedAsFollows(expectedIdentityResourceDetailsList, identityResourceName, CancellationToken.None); - } - - [When(@"I get the identity resources (.*) identity resource details are returned as follows")] - public async Task WhenIGetTheIdentityResourcesIdentityResourceDetailsAreReturnedAsFollows(Int32 numberOfIdentityResources, DataTable table) - { - List expectedIdentityResourceDetailsList = table.Rows.ToIdentityResourceDetails(); - await this.SecurityServiceSteps.WhenIGetTheIdentityResourcesIdentityResourceDetailsAreReturnedAsFollows(expectedIdentityResourceDetailsList, CancellationToken.None); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService.IntegrationTests/Roles/Roles.feature b/archive/SecurityService.IntegrationTests/Roles/Roles.feature deleted file mode 100644 index 63fdfa24..00000000 --- a/archive/SecurityService.IntegrationTests/Roles/Roles.feature +++ /dev/null @@ -1,24 +0,0 @@ -@base @roles -Feature: Roles - -@PRTest -Scenario: Get Roles - Given I create the following roles - | Role Name | - | TestRole1 | - | TestRole2 | - | TestRole3 | - When I get the role with name 'TestRole1' the role details are returned as follows - | Role Name | - | TestRole1 | - When I get the role with name 'TestRole2' the role details are returned as follows - | Role Name | - | TestRole2 | - When I get the role with name 'TestRole3' the role details are returned as follows - | Role Name | - | TestRole3 | - When I get the roles 3 roles details are returned as follows - | Role Name | - | TestRole1 | - | TestRole2 | - | TestRole3 | diff --git a/archive/SecurityService.IntegrationTests/Roles/Roles.feature.cs b/archive/SecurityService.IntegrationTests/Roles/Roles.feature.cs deleted file mode 100644 index 6ff7e1fd..00000000 --- a/archive/SecurityService.IntegrationTests/Roles/Roles.feature.cs +++ /dev/null @@ -1,186 +0,0 @@ -// ------------------------------------------------------------------------------ -// -// This code was generated by Reqnroll (https://reqnroll.net/). -// Reqnroll Version:3.0.0.0 -// Reqnroll Generator Version:3.0.0.0 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -// ------------------------------------------------------------------------------ -#region Designer generated code -#pragma warning disable -using Reqnroll; -namespace SecurityService.IntegrationTests.Roles -{ - - - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Reqnroll", "3.0.0.0")] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::NUnit.Framework.TestFixtureAttribute()] - [global::NUnit.Framework.DescriptionAttribute("Roles")] - [global::NUnit.Framework.FixtureLifeCycleAttribute(global::NUnit.Framework.LifeCycle.InstancePerTestCase)] - [global::NUnit.Framework.CategoryAttribute("base")] - [global::NUnit.Framework.CategoryAttribute("roles")] - public partial class RolesFeature - { - - private global::Reqnroll.ITestRunner testRunner; - - private static string[] featureTags = new string[] { - "base", - "roles"}; - - private static global::Reqnroll.FeatureInfo featureInfo = new global::Reqnroll.FeatureInfo(new global::System.Globalization.CultureInfo("en-US"), "Roles", "Roles", null, global::Reqnroll.ProgrammingLanguage.CSharp, featureTags, InitializeCucumberMessages()); - -#line 1 "Roles.feature" -#line hidden - - [global::NUnit.Framework.OneTimeSetUpAttribute()] - public static async global::System.Threading.Tasks.Task FeatureSetupAsync() - { - } - - [global::NUnit.Framework.OneTimeTearDownAttribute()] - public static async global::System.Threading.Tasks.Task FeatureTearDownAsync() - { - await global::Reqnroll.TestRunnerManager.ReleaseFeatureAsync(featureInfo); - } - - [global::NUnit.Framework.SetUpAttribute()] - public async global::System.Threading.Tasks.Task TestInitializeAsync() - { - testRunner = global::Reqnroll.TestRunnerManager.GetTestRunnerForAssembly(featureHint: featureInfo); - try - { - if (((testRunner.FeatureContext != null) - && (testRunner.FeatureContext.FeatureInfo.Equals(featureInfo) == false))) - { - await testRunner.OnFeatureEndAsync(); - } - } - finally - { - if (((testRunner.FeatureContext != null) - && testRunner.FeatureContext.BeforeFeatureHookFailed)) - { - throw new global::Reqnroll.ReqnrollException("Scenario skipped because of previous before feature hook error"); - } - if ((testRunner.FeatureContext == null)) - { - await testRunner.OnFeatureStartAsync(featureInfo); - } - } - } - - [global::NUnit.Framework.TearDownAttribute()] - public async global::System.Threading.Tasks.Task TestTearDownAsync() - { - if ((testRunner == null)) - { - return; - } - try - { - await testRunner.OnScenarioEndAsync(); - } - finally - { - global::Reqnroll.TestRunnerManager.ReleaseTestRunner(testRunner); - testRunner = null; - } - } - - public void ScenarioInitialize(global::Reqnroll.ScenarioInfo scenarioInfo, global::Reqnroll.RuleInfo ruleInfo) - { - testRunner.OnScenarioInitialize(scenarioInfo, ruleInfo); - testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(global::NUnit.Framework.TestContext.CurrentContext); - } - - public async global::System.Threading.Tasks.Task ScenarioStartAsync() - { - await testRunner.OnScenarioStartAsync(); - } - - public async global::System.Threading.Tasks.Task ScenarioCleanupAsync() - { - await testRunner.CollectScenarioErrorsAsync(); - } - - private static global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages InitializeCucumberMessages() - { - return new global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages("Roles/Roles.feature.ndjson", 3); - } - - [global::NUnit.Framework.TestAttribute()] - [global::NUnit.Framework.DescriptionAttribute("Get Roles")] - [global::NUnit.Framework.CategoryAttribute("PRTest")] - public async global::System.Threading.Tasks.Task GetRoles() - { - string[] tagsOfScenario = new string[] { - "PRTest"}; - global::System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new global::System.Collections.Specialized.OrderedDictionary(); - string pickleIndex = "0"; - global::Reqnroll.ScenarioInfo scenarioInfo = new global::Reqnroll.ScenarioInfo("Get Roles", null, tagsOfScenario, argumentsOfScenario, featureTags, pickleIndex); - string[] tagsOfRule = ((string[])(null)); - global::Reqnroll.RuleInfo ruleInfo = null; -#line 5 -this.ScenarioInitialize(scenarioInfo, ruleInfo); -#line hidden - if ((global::Reqnroll.TagHelper.ContainsIgnoreTag(scenarioInfo.CombinedTags) || global::Reqnroll.TagHelper.ContainsIgnoreTag(featureTags))) - { - await testRunner.SkipScenarioAsync(); - } - else - { - await this.ScenarioStartAsync(); - global::Reqnroll.Table table17 = new global::Reqnroll.Table(new string[] { - "Role Name"}); - table17.AddRow(new string[] { - "TestRole1"}); - table17.AddRow(new string[] { - "TestRole2"}); - table17.AddRow(new string[] { - "TestRole3"}); -#line 6 - await testRunner.GivenAsync("I create the following roles", ((string)(null)), table17, "Given "); -#line hidden - global::Reqnroll.Table table18 = new global::Reqnroll.Table(new string[] { - "Role Name"}); - table18.AddRow(new string[] { - "TestRole1"}); -#line 11 - await testRunner.WhenAsync("I get the role with name \'TestRole1\' the role details are returned as follows", ((string)(null)), table18, "When "); -#line hidden - global::Reqnroll.Table table19 = new global::Reqnroll.Table(new string[] { - "Role Name"}); - table19.AddRow(new string[] { - "TestRole2"}); -#line 14 - await testRunner.WhenAsync("I get the role with name \'TestRole2\' the role details are returned as follows", ((string)(null)), table19, "When "); -#line hidden - global::Reqnroll.Table table20 = new global::Reqnroll.Table(new string[] { - "Role Name"}); - table20.AddRow(new string[] { - "TestRole3"}); -#line 17 - await testRunner.WhenAsync("I get the role with name \'TestRole3\' the role details are returned as follows", ((string)(null)), table20, "When "); -#line hidden - global::Reqnroll.Table table21 = new global::Reqnroll.Table(new string[] { - "Role Name"}); - table21.AddRow(new string[] { - "TestRole1"}); - table21.AddRow(new string[] { - "TestRole2"}); - table21.AddRow(new string[] { - "TestRole3"}); -#line 20 - await testRunner.WhenAsync("I get the roles 3 roles details are returned as follows", ((string)(null)), table21, "When "); -#line hidden - } - await this.ScenarioCleanupAsync(); - } - } -} -#pragma warning restore -#endregion diff --git a/archive/SecurityService.IntegrationTests/Roles/RolesSteps.cs b/archive/SecurityService.IntegrationTests/Roles/RolesSteps.cs deleted file mode 100644 index 30a0203b..00000000 --- a/archive/SecurityService.IntegrationTests/Roles/RolesSteps.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; - -namespace SecurityService.IntegrationTests.Roles -{ - using System.Collections.Generic; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - using DataTransferObjects.Requests; - using DataTransferObjects.Responses; - using IntegrationTesting.Helpers; - using IntergrationTests.Common; - using Reqnroll; - using Shouldly; - - [Binding] - [Scope(Tag = "roles")] - public class RolesSteps - { - #region Fields - - /// - /// The testing context - /// - private readonly TestingContext TestingContext; - - private readonly SecurityServiceSteps SecurityServiceSteps; - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The testing context. - public RolesSteps(TestingContext testingContext) - { - this.TestingContext = testingContext; - this.SecurityServiceSteps = new SecurityServiceSteps(this.TestingContext.DockerHelper.SecurityServiceClient); - } - - #endregion - - [Given(@"I create the following roles")] - public async Task GivenICreateTheFollowingRoles(DataTable table){ - List requests = table.Rows.ToCreateRoleRequests(); - List<(String, Guid)> responses = await this.SecurityServiceSteps.GivenICreateTheFollowingRoles(requests, CancellationToken.None); - foreach ((String, Guid) response in responses){ - this.TestingContext.Roles.Add(response.Item1, response.Item2); - } - } - - [When(@"I get the role with name '(.*)' the role details are returned as follows")] - public async Task WhenIGetTheRoleWithNameTheRoleDetailsAreReturnedAsFollows(String roleName, DataTable table) - { - List requests = table.Rows.ToRoleDetails(); - // Get the role id - Guid roleId = this.TestingContext.Roles.Single(u => u.Key == roleName).Value; - await this.SecurityServiceSteps.WhenIGetTheRoleWithNameTheRoleDetailsAreReturnedAsFollows(requests, roleId, CancellationToken.None); - } - - [When(@"I get the roles (.*) roles details are returned as follows")] - public async Task WhenIGetTheRolesRolesDetailsAreReturnedAsFollows(Int32 numberOfRoles, Table table) - { - List requests = table.Rows.ToRoleDetails(); - await this.SecurityServiceSteps.WhenIGetTheRolesRolesDetailsAreReturnedAsFollows(requests, CancellationToken.None); - } - - } -} diff --git a/archive/SecurityService.IntegrationTests/SecurityService.IntegrationTests.csproj b/archive/SecurityService.IntegrationTests/SecurityService.IntegrationTests.csproj deleted file mode 100644 index 35a6f422..00000000 --- a/archive/SecurityService.IntegrationTests/SecurityService.IntegrationTests.csproj +++ /dev/null @@ -1,85 +0,0 @@ - - - - net10.0 - - false - - - - - - - - - - - - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - - - - - - - Always - - - Always - - - - - - SpecFlowSingleFileGenerator - ApiScope.feature.cs - - - - SpecFlowSingleFileGenerator - Clients.feature.cs - - - - SpecFlowSingleFileGenerator - IdentityResource.feature.cs - - - SpecFlowSingleFileGenerator - Roles.feature.cs - - - SpecFlowSingleFileGenerator - Users.feature.cs - - - - - diff --git a/archive/SecurityService.IntegrationTests/Token/Token.feature b/archive/SecurityService.IntegrationTests/Token/Token.feature deleted file mode 100644 index c5446ba3..00000000 --- a/archive/SecurityService.IntegrationTests/Token/Token.feature +++ /dev/null @@ -1,43 +0,0 @@ -@base @token @clients @apiresources @users @roles @apiscopes -Feature: Token - -Background: - - Given I create the following roles - | Role Name | - | Estate | - | Merchant | - - Given I create the following api scopes - | Name | DisplayName | Description | - | estateManagement | estateManagement Scope | A scope for estateManagement | - | transactionProcessor | transactionProcessor Scope | A scope for transactionProcessor | - | transactionProcessorAcl | transactionProcessorAcl Scope | A scope for transactionProcessorAcl | - - Given I create the following api resources - | Name | DisplayName | Secret | Scopes | UserClaims | - | estateManagement | Estate Managememt REST | Secret1 | estateManagement | MerchantId, EstateId, role | - | transactionProcessor | Transaction Processor REST | Secret1 | transactionProcessor | | - | transactionProcessorAcl | Transaction Processor ACL REST | Secret1 | transactionProcessorAcl | MerchantId, EstateId, role | - - Given I create the following clients - | ClientId | Name | Secret | Scopes | GrantTypes | - | serviceClient | Service Client | Secret1 | estateManagement,transactionProcessor,transactionProcessorAcl | client_credentials | - | merchantClient | Merchant Client | Secret1 | transactionProcessorAcl | password | - - Given I create the following users - | Email Address | Password | Phone Number | Given Name | Middle Name | Family Name | Claims | Roles | - | merchantuser@testmerchant1.co.uk | 123456 | 123456789 | Test | | User 1 | EstateId:1,MerchantId:2 | Merchant | - -@PRTest -Scenario: Get Tokens - When I request a client token with the following values - | ClientId | ClientSecret | - | serviceClient | Secret1 | - Then my token is returned - When I request a password token with the following values - | ClientId | ClientSecret | Username | Password | - | merchantClient | Secret1 | merchantuser@testmerchant1.co.uk | 123456 | - Then my token is returned - - diff --git a/archive/SecurityService.IntegrationTests/Token/Token.feature.cs b/archive/SecurityService.IntegrationTests/Token/Token.feature.cs deleted file mode 100644 index 319c470b..00000000 --- a/archive/SecurityService.IntegrationTests/Token/Token.feature.cs +++ /dev/null @@ -1,287 +0,0 @@ -// ------------------------------------------------------------------------------ -// -// This code was generated by Reqnroll (https://reqnroll.net/). -// Reqnroll Version:3.0.0.0 -// Reqnroll Generator Version:3.0.0.0 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -// ------------------------------------------------------------------------------ -#region Designer generated code -#pragma warning disable -using Reqnroll; -namespace SecurityService.IntegrationTests.Token -{ - - - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Reqnroll", "3.0.0.0")] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::NUnit.Framework.TestFixtureAttribute()] - [global::NUnit.Framework.DescriptionAttribute("Token")] - [global::NUnit.Framework.FixtureLifeCycleAttribute(global::NUnit.Framework.LifeCycle.InstancePerTestCase)] - [global::NUnit.Framework.CategoryAttribute("base")] - [global::NUnit.Framework.CategoryAttribute("token")] - [global::NUnit.Framework.CategoryAttribute("clients")] - [global::NUnit.Framework.CategoryAttribute("apiresources")] - [global::NUnit.Framework.CategoryAttribute("users")] - [global::NUnit.Framework.CategoryAttribute("roles")] - [global::NUnit.Framework.CategoryAttribute("apiscopes")] - public partial class TokenFeature - { - - private global::Reqnroll.ITestRunner testRunner; - - private static string[] featureTags = new string[] { - "base", - "token", - "clients", - "apiresources", - "users", - "roles", - "apiscopes"}; - - private static global::Reqnroll.FeatureInfo featureInfo = new global::Reqnroll.FeatureInfo(new global::System.Globalization.CultureInfo("en-US"), "Token", "Token", null, global::Reqnroll.ProgrammingLanguage.CSharp, featureTags, InitializeCucumberMessages()); - -#line 1 "Token.feature" -#line hidden - - [global::NUnit.Framework.OneTimeSetUpAttribute()] - public static async global::System.Threading.Tasks.Task FeatureSetupAsync() - { - } - - [global::NUnit.Framework.OneTimeTearDownAttribute()] - public static async global::System.Threading.Tasks.Task FeatureTearDownAsync() - { - await global::Reqnroll.TestRunnerManager.ReleaseFeatureAsync(featureInfo); - } - - [global::NUnit.Framework.SetUpAttribute()] - public async global::System.Threading.Tasks.Task TestInitializeAsync() - { - testRunner = global::Reqnroll.TestRunnerManager.GetTestRunnerForAssembly(featureHint: featureInfo); - try - { - if (((testRunner.FeatureContext != null) - && (testRunner.FeatureContext.FeatureInfo.Equals(featureInfo) == false))) - { - await testRunner.OnFeatureEndAsync(); - } - } - finally - { - if (((testRunner.FeatureContext != null) - && testRunner.FeatureContext.BeforeFeatureHookFailed)) - { - throw new global::Reqnroll.ReqnrollException("Scenario skipped because of previous before feature hook error"); - } - if ((testRunner.FeatureContext == null)) - { - await testRunner.OnFeatureStartAsync(featureInfo); - } - } - } - - [global::NUnit.Framework.TearDownAttribute()] - public async global::System.Threading.Tasks.Task TestTearDownAsync() - { - if ((testRunner == null)) - { - return; - } - try - { - await testRunner.OnScenarioEndAsync(); - } - finally - { - global::Reqnroll.TestRunnerManager.ReleaseTestRunner(testRunner); - testRunner = null; - } - } - - public void ScenarioInitialize(global::Reqnroll.ScenarioInfo scenarioInfo, global::Reqnroll.RuleInfo ruleInfo) - { - testRunner.OnScenarioInitialize(scenarioInfo, ruleInfo); - testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(global::NUnit.Framework.TestContext.CurrentContext); - } - - public async global::System.Threading.Tasks.Task ScenarioStartAsync() - { - await testRunner.OnScenarioStartAsync(); - } - - public async global::System.Threading.Tasks.Task ScenarioCleanupAsync() - { - await testRunner.CollectScenarioErrorsAsync(); - } - - public virtual async global::System.Threading.Tasks.Task FeatureBackgroundAsync() - { -#line 4 -#line hidden - global::Reqnroll.Table table22 = new global::Reqnroll.Table(new string[] { - "Role Name"}); - table22.AddRow(new string[] { - "Estate"}); - table22.AddRow(new string[] { - "Merchant"}); -#line 6 - await testRunner.GivenAsync("I create the following roles", ((string)(null)), table22, "Given "); -#line hidden - global::Reqnroll.Table table23 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Description"}); - table23.AddRow(new string[] { - "estateManagement", - "estateManagement Scope", - "A scope for estateManagement"}); - table23.AddRow(new string[] { - "transactionProcessor", - "transactionProcessor Scope", - "A scope for transactionProcessor"}); - table23.AddRow(new string[] { - "transactionProcessorAcl", - "transactionProcessorAcl Scope", - "A scope for transactionProcessorAcl"}); -#line 11 - await testRunner.GivenAsync("I create the following api scopes", ((string)(null)), table23, "Given "); -#line hidden - global::Reqnroll.Table table24 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Secret", - "Scopes", - "UserClaims"}); - table24.AddRow(new string[] { - "estateManagement", - "Estate Managememt REST", - "Secret1", - "estateManagement", - "MerchantId, EstateId, role"}); - table24.AddRow(new string[] { - "transactionProcessor", - "Transaction Processor REST", - "Secret1", - "transactionProcessor", - ""}); - table24.AddRow(new string[] { - "transactionProcessorAcl", - "Transaction Processor ACL REST", - "Secret1", - "transactionProcessorAcl", - "MerchantId, EstateId, role"}); -#line 17 - await testRunner.GivenAsync("I create the following api resources", ((string)(null)), table24, "Given "); -#line hidden - global::Reqnroll.Table table25 = new global::Reqnroll.Table(new string[] { - "ClientId", - "Name", - "Secret", - "Scopes", - "GrantTypes"}); - table25.AddRow(new string[] { - "serviceClient", - "Service Client", - "Secret1", - "estateManagement,transactionProcessor,transactionProcessorAcl", - "client_credentials"}); - table25.AddRow(new string[] { - "merchantClient", - "Merchant Client", - "Secret1", - "transactionProcessorAcl", - "password"}); -#line 23 - await testRunner.GivenAsync("I create the following clients", ((string)(null)), table25, "Given "); -#line hidden - global::Reqnroll.Table table26 = new global::Reqnroll.Table(new string[] { - "Email Address", - "Password", - "Phone Number", - "Given Name", - "Middle Name", - "Family Name", - "Claims", - "Roles"}); - table26.AddRow(new string[] { - "merchantuser@testmerchant1.co.uk", - "123456", - "123456789", - "Test", - "", - "User 1", - "EstateId:1,MerchantId:2", - "Merchant"}); -#line 28 - await testRunner.GivenAsync("I create the following users", ((string)(null)), table26, "Given "); -#line hidden - } - - private static global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages InitializeCucumberMessages() - { - return new global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages("Token/Token.feature.ndjson", 3); - } - - [global::NUnit.Framework.TestAttribute()] - [global::NUnit.Framework.DescriptionAttribute("Get Tokens")] - [global::NUnit.Framework.CategoryAttribute("PRTest")] - public async global::System.Threading.Tasks.Task GetTokens() - { - string[] tagsOfScenario = new string[] { - "PRTest"}; - global::System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new global::System.Collections.Specialized.OrderedDictionary(); - string pickleIndex = "0"; - global::Reqnroll.ScenarioInfo scenarioInfo = new global::Reqnroll.ScenarioInfo("Get Tokens", null, tagsOfScenario, argumentsOfScenario, featureTags, pickleIndex); - string[] tagsOfRule = ((string[])(null)); - global::Reqnroll.RuleInfo ruleInfo = null; -#line 33 -this.ScenarioInitialize(scenarioInfo, ruleInfo); -#line hidden - if ((global::Reqnroll.TagHelper.ContainsIgnoreTag(scenarioInfo.CombinedTags) || global::Reqnroll.TagHelper.ContainsIgnoreTag(featureTags))) - { - await testRunner.SkipScenarioAsync(); - } - else - { - await this.ScenarioStartAsync(); -#line 4 -await this.FeatureBackgroundAsync(); -#line hidden - global::Reqnroll.Table table27 = new global::Reqnroll.Table(new string[] { - "ClientId", - "ClientSecret"}); - table27.AddRow(new string[] { - "serviceClient", - "Secret1"}); -#line 34 - await testRunner.WhenAsync("I request a client token with the following values", ((string)(null)), table27, "When "); -#line hidden -#line 37 - await testRunner.ThenAsync("my token is returned", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden - global::Reqnroll.Table table28 = new global::Reqnroll.Table(new string[] { - "ClientId", - "ClientSecret", - "Username", - "Password"}); - table28.AddRow(new string[] { - "merchantClient", - "Secret1", - "merchantuser@testmerchant1.co.uk", - "123456"}); -#line 38 - await testRunner.WhenAsync("I request a password token with the following values", ((string)(null)), table28, "When "); -#line hidden -#line 41 - await testRunner.ThenAsync("my token is returned", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden - } - await this.ScenarioCleanupAsync(); - } - } -} -#pragma warning restore -#endregion diff --git a/archive/SecurityService.IntegrationTests/Token/TokenSteps.cs b/archive/SecurityService.IntegrationTests/Token/TokenSteps.cs deleted file mode 100644 index acb6c4aa..00000000 --- a/archive/SecurityService.IntegrationTests/Token/TokenSteps.cs +++ /dev/null @@ -1,65 +0,0 @@ - - -namespace SecurityService.IntegrationTests.Token -{ - using System; - using System.Collections.Generic; - using System.Text; - using System.Threading; - using System.Threading.Tasks; - using DataTransferObjects.Responses; - using IntergrationTests.Common; - using Reqnroll; - using Shouldly; - using SecurityService.IntegrationTesting.Helpers; - - [Binding] - [Scope(Tag = "token")] - public class TokenSteps - { - private readonly TestingContext TestingContext; - - private readonly SecurityServiceSteps SecurityServiceSteps; - - public TokenSteps(TestingContext testingContext) - { - this.TestingContext = testingContext; - this.SecurityServiceSteps = new SecurityServiceSteps(this.TestingContext.DockerHelper.SecurityServiceClient); - } - - [When(@"I request a client token with the following values")] - public async Task WhenIRequestAClientTokenWithTheFollowingValues(Table table) - { - table.Rows.Count.ShouldBe(1); - - String clientId = table.Rows[0]["ClientId"]; - String clientSecret = table.Rows[0]["ClientSecret"]; - - String tokenResponse = await this.SecurityServiceSteps.GetClientToken(clientId, clientSecret, CancellationToken.None); - - this.TestingContext.AccessToken = tokenResponse; - } - - [When(@"I request a password token with the following values")] - public async Task WhenIRequestAPasswordTokenWithTheFollowingValues(Table table) - { - table.Rows.Count.ShouldBe(1); - - String clientId = table.Rows[0]["ClientId"]; - String clientSecret = table.Rows[0]["ClientSecret"]; - String username = table.Rows[0]["Username"]; - String password = table.Rows[0]["Password"]; - - String tokenResponse = await this.SecurityServiceSteps.GetPasswordToken(clientId, clientSecret, username, password,CancellationToken.None); - - this.TestingContext.AccessToken = tokenResponse; - } - - [Then(@"my token is returned")] - public void ThenMyTokenIsReturned() - { - this.TestingContext.AccessToken.ShouldNotBeNullOrEmpty(); - } - - } -} diff --git a/archive/SecurityService.IntegrationTests/Users/Users.feature b/archive/SecurityService.IntegrationTests/Users/Users.feature deleted file mode 100644 index 6807b18a..00000000 --- a/archive/SecurityService.IntegrationTests/Users/Users.feature +++ /dev/null @@ -1,31 +0,0 @@ -@base @users @roles -Feature: Users - -Background: - Given I create the following roles - | Role Name | - | TestRole1 | - | TestRole2 | - | TestRole3 | - -@PRTest -Scenario: Get Users - Given I create the following users - | Email Address | Phone Number | Given Name | Middle Name | Family Name | Claims | Roles | - | testuser1@testing.co.uk | 123456789 | Test | | User 1 | | TestRole1 | - | testuser2@testing.co.uk | 123456789 | Test | | User 2 | | TestRole2 | - | testuser3@testing.co.uk | 123456789 | Test | | User 3 | | TestRole3 | - When I get the user with user name 'testuser1@testing.co.uk' the user details are returned as follows - | Email Address | Phone Number | Given Name | Middle Name | Family Name | Claims | Roles | RegistrationDate | - | testuser1@testing.co.uk | 123456789 | Test | | User 1 | email:testuser1@testing.co.uk, given_name:Test, family_name:User 1 | TestRole1 | Today | - When I get the user with user name 'testuser2@testing.co.uk' the user details are returned as follows - | Email Address | Phone Number | Given Name | Middle Name | Family Name | Claims | Roles |RegistrationDate | - | testuser2@testing.co.uk | 123456789 | Test | | User 2 | email:testuser2@testing.co.uk, given_name:Test, family_name:User 2 | TestRole2 |Today | - When I get the user with user name 'testuser3@testing.co.uk' the user details are returned as follows - | Email Address | Phone Number | Given Name | Middle Name | Family Name | Claims | Roles |RegistrationDate | - | testuser3@testing.co.uk | 123456789 | Test | | User 3 | email:testuser3@testing.co.uk, given_name:Test, family_name:User 3 | TestRole3 |Today | - When I get the users 3 users details are returned as follows - | Email Address | Phone Number | Given Name | Middle Name | Family Name | Claims | Roles |RegistrationDate | - | testuser1@testing.co.uk | 123456789 | Test | | User 1 | email:testuser1@testing.co.uk, given_name:Test, family_name:User 1 | TestRole1 |Today | - | testuser2@testing.co.uk | 123456789 | Test | | User 2 | email:testuser2@testing.co.uk, given_name:Test, family_name:User 2 | TestRole2 |Today | - | testuser3@testing.co.uk | 123456789 | Test | | User 3 | email:testuser3@testing.co.uk, given_name:Test, family_name:User 3 | TestRole3 |Today | diff --git a/archive/SecurityService.IntegrationTests/Users/Users.feature.cs b/archive/SecurityService.IntegrationTests/Users/Users.feature.cs deleted file mode 100644 index e1848c40..00000000 --- a/archive/SecurityService.IntegrationTests/Users/Users.feature.cs +++ /dev/null @@ -1,305 +0,0 @@ -// ------------------------------------------------------------------------------ -// -// This code was generated by Reqnroll (https://reqnroll.net/). -// Reqnroll Version:3.0.0.0 -// Reqnroll Generator Version:3.0.0.0 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -// ------------------------------------------------------------------------------ -#region Designer generated code -#pragma warning disable -using Reqnroll; -namespace SecurityService.IntegrationTests.Users -{ - - - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Reqnroll", "3.0.0.0")] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::NUnit.Framework.TestFixtureAttribute()] - [global::NUnit.Framework.DescriptionAttribute("Users")] - [global::NUnit.Framework.FixtureLifeCycleAttribute(global::NUnit.Framework.LifeCycle.InstancePerTestCase)] - [global::NUnit.Framework.CategoryAttribute("base")] - [global::NUnit.Framework.CategoryAttribute("users")] - [global::NUnit.Framework.CategoryAttribute("roles")] - public partial class UsersFeature - { - - private global::Reqnroll.ITestRunner testRunner; - - private static string[] featureTags = new string[] { - "base", - "users", - "roles"}; - - private static global::Reqnroll.FeatureInfo featureInfo = new global::Reqnroll.FeatureInfo(new global::System.Globalization.CultureInfo("en-US"), "Users", "Users", null, global::Reqnroll.ProgrammingLanguage.CSharp, featureTags, InitializeCucumberMessages()); - -#line 1 "Users.feature" -#line hidden - - [global::NUnit.Framework.OneTimeSetUpAttribute()] - public static async global::System.Threading.Tasks.Task FeatureSetupAsync() - { - } - - [global::NUnit.Framework.OneTimeTearDownAttribute()] - public static async global::System.Threading.Tasks.Task FeatureTearDownAsync() - { - await global::Reqnroll.TestRunnerManager.ReleaseFeatureAsync(featureInfo); - } - - [global::NUnit.Framework.SetUpAttribute()] - public async global::System.Threading.Tasks.Task TestInitializeAsync() - { - testRunner = global::Reqnroll.TestRunnerManager.GetTestRunnerForAssembly(featureHint: featureInfo); - try - { - if (((testRunner.FeatureContext != null) - && (testRunner.FeatureContext.FeatureInfo.Equals(featureInfo) == false))) - { - await testRunner.OnFeatureEndAsync(); - } - } - finally - { - if (((testRunner.FeatureContext != null) - && testRunner.FeatureContext.BeforeFeatureHookFailed)) - { - throw new global::Reqnroll.ReqnrollException("Scenario skipped because of previous before feature hook error"); - } - if ((testRunner.FeatureContext == null)) - { - await testRunner.OnFeatureStartAsync(featureInfo); - } - } - } - - [global::NUnit.Framework.TearDownAttribute()] - public async global::System.Threading.Tasks.Task TestTearDownAsync() - { - if ((testRunner == null)) - { - return; - } - try - { - await testRunner.OnScenarioEndAsync(); - } - finally - { - global::Reqnroll.TestRunnerManager.ReleaseTestRunner(testRunner); - testRunner = null; - } - } - - public void ScenarioInitialize(global::Reqnroll.ScenarioInfo scenarioInfo, global::Reqnroll.RuleInfo ruleInfo) - { - testRunner.OnScenarioInitialize(scenarioInfo, ruleInfo); - testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(global::NUnit.Framework.TestContext.CurrentContext); - } - - public async global::System.Threading.Tasks.Task ScenarioStartAsync() - { - await testRunner.OnScenarioStartAsync(); - } - - public async global::System.Threading.Tasks.Task ScenarioCleanupAsync() - { - await testRunner.CollectScenarioErrorsAsync(); - } - - public virtual async global::System.Threading.Tasks.Task FeatureBackgroundAsync() - { -#line 4 -#line hidden - global::Reqnroll.Table table29 = new global::Reqnroll.Table(new string[] { - "Role Name"}); - table29.AddRow(new string[] { - "TestRole1"}); - table29.AddRow(new string[] { - "TestRole2"}); - table29.AddRow(new string[] { - "TestRole3"}); -#line 5 - await testRunner.GivenAsync("I create the following roles", ((string)(null)), table29, "Given "); -#line hidden - } - - private static global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages InitializeCucumberMessages() - { - return new global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages("Users/Users.feature.ndjson", 3); - } - - [global::NUnit.Framework.TestAttribute()] - [global::NUnit.Framework.DescriptionAttribute("Get Users")] - [global::NUnit.Framework.CategoryAttribute("PRTest")] - public async global::System.Threading.Tasks.Task GetUsers() - { - string[] tagsOfScenario = new string[] { - "PRTest"}; - global::System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new global::System.Collections.Specialized.OrderedDictionary(); - string pickleIndex = "0"; - global::Reqnroll.ScenarioInfo scenarioInfo = new global::Reqnroll.ScenarioInfo("Get Users", null, tagsOfScenario, argumentsOfScenario, featureTags, pickleIndex); - string[] tagsOfRule = ((string[])(null)); - global::Reqnroll.RuleInfo ruleInfo = null; -#line 12 -this.ScenarioInitialize(scenarioInfo, ruleInfo); -#line hidden - if ((global::Reqnroll.TagHelper.ContainsIgnoreTag(scenarioInfo.CombinedTags) || global::Reqnroll.TagHelper.ContainsIgnoreTag(featureTags))) - { - await testRunner.SkipScenarioAsync(); - } - else - { - await this.ScenarioStartAsync(); -#line 4 -await this.FeatureBackgroundAsync(); -#line hidden - global::Reqnroll.Table table30 = new global::Reqnroll.Table(new string[] { - "Email Address", - "Phone Number", - "Given Name", - "Middle Name", - "Family Name", - "Claims", - "Roles"}); - table30.AddRow(new string[] { - "testuser1@testing.co.uk", - "123456789", - "Test", - "", - "User 1", - "", - "TestRole1"}); - table30.AddRow(new string[] { - "testuser2@testing.co.uk", - "123456789", - "Test", - "", - "User 2", - "", - "TestRole2"}); - table30.AddRow(new string[] { - "testuser3@testing.co.uk", - "123456789", - "Test", - "", - "User 3", - "", - "TestRole3"}); -#line 13 - await testRunner.GivenAsync("I create the following users", ((string)(null)), table30, "Given "); -#line hidden - global::Reqnroll.Table table31 = new global::Reqnroll.Table(new string[] { - "Email Address", - "Phone Number", - "Given Name", - "Middle Name", - "Family Name", - "Claims", - "Roles", - "RegistrationDate"}); - table31.AddRow(new string[] { - "testuser1@testing.co.uk", - "123456789", - "Test", - "", - "User 1", - "email:testuser1@testing.co.uk, given_name:Test, family_name:User 1", - "TestRole1", - "Today"}); -#line 18 - await testRunner.WhenAsync("I get the user with user name \'testuser1@testing.co.uk\' the user details are retu" + - "rned as follows", ((string)(null)), table31, "When "); -#line hidden - global::Reqnroll.Table table32 = new global::Reqnroll.Table(new string[] { - "Email Address", - "Phone Number", - "Given Name", - "Middle Name", - "Family Name", - "Claims", - "Roles", - "RegistrationDate"}); - table32.AddRow(new string[] { - "testuser2@testing.co.uk", - "123456789", - "Test", - "", - "User 2", - "email:testuser2@testing.co.uk, given_name:Test, family_name:User 2", - "TestRole2", - "Today"}); -#line 21 - await testRunner.WhenAsync("I get the user with user name \'testuser2@testing.co.uk\' the user details are retu" + - "rned as follows", ((string)(null)), table32, "When "); -#line hidden - global::Reqnroll.Table table33 = new global::Reqnroll.Table(new string[] { - "Email Address", - "Phone Number", - "Given Name", - "Middle Name", - "Family Name", - "Claims", - "Roles", - "RegistrationDate"}); - table33.AddRow(new string[] { - "testuser3@testing.co.uk", - "123456789", - "Test", - "", - "User 3", - "email:testuser3@testing.co.uk, given_name:Test, family_name:User 3", - "TestRole3", - "Today"}); -#line 24 - await testRunner.WhenAsync("I get the user with user name \'testuser3@testing.co.uk\' the user details are retu" + - "rned as follows", ((string)(null)), table33, "When "); -#line hidden - global::Reqnroll.Table table34 = new global::Reqnroll.Table(new string[] { - "Email Address", - "Phone Number", - "Given Name", - "Middle Name", - "Family Name", - "Claims", - "Roles", - "RegistrationDate"}); - table34.AddRow(new string[] { - "testuser1@testing.co.uk", - "123456789", - "Test", - "", - "User 1", - "email:testuser1@testing.co.uk, given_name:Test, family_name:User 1", - "TestRole1", - "Today"}); - table34.AddRow(new string[] { - "testuser2@testing.co.uk", - "123456789", - "Test", - "", - "User 2", - "email:testuser2@testing.co.uk, given_name:Test, family_name:User 2", - "TestRole2", - "Today"}); - table34.AddRow(new string[] { - "testuser3@testing.co.uk", - "123456789", - "Test", - "", - "User 3", - "email:testuser3@testing.co.uk, given_name:Test, family_name:User 3", - "TestRole3", - "Today"}); -#line 27 - await testRunner.WhenAsync("I get the users 3 users details are returned as follows", ((string)(null)), table34, "When "); -#line hidden - } - await this.ScenarioCleanupAsync(); - } - } -} -#pragma warning restore -#endregion diff --git a/archive/SecurityService.IntegrationTests/Users/UsersSteps.cs b/archive/SecurityService.IntegrationTests/Users/UsersSteps.cs deleted file mode 100644 index ee2aebbd..00000000 --- a/archive/SecurityService.IntegrationTests/Users/UsersSteps.cs +++ /dev/null @@ -1,92 +0,0 @@ -namespace SecurityService.IntergrationTests.Users -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Net.Http; - using System.Text; - using System.Threading; - using System.Threading.Tasks; - using Common; - using DataTransferObjects; - using DataTransferObjects.Responses; - using IntegrationTesting.Helpers; - using Newtonsoft.Json; - using Reqnroll; - using Shouldly; - - /// - /// - /// - [Binding] - [Scope(Tag = "users")] - public class UsersSteps - { - #region Fields - - /// - /// The testing context - /// - private readonly TestingContext TestingContext; - - private readonly SecurityServiceSteps SecurityServiceSteps; - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The testing context. - public UsersSteps(TestingContext testingContext) - { - this.TestingContext = testingContext; - this.SecurityServiceSteps = new SecurityServiceSteps(this.TestingContext.DockerHelper.SecurityServiceClient); - } - - #endregion - - #region Methods - - /// - /// Givens the i create the following users. - /// - /// The table. - [Given(@"I create the following users")] - public async Task GivenICreateTheFollowingUsers(DataTable table){ - List requests = table.Rows.ToCreateUserRequests(); - - List<(String, Guid)> results = await this.SecurityServiceSteps.GivenICreateTheFollowingUsers(requests, CancellationToken.None); - - foreach ((String, Guid) response in results){ - this.TestingContext.Users.Add(response.Item1, response.Item2); - } - } - - [When(@"I get the users (.*) users details are returned as follows")] - public async Task WhenIGetTheUsersUsersDetailsAreReturnedAsFollows(Int32 numberOfUsers, - DataTable table){ - List userDetailsList = table.Rows.ToUserDetails(); - await this.SecurityServiceSteps.WhenIGetTheUsersUsersDetailsAreReturnedAsFollows(userDetailsList, CancellationToken.None); - } - - /// - /// Whens the i get the user with user name the user details are returned as follows. - /// - /// Name of the user. - /// The table. - [When(@"I get the user with user name '(.*)' the user details are returned as follows")] - public async Task WhenIGetTheUserWithUserNameTheUserDetailsAreReturnedAsFollows(String userName, - DataTable table) - { - // Get the user id - Guid userId = this.TestingContext.Users.Single(u => u.Key == userName).Value; - - List userDetailsList = table.Rows.ToUserDetails(); - await this.SecurityServiceSteps.WhenIGetTheUserWithUserNameTheUserDetailsAreReturnedAsFollows(userDetailsList, userId, CancellationToken.None); - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.IntegrationTests/nlog.config b/archive/SecurityService.IntegrationTests/nlog.config deleted file mode 100644 index 00ad1430..00000000 --- a/archive/SecurityService.IntegrationTests/nlog.config +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/archive/SecurityService.IntegrationTests/xunit.runner.json b/archive/SecurityService.IntegrationTests/xunit.runner.json deleted file mode 100644 index 7b19a6ce..00000000 --- a/archive/SecurityService.IntegrationTests/xunit.runner.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "maxParallelThreads" : 1 -} diff --git a/archive/SecurityService.Models/AccountOptions.cs b/archive/SecurityService.Models/AccountOptions.cs deleted file mode 100644 index 0e25dd84..00000000 --- a/archive/SecurityService.Models/AccountOptions.cs +++ /dev/null @@ -1,55 +0,0 @@ -namespace SecurityService.Models -{ - using System; - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public static class AccountOptions - { - #region Fields - - /// - /// The allow local login - /// - public static readonly Boolean AllowLocalLogin = true; - - /// - /// The allow remember login - /// - public static readonly Boolean AllowRememberLogin = true; - - /// - /// The automatic redirect after sign out - /// - public static readonly Boolean AutomaticRedirectAfterSignOut = false; - - // if user uses windows auth, should we load the groups from windows - /// - /// The include windows groups - /// - public static readonly Boolean IncludeWindowsGroups = false; - - /// - /// The invalid credentials error message - /// - public static readonly String InvalidCredentialsErrorMessage = "Invalid username or password"; - - /// - /// The remember me login duration - /// - public static readonly TimeSpan RememberMeLoginDuration = TimeSpan.FromDays(30); - - /// - /// The show logout prompt - /// - public static readonly Boolean ShowLogoutPrompt = true; - - // specify the Windows authentication scheme being used - /// - /// The windows authentication scheme name - /// - public static readonly String WindowsAuthenticationSchemeName = "Windows"; - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.Models/ChangeUserPasswordResult.cs b/archive/SecurityService.Models/ChangeUserPasswordResult.cs deleted file mode 100644 index 61aea80c..00000000 --- a/archive/SecurityService.Models/ChangeUserPasswordResult.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SecurityService.Models -{ - public class ChangeUserPasswordResult - { - public Boolean IsSuccessful { get; set; } - public String RedirectUri { get; set; } - } -} diff --git a/archive/SecurityService.Models/ConsentOptions.cs b/archive/SecurityService.Models/ConsentOptions.cs deleted file mode 100644 index 414c25ef..00000000 --- a/archive/SecurityService.Models/ConsentOptions.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace SecurityService.Models -{ - using System; - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public static class ConsentOptions - { - #region Fields - - /// - /// The enable offline access - /// - public static readonly Boolean EnableOfflineAccess = true; - - /// - /// The invalid selection error message - /// - public static readonly String InvalidSelectionErrorMessage = "Invalid selection"; - - /// - /// The must choose one error message - /// - public static readonly String MustChooseOneErrorMessage = "You must pick at least one permission"; - - /// - /// The offline access description - /// - public static readonly String OfflineAccessDescription = "Access to your applications and resources, even when you are offline"; - - /// - /// The offline access display name - /// - public static readonly String OfflineAccessDisplayName = "Offline Access"; - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.Models/RoleDetails.cs b/archive/SecurityService.Models/RoleDetails.cs deleted file mode 100644 index 1cea4f7f..00000000 --- a/archive/SecurityService.Models/RoleDetails.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace SecurityService.Models -{ - using System; - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class RoleDetails - { - /// - /// Gets or sets the role identifier. - /// - /// - /// The role identifier. - /// - public Guid RoleId { get; set; } - - /// - /// Gets or sets the name of the role. - /// - /// - /// The name of the role. - /// - public String RoleName { get; set; } - } -} \ No newline at end of file diff --git a/archive/SecurityService.Models/SecurityService.Models.csproj b/archive/SecurityService.Models/SecurityService.Models.csproj deleted file mode 100644 index 4a974a71..00000000 --- a/archive/SecurityService.Models/SecurityService.Models.csproj +++ /dev/null @@ -1,7 +0,0 @@ - - - - net10.0 - - - diff --git a/archive/SecurityService.Models/UserDetails.cs b/archive/SecurityService.Models/UserDetails.cs deleted file mode 100644 index 32167d4b..00000000 --- a/archive/SecurityService.Models/UserDetails.cs +++ /dev/null @@ -1,62 +0,0 @@ -namespace SecurityService.Models -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class UserDetails - { - /// - /// Gets or sets the claims. - /// - /// - /// The claims. - /// - public Dictionary Claims { get; set; } - - /// - /// Gets or sets the email. - /// - /// - /// The email. - /// - public String Email { get; set; } - - /// - /// Gets or sets the phone number. - /// - /// - /// The phone number. - /// - public String PhoneNumber { get; set; } - - /// - /// Gets or sets the roles. - /// - /// - /// The roles. - /// - public List Roles { get; set; } - - /// - /// Gets or sets the user identifier. - /// - /// - /// The user identifier. - /// - public Guid UserId { get; set; } - - public String SubjectId { get; set; } - - /// - /// Gets or sets the name of the user. - /// - /// - /// The name of the user. - /// - public String Username { get; set; } - - public DateTime RegistrationDateTime { get; set; } - } -} diff --git a/archive/SecurityService.MySqlMigrations/AuthenticationDb/20211201220044_InitialCreate.Designer.cs b/archive/SecurityService.MySqlMigrations/AuthenticationDb/20211201220044_InitialCreate.Designer.cs deleted file mode 100644 index ffb31d9d..00000000 --- a/archive/SecurityService.MySqlMigrations/AuthenticationDb/20211201220044_InitialCreate.Designer.cs +++ /dev/null @@ -1,267 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SecurityService.Database.DbContexts; - -namespace SecurityService.MySqlMigrations.AuthenticationDb -{ - [DbContext(typeof(AuthenticationDbContext))] - [Migration("20211201220044_InitialCreate")] - partial class InitialCreate - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("Relational:MaxIdentifierLength", 64) - .HasAnnotation("ProductVersion", "5.0.12"); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("varchar(255)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("longtext"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex"); - - b.ToTable("AspNetRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClaimType") - .HasColumnType("longtext"); - - b.Property("ClaimValue") - .HasColumnType("longtext"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("varchar(255)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => - { - b.Property("Id") - .HasColumnType("varchar(255)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("longtext"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("tinyint(1)"); - - b.Property("LockoutEnabled") - .HasColumnType("tinyint(1)"); - - b.Property("LockoutEnd") - .HasColumnType("datetime(6)"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("longtext"); - - b.Property("PhoneNumber") - .HasColumnType("longtext"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("tinyint(1)"); - - b.Property("SecurityStamp") - .HasColumnType("longtext"); - - b.Property("TwoFactorEnabled") - .HasColumnType("tinyint(1)"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex"); - - b.ToTable("AspNetUsers"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClaimType") - .HasColumnType("longtext"); - - b.Property("ClaimValue") - .HasColumnType("longtext"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("varchar(255)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("varchar(255)"); - - b.Property("ProviderKey") - .HasColumnType("varchar(255)"); - - b.Property("ProviderDisplayName") - .HasColumnType("longtext"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("varchar(255)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("varchar(255)"); - - b.Property("RoleId") - .HasColumnType("varchar(255)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("varchar(255)"); - - b.Property("LoginProvider") - .HasColumnType("varchar(255)"); - - b.Property("Name") - .HasColumnType("varchar(255)"); - - b.Property("Value") - .HasColumnType("longtext"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/AuthenticationDb/20211201220044_InitialCreate.cs b/archive/SecurityService.MySqlMigrations/AuthenticationDb/20211201220044_InitialCreate.cs deleted file mode 100644 index 874b42eb..00000000 --- a/archive/SecurityService.MySqlMigrations/AuthenticationDb/20211201220044_InitialCreate.cs +++ /dev/null @@ -1,257 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace SecurityService.MySqlMigrations.AuthenticationDb -{ - public partial class InitialCreate : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterDatabase() - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "AspNetRoles", - columns: table => new - { - Id = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Name = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - NormalizedName = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - ConcurrencyStamp = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoles", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "AspNetUsers", - columns: table => new - { - Id = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - UserName = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - NormalizedUserName = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Email = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - NormalizedEmail = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - EmailConfirmed = table.Column(type: "tinyint(1)", nullable: false), - PasswordHash = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - SecurityStamp = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - ConcurrencyStamp = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - PhoneNumber = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - PhoneNumberConfirmed = table.Column(type: "tinyint(1)", nullable: false), - TwoFactorEnabled = table.Column(type: "tinyint(1)", nullable: false), - LockoutEnd = table.Column(type: "datetime(6)", nullable: true), - LockoutEnabled = table.Column(type: "tinyint(1)", nullable: false), - AccessFailedCount = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUsers", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "AspNetRoleClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - RoleId = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ClaimType = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - ClaimValue = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "AspNetUserClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - UserId = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ClaimType = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - ClaimValue = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetUserClaims_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "AspNetUserLogins", - columns: table => new - { - LoginProvider = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ProviderKey = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ProviderDisplayName = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - UserId = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); - table.ForeignKey( - name: "FK_AspNetUserLogins_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "AspNetUserRoles", - columns: table => new - { - UserId = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - RoleId = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "AspNetUserTokens", - columns: table => new - { - UserId = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - LoginProvider = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Name = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Value = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); - table.ForeignKey( - name: "FK_AspNetUserTokens_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetRoleClaims_RoleId", - table: "AspNetRoleClaims", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "RoleNameIndex", - table: "AspNetRoles", - column: "NormalizedName", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserClaims_UserId", - table: "AspNetUserClaims", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserLogins_UserId", - table: "AspNetUserLogins", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserRoles_RoleId", - table: "AspNetUserRoles", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "EmailIndex", - table: "AspNetUsers", - column: "NormalizedEmail"); - - migrationBuilder.CreateIndex( - name: "UserNameIndex", - table: "AspNetUsers", - column: "NormalizedUserName", - unique: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "AspNetRoleClaims"); - - migrationBuilder.DropTable( - name: "AspNetUserClaims"); - - migrationBuilder.DropTable( - name: "AspNetUserLogins"); - - migrationBuilder.DropTable( - name: "AspNetUserRoles"); - - migrationBuilder.DropTable( - name: "AspNetUserTokens"); - - migrationBuilder.DropTable( - name: "AspNetRoles"); - - migrationBuilder.DropTable( - name: "AspNetUsers"); - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/AuthenticationDb/20220609182009_Net6Update.Designer.cs b/archive/SecurityService.MySqlMigrations/AuthenticationDb/20220609182009_Net6Update.Designer.cs deleted file mode 100644 index 995c8bfe..00000000 --- a/archive/SecurityService.MySqlMigrations/AuthenticationDb/20220609182009_Net6Update.Designer.cs +++ /dev/null @@ -1,269 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SecurityService.Database.DbContexts; - -#nullable disable - -namespace SecurityService.MySqlMigrations.AuthenticationDb -{ - [DbContext(typeof(AuthenticationDbContext))] - [Migration("20220609182009_Net6Update")] - partial class Net6Update - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "6.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("varchar(255)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("longtext"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClaimType") - .HasColumnType("longtext"); - - b.Property("ClaimValue") - .HasColumnType("longtext"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("varchar(255)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => - { - b.Property("Id") - .HasColumnType("varchar(255)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("longtext"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("tinyint(1)"); - - b.Property("LockoutEnabled") - .HasColumnType("tinyint(1)"); - - b.Property("LockoutEnd") - .HasColumnType("datetime(6)"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("longtext"); - - b.Property("PhoneNumber") - .HasColumnType("longtext"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("tinyint(1)"); - - b.Property("SecurityStamp") - .HasColumnType("longtext"); - - b.Property("TwoFactorEnabled") - .HasColumnType("tinyint(1)"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClaimType") - .HasColumnType("longtext"); - - b.Property("ClaimValue") - .HasColumnType("longtext"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("varchar(255)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("varchar(255)"); - - b.Property("ProviderKey") - .HasColumnType("varchar(255)"); - - b.Property("ProviderDisplayName") - .HasColumnType("longtext"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("varchar(255)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("varchar(255)"); - - b.Property("RoleId") - .HasColumnType("varchar(255)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("varchar(255)"); - - b.Property("LoginProvider") - .HasColumnType("varchar(255)"); - - b.Property("Name") - .HasColumnType("varchar(255)"); - - b.Property("Value") - .HasColumnType("longtext"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/AuthenticationDb/20220609182009_Net6Update.cs b/archive/SecurityService.MySqlMigrations/AuthenticationDb/20220609182009_Net6Update.cs deleted file mode 100644 index 1d36f4f8..00000000 --- a/archive/SecurityService.MySqlMigrations/AuthenticationDb/20220609182009_Net6Update.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace SecurityService.MySqlMigrations.AuthenticationDb -{ - public partial class Net6Update : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/AuthenticationDb/20240325171939_net8upgrade.Designer.cs b/archive/SecurityService.MySqlMigrations/AuthenticationDb/20240325171939_net8upgrade.Designer.cs deleted file mode 100644 index 6e01674e..00000000 --- a/archive/SecurityService.MySqlMigrations/AuthenticationDb/20240325171939_net8upgrade.Designer.cs +++ /dev/null @@ -1,277 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SecurityService.Database.DbContexts; - -#nullable disable - -namespace SecurityService.MySqlMigrations.AuthenticationDb -{ - [DbContext(typeof(AuthenticationDbContext))] - [Migration("20240325171939_net8upgrade")] - partial class net8upgrade - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("varchar(255)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("longtext"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("longtext"); - - b.Property("ClaimValue") - .HasColumnType("longtext"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("varchar(255)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => - { - b.Property("Id") - .HasColumnType("varchar(255)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("longtext"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("tinyint(1)"); - - b.Property("LockoutEnabled") - .HasColumnType("tinyint(1)"); - - b.Property("LockoutEnd") - .HasColumnType("datetime(6)"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("longtext"); - - b.Property("PhoneNumber") - .HasColumnType("longtext"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("tinyint(1)"); - - b.Property("SecurityStamp") - .HasColumnType("longtext"); - - b.Property("TwoFactorEnabled") - .HasColumnType("tinyint(1)"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("longtext"); - - b.Property("ClaimValue") - .HasColumnType("longtext"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("varchar(255)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("varchar(255)"); - - b.Property("ProviderKey") - .HasColumnType("varchar(255)"); - - b.Property("ProviderDisplayName") - .HasColumnType("longtext"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("varchar(255)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("varchar(255)"); - - b.Property("RoleId") - .HasColumnType("varchar(255)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("varchar(255)"); - - b.Property("LoginProvider") - .HasColumnType("varchar(255)"); - - b.Property("Name") - .HasColumnType("varchar(255)"); - - b.Property("Value") - .HasColumnType("longtext"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/AuthenticationDb/20240325171939_net8upgrade.cs b/archive/SecurityService.MySqlMigrations/AuthenticationDb/20240325171939_net8upgrade.cs deleted file mode 100644 index d6f65784..00000000 --- a/archive/SecurityService.MySqlMigrations/AuthenticationDb/20240325171939_net8upgrade.cs +++ /dev/null @@ -1,55 +0,0 @@ -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace SecurityService.MySqlMigrations.AuthenticationDb -{ - /// - public partial class net8upgrade : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "Id", - table: "AspNetUserClaims", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "AspNetRoleClaims", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "Id", - table: "AspNetUserClaims", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "AspNetRoleClaims", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/AuthenticationDb/20250318231636_record_registration_date.Designer.cs b/archive/SecurityService.MySqlMigrations/AuthenticationDb/20250318231636_record_registration_date.Designer.cs deleted file mode 100644 index 595d26cd..00000000 --- a/archive/SecurityService.MySqlMigrations/AuthenticationDb/20250318231636_record_registration_date.Designer.cs +++ /dev/null @@ -1,280 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SecurityService.Database.DbContexts; - -#nullable disable - -namespace SecurityService.MySqlMigrations.AuthenticationDb -{ - [DbContext(typeof(AuthenticationDbContext))] - [Migration("20250318231636_record_registration_date")] - partial class record_registration_date - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("varchar(255)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("longtext"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("longtext"); - - b.Property("ClaimValue") - .HasColumnType("longtext"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("varchar(255)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("longtext"); - - b.Property("ClaimValue") - .HasColumnType("longtext"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("varchar(255)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("varchar(255)"); - - b.Property("ProviderKey") - .HasColumnType("varchar(255)"); - - b.Property("ProviderDisplayName") - .HasColumnType("longtext"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("varchar(255)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("varchar(255)"); - - b.Property("RoleId") - .HasColumnType("varchar(255)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("varchar(255)"); - - b.Property("LoginProvider") - .HasColumnType("varchar(255)"); - - b.Property("Name") - .HasColumnType("varchar(255)"); - - b.Property("Value") - .HasColumnType("longtext"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("SecurityService.BusinessLogic.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("varchar(255)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("longtext"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("tinyint(1)"); - - b.Property("LockoutEnabled") - .HasColumnType("tinyint(1)"); - - b.Property("LockoutEnd") - .HasColumnType("datetime(6)"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("longtext"); - - b.Property("PhoneNumber") - .HasColumnType("longtext"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("tinyint(1)"); - - b.Property("RegistrationDateTime") - .HasColumnType("datetime(6)"); - - b.Property("SecurityStamp") - .HasColumnType("longtext"); - - b.Property("TwoFactorEnabled") - .HasColumnType("tinyint(1)"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("SecurityService.BusinessLogic.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("SecurityService.BusinessLogic.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SecurityService.BusinessLogic.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("SecurityService.BusinessLogic.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/AuthenticationDb/20250318231636_record_registration_date.cs b/archive/SecurityService.MySqlMigrations/AuthenticationDb/20250318231636_record_registration_date.cs deleted file mode 100644 index 4c036be1..00000000 --- a/archive/SecurityService.MySqlMigrations/AuthenticationDb/20250318231636_record_registration_date.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace SecurityService.MySqlMigrations.AuthenticationDb -{ - /// - public partial class record_registration_date : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "RegistrationDateTime", - table: "AspNetUsers", - type: "datetime(6)", - nullable: false, - defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "RegistrationDateTime", - table: "AspNetUsers"); - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/AuthenticationDb/AuthenticationDbContextModelSnapshot.cs b/archive/SecurityService.MySqlMigrations/AuthenticationDb/AuthenticationDbContextModelSnapshot.cs deleted file mode 100644 index ead15fb1..00000000 --- a/archive/SecurityService.MySqlMigrations/AuthenticationDb/AuthenticationDbContextModelSnapshot.cs +++ /dev/null @@ -1,277 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SecurityService.Database.DbContexts; - -#nullable disable - -namespace SecurityService.MySqlMigrations.AuthenticationDb -{ - [DbContext(typeof(AuthenticationDbContext))] - partial class AuthenticationDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("varchar(255)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("longtext"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("longtext"); - - b.Property("ClaimValue") - .HasColumnType("longtext"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("varchar(255)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("longtext"); - - b.Property("ClaimValue") - .HasColumnType("longtext"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("varchar(255)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("varchar(255)"); - - b.Property("ProviderKey") - .HasColumnType("varchar(255)"); - - b.Property("ProviderDisplayName") - .HasColumnType("longtext"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("varchar(255)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("varchar(255)"); - - b.Property("RoleId") - .HasColumnType("varchar(255)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("varchar(255)"); - - b.Property("LoginProvider") - .HasColumnType("varchar(255)"); - - b.Property("Name") - .HasColumnType("varchar(255)"); - - b.Property("Value") - .HasColumnType("longtext"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("SecurityService.BusinessLogic.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("varchar(255)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("longtext"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("tinyint(1)"); - - b.Property("LockoutEnabled") - .HasColumnType("tinyint(1)"); - - b.Property("LockoutEnd") - .HasColumnType("datetime(6)"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("longtext"); - - b.Property("PhoneNumber") - .HasColumnType("longtext"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("tinyint(1)"); - - b.Property("RegistrationDateTime") - .HasColumnType("datetime(6)"); - - b.Property("SecurityStamp") - .HasColumnType("longtext"); - - b.Property("TwoFactorEnabled") - .HasColumnType("tinyint(1)"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("SecurityService.BusinessLogic.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("SecurityService.BusinessLogic.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SecurityService.BusinessLogic.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("SecurityService.BusinessLogic.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/ConfigurationDb/20211201215951_InitialCreate.Designer.cs b/archive/SecurityService.MySqlMigrations/ConfigurationDb/20211201215951_InitialCreate.Designer.cs deleted file mode 100644 index afe98805..00000000 --- a/archive/SecurityService.MySqlMigrations/ConfigurationDb/20211201215951_InitialCreate.Designer.cs +++ /dev/null @@ -1,996 +0,0 @@ -// -using System; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace SecurityService.MySqlMigrations.ConfigurationDb -{ - [DbContext(typeof(ConfigurationDbContext))] - [Migration("20211201215951_InitialCreate")] - partial class InitialCreate - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("Relational:MaxIdentifierLength", 64) - .HasAnnotation("ProductVersion", "5.0.12"); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("AllowedAccessTokenSigningAlgorithms") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("LastAccessed") - .HasColumnType("datetime(6)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("NonEditable") - .HasColumnType("tinyint(1)"); - - b.Property("RequireResourceIndicator") - .HasColumnType("tinyint(1)"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("tinyint(1)"); - - b.Property("Updated") - .HasColumnType("datetime(6)"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiResources"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiResourceClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiResourceProperties"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Scope") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiResourceScopes"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("Expiration") - .HasColumnType("datetime(6)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(4000) - .HasColumnType("varchar(4000)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiResourceSecrets"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Emphasize") - .HasColumnType("tinyint(1)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Required") - .HasColumnType("tinyint(1)"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("tinyint(1)"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiScopes"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ScopeId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ScopeId"); - - b.ToTable("ApiScopeClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("ScopeId") - .HasColumnType("int"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ScopeId"); - - b.ToTable("ApiScopeProperties"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("AbsoluteRefreshTokenLifetime") - .HasColumnType("int"); - - b.Property("AccessTokenLifetime") - .HasColumnType("int"); - - b.Property("AccessTokenType") - .HasColumnType("int"); - - b.Property("AllowAccessTokensViaBrowser") - .HasColumnType("tinyint(1)"); - - b.Property("AllowOfflineAccess") - .HasColumnType("tinyint(1)"); - - b.Property("AllowPlainTextPkce") - .HasColumnType("tinyint(1)"); - - b.Property("AllowRememberConsent") - .HasColumnType("tinyint(1)"); - - b.Property("AllowedIdentityTokenSigningAlgorithms") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("AlwaysIncludeUserClaimsInIdToken") - .HasColumnType("tinyint(1)"); - - b.Property("AlwaysSendClientClaims") - .HasColumnType("tinyint(1)"); - - b.Property("AuthorizationCodeLifetime") - .HasColumnType("int"); - - b.Property("BackChannelLogoutSessionRequired") - .HasColumnType("tinyint(1)"); - - b.Property("BackChannelLogoutUri") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("ClientClaimsPrefix") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ClientName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ClientUri") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("ConsentLifetime") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("DeviceCodeLifetime") - .HasColumnType("int"); - - b.Property("EnableLocalLogin") - .HasColumnType("tinyint(1)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("FrontChannelLogoutSessionRequired") - .HasColumnType("tinyint(1)"); - - b.Property("FrontChannelLogoutUri") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("IdentityTokenLifetime") - .HasColumnType("int"); - - b.Property("IncludeJwtId") - .HasColumnType("tinyint(1)"); - - b.Property("LastAccessed") - .HasColumnType("datetime(6)"); - - b.Property("LogoUri") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("NonEditable") - .HasColumnType("tinyint(1)"); - - b.Property("PairWiseSubjectSalt") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ProtocolType") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("RefreshTokenExpiration") - .HasColumnType("int"); - - b.Property("RefreshTokenUsage") - .HasColumnType("int"); - - b.Property("RequireClientSecret") - .HasColumnType("tinyint(1)"); - - b.Property("RequireConsent") - .HasColumnType("tinyint(1)"); - - b.Property("RequirePkce") - .HasColumnType("tinyint(1)"); - - b.Property("RequireRequestObject") - .HasColumnType("tinyint(1)"); - - b.Property("SlidingRefreshTokenLifetime") - .HasColumnType("int"); - - b.Property("UpdateAccessTokenClaimsOnRefresh") - .HasColumnType("tinyint(1)"); - - b.Property("Updated") - .HasColumnType("datetime(6)"); - - b.Property("UserCodeType") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("UserSsoLifetime") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ClientId") - .IsUnique(); - - b.ToTable("Clients"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Origin") - .IsRequired() - .HasMaxLength(150) - .HasColumnType("varchar(150)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientCorsOrigins"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("GrantType") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientGrantTypes"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Provider") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientIdPRestrictions"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("PostLogoutRedirectUri") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientPostLogoutRedirectUris"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientProperties"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("RedirectUri") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientRedirectUris"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Scope") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientScopes"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("Expiration") - .HasColumnType("datetime(6)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(4000) - .HasColumnType("varchar(4000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientSecrets"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityProvider", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("Properties") - .HasColumnType("longtext"); - - b.Property("Scheme") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("varchar(20)"); - - b.HasKey("Id"); - - b.ToTable("IdentityProviders"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Emphasize") - .HasColumnType("tinyint(1)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("NonEditable") - .HasColumnType("tinyint(1)"); - - b.Property("Required") - .HasColumnType("tinyint(1)"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("tinyint(1)"); - - b.Property("Updated") - .HasColumnType("datetime(6)"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("IdentityResources"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("IdentityResourceId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId"); - - b.ToTable("IdentityResourceClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("IdentityResourceId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId"); - - b.ToTable("IdentityResourceProperties"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Properties") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Scopes") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Secrets") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") - .WithMany("UserClaims") - .HasForeignKey("ScopeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Scope"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") - .WithMany("Properties") - .HasForeignKey("ScopeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Scope"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("Claims") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedCorsOrigins") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedGrantTypes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("IdentityProviderRestrictions") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("PostLogoutRedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("Properties") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("RedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedScopes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("ClientSecrets") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("UserClaims") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("IdentityResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("Properties") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("IdentityResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => - { - b.Navigation("Properties"); - - b.Navigation("Scopes"); - - b.Navigation("Secrets"); - - b.Navigation("UserClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => - { - b.Navigation("Properties"); - - b.Navigation("UserClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => - { - b.Navigation("AllowedCorsOrigins"); - - b.Navigation("AllowedGrantTypes"); - - b.Navigation("AllowedScopes"); - - b.Navigation("Claims"); - - b.Navigation("ClientSecrets"); - - b.Navigation("IdentityProviderRestrictions"); - - b.Navigation("PostLogoutRedirectUris"); - - b.Navigation("Properties"); - - b.Navigation("RedirectUris"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => - { - b.Navigation("Properties"); - - b.Navigation("UserClaims"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/ConfigurationDb/20211201215951_InitialCreate.cs b/archive/SecurityService.MySqlMigrations/ConfigurationDb/20211201215951_InitialCreate.cs deleted file mode 100644 index 3a398ed2..00000000 --- a/archive/SecurityService.MySqlMigrations/ConfigurationDb/20211201215951_InitialCreate.cs +++ /dev/null @@ -1,756 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace SecurityService.MySqlMigrations.ConfigurationDb -{ - public partial class InitialCreate : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterDatabase() - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "ApiResources", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - Enabled = table.Column(type: "tinyint(1)", nullable: false), - Name = table.Column(type: "varchar(200)", maxLength: 200, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - DisplayName = table.Column(type: "varchar(200)", maxLength: 200, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Description = table.Column(type: "varchar(1000)", maxLength: 1000, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - AllowedAccessTokenSigningAlgorithms = table.Column(type: "varchar(100)", maxLength: 100, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - ShowInDiscoveryDocument = table.Column(type: "tinyint(1)", nullable: false), - RequireResourceIndicator = table.Column(type: "tinyint(1)", nullable: false), - Created = table.Column(type: "datetime(6)", nullable: false), - Updated = table.Column(type: "datetime(6)", nullable: true), - LastAccessed = table.Column(type: "datetime(6)", nullable: true), - NonEditable = table.Column(type: "tinyint(1)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiResources", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "ApiScopes", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - Enabled = table.Column(type: "tinyint(1)", nullable: false), - Name = table.Column(type: "varchar(200)", maxLength: 200, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - DisplayName = table.Column(type: "varchar(200)", maxLength: 200, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Description = table.Column(type: "varchar(1000)", maxLength: 1000, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Required = table.Column(type: "tinyint(1)", nullable: false), - Emphasize = table.Column(type: "tinyint(1)", nullable: false), - ShowInDiscoveryDocument = table.Column(type: "tinyint(1)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiScopes", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "Clients", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - Enabled = table.Column(type: "tinyint(1)", nullable: false), - ClientId = table.Column(type: "varchar(200)", maxLength: 200, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ProtocolType = table.Column(type: "varchar(200)", maxLength: 200, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - RequireClientSecret = table.Column(type: "tinyint(1)", nullable: false), - ClientName = table.Column(type: "varchar(200)", maxLength: 200, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Description = table.Column(type: "varchar(1000)", maxLength: 1000, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - ClientUri = table.Column(type: "varchar(2000)", maxLength: 2000, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - LogoUri = table.Column(type: "varchar(2000)", maxLength: 2000, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - RequireConsent = table.Column(type: "tinyint(1)", nullable: false), - AllowRememberConsent = table.Column(type: "tinyint(1)", nullable: false), - AlwaysIncludeUserClaimsInIdToken = table.Column(type: "tinyint(1)", nullable: false), - RequirePkce = table.Column(type: "tinyint(1)", nullable: false), - AllowPlainTextPkce = table.Column(type: "tinyint(1)", nullable: false), - RequireRequestObject = table.Column(type: "tinyint(1)", nullable: false), - AllowAccessTokensViaBrowser = table.Column(type: "tinyint(1)", nullable: false), - FrontChannelLogoutUri = table.Column(type: "varchar(2000)", maxLength: 2000, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - FrontChannelLogoutSessionRequired = table.Column(type: "tinyint(1)", nullable: false), - BackChannelLogoutUri = table.Column(type: "varchar(2000)", maxLength: 2000, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - BackChannelLogoutSessionRequired = table.Column(type: "tinyint(1)", nullable: false), - AllowOfflineAccess = table.Column(type: "tinyint(1)", nullable: false), - IdentityTokenLifetime = table.Column(type: "int", nullable: false), - AllowedIdentityTokenSigningAlgorithms = table.Column(type: "varchar(100)", maxLength: 100, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - AccessTokenLifetime = table.Column(type: "int", nullable: false), - AuthorizationCodeLifetime = table.Column(type: "int", nullable: false), - ConsentLifetime = table.Column(type: "int", nullable: true), - AbsoluteRefreshTokenLifetime = table.Column(type: "int", nullable: false), - SlidingRefreshTokenLifetime = table.Column(type: "int", nullable: false), - RefreshTokenUsage = table.Column(type: "int", nullable: false), - UpdateAccessTokenClaimsOnRefresh = table.Column(type: "tinyint(1)", nullable: false), - RefreshTokenExpiration = table.Column(type: "int", nullable: false), - AccessTokenType = table.Column(type: "int", nullable: false), - EnableLocalLogin = table.Column(type: "tinyint(1)", nullable: false), - IncludeJwtId = table.Column(type: "tinyint(1)", nullable: false), - AlwaysSendClientClaims = table.Column(type: "tinyint(1)", nullable: false), - ClientClaimsPrefix = table.Column(type: "varchar(200)", maxLength: 200, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - PairWiseSubjectSalt = table.Column(type: "varchar(200)", maxLength: 200, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Created = table.Column(type: "datetime(6)", nullable: false), - Updated = table.Column(type: "datetime(6)", nullable: true), - LastAccessed = table.Column(type: "datetime(6)", nullable: true), - UserSsoLifetime = table.Column(type: "int", nullable: true), - UserCodeType = table.Column(type: "varchar(100)", maxLength: 100, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - DeviceCodeLifetime = table.Column(type: "int", nullable: false), - NonEditable = table.Column(type: "tinyint(1)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Clients", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "IdentityProviders", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - Scheme = table.Column(type: "varchar(200)", maxLength: 200, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - DisplayName = table.Column(type: "varchar(200)", maxLength: 200, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Enabled = table.Column(type: "tinyint(1)", nullable: false), - Type = table.Column(type: "varchar(20)", maxLength: 20, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Properties = table.Column(type: "longtext", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_IdentityProviders", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "IdentityResources", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - Enabled = table.Column(type: "tinyint(1)", nullable: false), - Name = table.Column(type: "varchar(200)", maxLength: 200, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - DisplayName = table.Column(type: "varchar(200)", maxLength: 200, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Description = table.Column(type: "varchar(1000)", maxLength: 1000, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Required = table.Column(type: "tinyint(1)", nullable: false), - Emphasize = table.Column(type: "tinyint(1)", nullable: false), - ShowInDiscoveryDocument = table.Column(type: "tinyint(1)", nullable: false), - Created = table.Column(type: "datetime(6)", nullable: false), - Updated = table.Column(type: "datetime(6)", nullable: true), - NonEditable = table.Column(type: "tinyint(1)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_IdentityResources", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "ApiResourceClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - ApiResourceId = table.Column(type: "int", nullable: false), - Type = table.Column(type: "varchar(200)", maxLength: 200, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_ApiResourceClaims", x => x.Id); - table.ForeignKey( - name: "FK_ApiResourceClaims_ApiResources_ApiResourceId", - column: x => x.ApiResourceId, - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "ApiResourceProperties", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - ApiResourceId = table.Column(type: "int", nullable: false), - Key = table.Column(type: "varchar(250)", maxLength: 250, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Value = table.Column(type: "varchar(2000)", maxLength: 2000, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_ApiResourceProperties", x => x.Id); - table.ForeignKey( - name: "FK_ApiResourceProperties_ApiResources_ApiResourceId", - column: x => x.ApiResourceId, - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "ApiResourceScopes", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - Scope = table.Column(type: "varchar(200)", maxLength: 200, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ApiResourceId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiResourceScopes", x => x.Id); - table.ForeignKey( - name: "FK_ApiResourceScopes_ApiResources_ApiResourceId", - column: x => x.ApiResourceId, - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "ApiResourceSecrets", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - ApiResourceId = table.Column(type: "int", nullable: false), - Description = table.Column(type: "varchar(1000)", maxLength: 1000, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Value = table.Column(type: "varchar(4000)", maxLength: 4000, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Expiration = table.Column(type: "datetime(6)", nullable: true), - Type = table.Column(type: "varchar(250)", maxLength: 250, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Created = table.Column(type: "datetime(6)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiResourceSecrets", x => x.Id); - table.ForeignKey( - name: "FK_ApiResourceSecrets_ApiResources_ApiResourceId", - column: x => x.ApiResourceId, - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "ApiScopeClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - ScopeId = table.Column(type: "int", nullable: false), - Type = table.Column(type: "varchar(200)", maxLength: 200, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_ApiScopeClaims", x => x.Id); - table.ForeignKey( - name: "FK_ApiScopeClaims_ApiScopes_ScopeId", - column: x => x.ScopeId, - principalTable: "ApiScopes", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "ApiScopeProperties", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - ScopeId = table.Column(type: "int", nullable: false), - Key = table.Column(type: "varchar(250)", maxLength: 250, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Value = table.Column(type: "varchar(2000)", maxLength: 2000, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_ApiScopeProperties", x => x.Id); - table.ForeignKey( - name: "FK_ApiScopeProperties_ApiScopes_ScopeId", - column: x => x.ScopeId, - principalTable: "ApiScopes", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "ClientClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - Type = table.Column(type: "varchar(250)", maxLength: 250, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Value = table.Column(type: "varchar(250)", maxLength: 250, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ClientId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientClaims", x => x.Id); - table.ForeignKey( - name: "FK_ClientClaims_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "ClientCorsOrigins", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - Origin = table.Column(type: "varchar(150)", maxLength: 150, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ClientId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientCorsOrigins", x => x.Id); - table.ForeignKey( - name: "FK_ClientCorsOrigins_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "ClientGrantTypes", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - GrantType = table.Column(type: "varchar(250)", maxLength: 250, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ClientId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientGrantTypes", x => x.Id); - table.ForeignKey( - name: "FK_ClientGrantTypes_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "ClientIdPRestrictions", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - Provider = table.Column(type: "varchar(200)", maxLength: 200, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ClientId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientIdPRestrictions", x => x.Id); - table.ForeignKey( - name: "FK_ClientIdPRestrictions_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "ClientPostLogoutRedirectUris", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - PostLogoutRedirectUri = table.Column(type: "varchar(2000)", maxLength: 2000, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ClientId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientPostLogoutRedirectUris", x => x.Id); - table.ForeignKey( - name: "FK_ClientPostLogoutRedirectUris_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "ClientProperties", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - ClientId = table.Column(type: "int", nullable: false), - Key = table.Column(type: "varchar(250)", maxLength: 250, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Value = table.Column(type: "varchar(2000)", maxLength: 2000, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_ClientProperties", x => x.Id); - table.ForeignKey( - name: "FK_ClientProperties_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "ClientRedirectUris", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - RedirectUri = table.Column(type: "varchar(2000)", maxLength: 2000, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ClientId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientRedirectUris", x => x.Id); - table.ForeignKey( - name: "FK_ClientRedirectUris_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "ClientScopes", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - Scope = table.Column(type: "varchar(200)", maxLength: 200, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ClientId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientScopes", x => x.Id); - table.ForeignKey( - name: "FK_ClientScopes_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "ClientSecrets", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - ClientId = table.Column(type: "int", nullable: false), - Description = table.Column(type: "varchar(2000)", maxLength: 2000, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Value = table.Column(type: "varchar(4000)", maxLength: 4000, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Expiration = table.Column(type: "datetime(6)", nullable: true), - Type = table.Column(type: "varchar(250)", maxLength: 250, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Created = table.Column(type: "datetime(6)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientSecrets", x => x.Id); - table.ForeignKey( - name: "FK_ClientSecrets_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "IdentityResourceClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - IdentityResourceId = table.Column(type: "int", nullable: false), - Type = table.Column(type: "varchar(200)", maxLength: 200, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_IdentityResourceClaims", x => x.Id); - table.ForeignKey( - name: "FK_IdentityResourceClaims_IdentityResources_IdentityResourceId", - column: x => x.IdentityResourceId, - principalTable: "IdentityResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "IdentityResourceProperties", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - IdentityResourceId = table.Column(type: "int", nullable: false), - Key = table.Column(type: "varchar(250)", maxLength: 250, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Value = table.Column(type: "varchar(2000)", maxLength: 2000, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_IdentityResourceProperties", x => x.Id); - table.ForeignKey( - name: "FK_IdentityResourceProperties_IdentityResources_IdentityResourc~", - column: x => x.IdentityResourceId, - principalTable: "IdentityResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceClaims_ApiResourceId", - table: "ApiResourceClaims", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceProperties_ApiResourceId", - table: "ApiResourceProperties", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiResources_Name", - table: "ApiResources", - column: "Name", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceScopes_ApiResourceId", - table: "ApiResourceScopes", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceSecrets_ApiResourceId", - table: "ApiResourceSecrets", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopeClaims_ScopeId", - table: "ApiScopeClaims", - column: "ScopeId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopeProperties_ScopeId", - table: "ApiScopeProperties", - column: "ScopeId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopes_Name", - table: "ApiScopes", - column: "Name", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientClaims_ClientId", - table: "ClientClaims", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientCorsOrigins_ClientId", - table: "ClientCorsOrigins", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientGrantTypes_ClientId", - table: "ClientGrantTypes", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientIdPRestrictions_ClientId", - table: "ClientIdPRestrictions", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientPostLogoutRedirectUris_ClientId", - table: "ClientPostLogoutRedirectUris", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientProperties_ClientId", - table: "ClientProperties", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientRedirectUris_ClientId", - table: "ClientRedirectUris", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_Clients_ClientId", - table: "Clients", - column: "ClientId", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientScopes_ClientId", - table: "ClientScopes", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientSecrets_ClientId", - table: "ClientSecrets", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_IdentityResourceClaims_IdentityResourceId", - table: "IdentityResourceClaims", - column: "IdentityResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_IdentityResourceProperties_IdentityResourceId", - table: "IdentityResourceProperties", - column: "IdentityResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_IdentityResources_Name", - table: "IdentityResources", - column: "Name", - unique: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "ApiResourceClaims"); - - migrationBuilder.DropTable( - name: "ApiResourceProperties"); - - migrationBuilder.DropTable( - name: "ApiResourceScopes"); - - migrationBuilder.DropTable( - name: "ApiResourceSecrets"); - - migrationBuilder.DropTable( - name: "ApiScopeClaims"); - - migrationBuilder.DropTable( - name: "ApiScopeProperties"); - - migrationBuilder.DropTable( - name: "ClientClaims"); - - migrationBuilder.DropTable( - name: "ClientCorsOrigins"); - - migrationBuilder.DropTable( - name: "ClientGrantTypes"); - - migrationBuilder.DropTable( - name: "ClientIdPRestrictions"); - - migrationBuilder.DropTable( - name: "ClientPostLogoutRedirectUris"); - - migrationBuilder.DropTable( - name: "ClientProperties"); - - migrationBuilder.DropTable( - name: "ClientRedirectUris"); - - migrationBuilder.DropTable( - name: "ClientScopes"); - - migrationBuilder.DropTable( - name: "ClientSecrets"); - - migrationBuilder.DropTable( - name: "IdentityProviders"); - - migrationBuilder.DropTable( - name: "IdentityResourceClaims"); - - migrationBuilder.DropTable( - name: "IdentityResourceProperties"); - - migrationBuilder.DropTable( - name: "ApiResources"); - - migrationBuilder.DropTable( - name: "ApiScopes"); - - migrationBuilder.DropTable( - name: "Clients"); - - migrationBuilder.DropTable( - name: "IdentityResources"); - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/ConfigurationDb/20220609181951_Net6Update.Designer.cs b/archive/SecurityService.MySqlMigrations/ConfigurationDb/20220609181951_Net6Update.Designer.cs deleted file mode 100644 index 32510e05..00000000 --- a/archive/SecurityService.MySqlMigrations/ConfigurationDb/20220609181951_Net6Update.Designer.cs +++ /dev/null @@ -1,1049 +0,0 @@ -// -using System; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace SecurityService.MySqlMigrations.ConfigurationDb -{ - [DbContext(typeof(ConfigurationDbContext))] - [Migration("20220609181951_Net6Update")] - partial class Net6Update - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "6.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("AllowedAccessTokenSigningAlgorithms") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("LastAccessed") - .HasColumnType("datetime(6)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("NonEditable") - .HasColumnType("tinyint(1)"); - - b.Property("RequireResourceIndicator") - .HasColumnType("tinyint(1)"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("tinyint(1)"); - - b.Property("Updated") - .HasColumnType("datetime(6)"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiResources", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId", "Type") - .IsUnique(); - - b.ToTable("ApiResourceClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId", "Key") - .IsUnique(); - - b.ToTable("ApiResourceProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Scope") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId", "Scope") - .IsUnique(); - - b.ToTable("ApiResourceScopes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("Expiration") - .HasColumnType("datetime(6)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(4000) - .HasColumnType("varchar(4000)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiResourceSecrets", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Emphasize") - .HasColumnType("tinyint(1)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("LastAccessed") - .HasColumnType("datetime(6)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("NonEditable") - .HasColumnType("tinyint(1)"); - - b.Property("Required") - .HasColumnType("tinyint(1)"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("tinyint(1)"); - - b.Property("Updated") - .HasColumnType("datetime(6)"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiScopes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ScopeId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ScopeId", "Type") - .IsUnique(); - - b.ToTable("ApiScopeClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("ScopeId") - .HasColumnType("int"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ScopeId", "Key") - .IsUnique(); - - b.ToTable("ApiScopeProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("AbsoluteRefreshTokenLifetime") - .HasColumnType("int"); - - b.Property("AccessTokenLifetime") - .HasColumnType("int"); - - b.Property("AccessTokenType") - .HasColumnType("int"); - - b.Property("AllowAccessTokensViaBrowser") - .HasColumnType("tinyint(1)"); - - b.Property("AllowOfflineAccess") - .HasColumnType("tinyint(1)"); - - b.Property("AllowPlainTextPkce") - .HasColumnType("tinyint(1)"); - - b.Property("AllowRememberConsent") - .HasColumnType("tinyint(1)"); - - b.Property("AllowedIdentityTokenSigningAlgorithms") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("AlwaysIncludeUserClaimsInIdToken") - .HasColumnType("tinyint(1)"); - - b.Property("AlwaysSendClientClaims") - .HasColumnType("tinyint(1)"); - - b.Property("AuthorizationCodeLifetime") - .HasColumnType("int"); - - b.Property("BackChannelLogoutSessionRequired") - .HasColumnType("tinyint(1)"); - - b.Property("BackChannelLogoutUri") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("CibaLifetime") - .HasColumnType("int"); - - b.Property("ClientClaimsPrefix") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ClientName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ClientUri") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("ConsentLifetime") - .HasColumnType("int"); - - b.Property("CoordinateLifetimeWithUserSession") - .HasColumnType("tinyint(1)"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("DeviceCodeLifetime") - .HasColumnType("int"); - - b.Property("EnableLocalLogin") - .HasColumnType("tinyint(1)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("FrontChannelLogoutSessionRequired") - .HasColumnType("tinyint(1)"); - - b.Property("FrontChannelLogoutUri") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("IdentityTokenLifetime") - .HasColumnType("int"); - - b.Property("IncludeJwtId") - .HasColumnType("tinyint(1)"); - - b.Property("LastAccessed") - .HasColumnType("datetime(6)"); - - b.Property("LogoUri") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("NonEditable") - .HasColumnType("tinyint(1)"); - - b.Property("PairWiseSubjectSalt") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("PollingInterval") - .HasColumnType("int"); - - b.Property("ProtocolType") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("RefreshTokenExpiration") - .HasColumnType("int"); - - b.Property("RefreshTokenUsage") - .HasColumnType("int"); - - b.Property("RequireClientSecret") - .HasColumnType("tinyint(1)"); - - b.Property("RequireConsent") - .HasColumnType("tinyint(1)"); - - b.Property("RequirePkce") - .HasColumnType("tinyint(1)"); - - b.Property("RequireRequestObject") - .HasColumnType("tinyint(1)"); - - b.Property("SlidingRefreshTokenLifetime") - .HasColumnType("int"); - - b.Property("UpdateAccessTokenClaimsOnRefresh") - .HasColumnType("tinyint(1)"); - - b.Property("Updated") - .HasColumnType("datetime(6)"); - - b.Property("UserCodeType") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("UserSsoLifetime") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ClientId") - .IsUnique(); - - b.ToTable("Clients", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Type", "Value") - .IsUnique(); - - b.ToTable("ClientClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Origin") - .IsRequired() - .HasMaxLength(150) - .HasColumnType("varchar(150)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Origin") - .IsUnique(); - - b.ToTable("ClientCorsOrigins", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("GrantType") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "GrantType") - .IsUnique(); - - b.ToTable("ClientGrantTypes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Provider") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Provider") - .IsUnique(); - - b.ToTable("ClientIdPRestrictions", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("PostLogoutRedirectUri") - .IsRequired() - .HasMaxLength(400) - .HasColumnType("varchar(400)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "PostLogoutRedirectUri") - .IsUnique(); - - b.ToTable("ClientPostLogoutRedirectUris", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Key") - .IsUnique(); - - b.ToTable("ClientProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("RedirectUri") - .IsRequired() - .HasMaxLength(400) - .HasColumnType("varchar(400)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "RedirectUri") - .IsUnique(); - - b.ToTable("ClientRedirectUris", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Scope") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Scope") - .IsUnique(); - - b.ToTable("ClientScopes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("Expiration") - .HasColumnType("datetime(6)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(4000) - .HasColumnType("varchar(4000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientSecrets", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityProvider", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("LastAccessed") - .HasColumnType("datetime(6)"); - - b.Property("NonEditable") - .HasColumnType("tinyint(1)"); - - b.Property("Properties") - .HasColumnType("longtext"); - - b.Property("Scheme") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("varchar(20)"); - - b.Property("Updated") - .HasColumnType("datetime(6)"); - - b.HasKey("Id"); - - b.HasIndex("Scheme") - .IsUnique(); - - b.ToTable("IdentityProviders", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Emphasize") - .HasColumnType("tinyint(1)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("NonEditable") - .HasColumnType("tinyint(1)"); - - b.Property("Required") - .HasColumnType("tinyint(1)"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("tinyint(1)"); - - b.Property("Updated") - .HasColumnType("datetime(6)"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("IdentityResources", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("IdentityResourceId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId", "Type") - .IsUnique(); - - b.ToTable("IdentityResourceClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("IdentityResourceId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId", "Key") - .IsUnique(); - - b.ToTable("IdentityResourceProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Properties") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Scopes") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Secrets") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") - .WithMany("UserClaims") - .HasForeignKey("ScopeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Scope"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") - .WithMany("Properties") - .HasForeignKey("ScopeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Scope"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("Claims") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedCorsOrigins") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedGrantTypes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("IdentityProviderRestrictions") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("PostLogoutRedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("Properties") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("RedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedScopes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("ClientSecrets") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("UserClaims") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("IdentityResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("Properties") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("IdentityResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => - { - b.Navigation("Properties"); - - b.Navigation("Scopes"); - - b.Navigation("Secrets"); - - b.Navigation("UserClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => - { - b.Navigation("Properties"); - - b.Navigation("UserClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => - { - b.Navigation("AllowedCorsOrigins"); - - b.Navigation("AllowedGrantTypes"); - - b.Navigation("AllowedScopes"); - - b.Navigation("Claims"); - - b.Navigation("ClientSecrets"); - - b.Navigation("IdentityProviderRestrictions"); - - b.Navigation("PostLogoutRedirectUris"); - - b.Navigation("Properties"); - - b.Navigation("RedirectUris"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => - { - b.Navigation("Properties"); - - b.Navigation("UserClaims"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/ConfigurationDb/20220609181951_Net6Update.cs b/archive/SecurityService.MySqlMigrations/ConfigurationDb/20220609181951_Net6Update.cs deleted file mode 100644 index 2cc2d2c3..00000000 --- a/archive/SecurityService.MySqlMigrations/ConfigurationDb/20220609181951_Net6Update.cs +++ /dev/null @@ -1,473 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace SecurityService.MySqlMigrations.ConfigurationDb -{ - public partial class Net6Update : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_IdentityResourceProperties_IdentityResourceId", - table: "IdentityResourceProperties"); - - migrationBuilder.DropIndex( - name: "IX_IdentityResourceClaims_IdentityResourceId", - table: "IdentityResourceClaims"); - - migrationBuilder.DropIndex( - name: "IX_ClientScopes_ClientId", - table: "ClientScopes"); - - migrationBuilder.DropIndex( - name: "IX_ClientRedirectUris_ClientId", - table: "ClientRedirectUris"); - - migrationBuilder.DropIndex( - name: "IX_ClientProperties_ClientId", - table: "ClientProperties"); - - migrationBuilder.DropIndex( - name: "IX_ClientPostLogoutRedirectUris_ClientId", - table: "ClientPostLogoutRedirectUris"); - - migrationBuilder.DropIndex( - name: "IX_ClientIdPRestrictions_ClientId", - table: "ClientIdPRestrictions"); - - migrationBuilder.DropIndex( - name: "IX_ClientGrantTypes_ClientId", - table: "ClientGrantTypes"); - - migrationBuilder.DropIndex( - name: "IX_ClientCorsOrigins_ClientId", - table: "ClientCorsOrigins"); - - migrationBuilder.DropIndex( - name: "IX_ClientClaims_ClientId", - table: "ClientClaims"); - - migrationBuilder.DropIndex( - name: "IX_ApiScopeProperties_ScopeId", - table: "ApiScopeProperties"); - - migrationBuilder.DropIndex( - name: "IX_ApiScopeClaims_ScopeId", - table: "ApiScopeClaims"); - - migrationBuilder.DropIndex( - name: "IX_ApiResourceScopes_ApiResourceId", - table: "ApiResourceScopes"); - - migrationBuilder.DropIndex( - name: "IX_ApiResourceProperties_ApiResourceId", - table: "ApiResourceProperties"); - - migrationBuilder.DropIndex( - name: "IX_ApiResourceClaims_ApiResourceId", - table: "ApiResourceClaims"); - - migrationBuilder.AddColumn( - name: "Created", - table: "IdentityProviders", - type: "datetime(6)", - nullable: false, - defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); - - migrationBuilder.AddColumn( - name: "LastAccessed", - table: "IdentityProviders", - type: "datetime(6)", - nullable: true); - - migrationBuilder.AddColumn( - name: "NonEditable", - table: "IdentityProviders", - type: "tinyint(1)", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "Updated", - table: "IdentityProviders", - type: "datetime(6)", - nullable: true); - - migrationBuilder.AddColumn( - name: "CibaLifetime", - table: "Clients", - type: "int", - nullable: true); - - migrationBuilder.AddColumn( - name: "CoordinateLifetimeWithUserSession", - table: "Clients", - type: "tinyint(1)", - nullable: true); - - migrationBuilder.AddColumn( - name: "PollingInterval", - table: "Clients", - type: "int", - nullable: true); - - migrationBuilder.AlterColumn( - name: "RedirectUri", - table: "ClientRedirectUris", - type: "varchar(400)", - maxLength: 400, - nullable: false, - oldClrType: typeof(string), - oldType: "varchar(2000)", - oldMaxLength: 2000) - .Annotation("MySql:CharSet", "utf8mb4") - .OldAnnotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AlterColumn( - name: "PostLogoutRedirectUri", - table: "ClientPostLogoutRedirectUris", - type: "varchar(400)", - maxLength: 400, - nullable: false, - oldClrType: typeof(string), - oldType: "varchar(2000)", - oldMaxLength: 2000) - .Annotation("MySql:CharSet", "utf8mb4") - .OldAnnotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AddColumn( - name: "Created", - table: "ApiScopes", - type: "datetime(6)", - nullable: false, - defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); - - migrationBuilder.AddColumn( - name: "LastAccessed", - table: "ApiScopes", - type: "datetime(6)", - nullable: true); - - migrationBuilder.AddColumn( - name: "NonEditable", - table: "ApiScopes", - type: "tinyint(1)", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "Updated", - table: "ApiScopes", - type: "datetime(6)", - nullable: true); - - migrationBuilder.CreateIndex( - name: "IX_IdentityResourceProperties_IdentityResourceId_Key", - table: "IdentityResourceProperties", - columns: new[] { "IdentityResourceId", "Key" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_IdentityResourceClaims_IdentityResourceId_Type", - table: "IdentityResourceClaims", - columns: new[] { "IdentityResourceId", "Type" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_IdentityProviders_Scheme", - table: "IdentityProviders", - column: "Scheme", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientScopes_ClientId_Scope", - table: "ClientScopes", - columns: new[] { "ClientId", "Scope" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientRedirectUris_ClientId_RedirectUri", - table: "ClientRedirectUris", - columns: new[] { "ClientId", "RedirectUri" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientProperties_ClientId_Key", - table: "ClientProperties", - columns: new[] { "ClientId", "Key" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientPostLogoutRedirectUris_ClientId_PostLogoutRedirectUri", - table: "ClientPostLogoutRedirectUris", - columns: new[] { "ClientId", "PostLogoutRedirectUri" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientIdPRestrictions_ClientId_Provider", - table: "ClientIdPRestrictions", - columns: new[] { "ClientId", "Provider" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientGrantTypes_ClientId_GrantType", - table: "ClientGrantTypes", - columns: new[] { "ClientId", "GrantType" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientCorsOrigins_ClientId_Origin", - table: "ClientCorsOrigins", - columns: new[] { "ClientId", "Origin" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientClaims_ClientId_Type_Value", - table: "ClientClaims", - columns: new[] { "ClientId", "Type", "Value" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopeProperties_ScopeId_Key", - table: "ApiScopeProperties", - columns: new[] { "ScopeId", "Key" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopeClaims_ScopeId_Type", - table: "ApiScopeClaims", - columns: new[] { "ScopeId", "Type" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceScopes_ApiResourceId_Scope", - table: "ApiResourceScopes", - columns: new[] { "ApiResourceId", "Scope" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceProperties_ApiResourceId_Key", - table: "ApiResourceProperties", - columns: new[] { "ApiResourceId", "Key" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceClaims_ApiResourceId_Type", - table: "ApiResourceClaims", - columns: new[] { "ApiResourceId", "Type" }, - unique: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_IdentityResourceProperties_IdentityResourceId_Key", - table: "IdentityResourceProperties"); - - migrationBuilder.DropIndex( - name: "IX_IdentityResourceClaims_IdentityResourceId_Type", - table: "IdentityResourceClaims"); - - migrationBuilder.DropIndex( - name: "IX_IdentityProviders_Scheme", - table: "IdentityProviders"); - - migrationBuilder.DropIndex( - name: "IX_ClientScopes_ClientId_Scope", - table: "ClientScopes"); - - migrationBuilder.DropIndex( - name: "IX_ClientRedirectUris_ClientId_RedirectUri", - table: "ClientRedirectUris"); - - migrationBuilder.DropIndex( - name: "IX_ClientProperties_ClientId_Key", - table: "ClientProperties"); - - migrationBuilder.DropIndex( - name: "IX_ClientPostLogoutRedirectUris_ClientId_PostLogoutRedirectUri", - table: "ClientPostLogoutRedirectUris"); - - migrationBuilder.DropIndex( - name: "IX_ClientIdPRestrictions_ClientId_Provider", - table: "ClientIdPRestrictions"); - - migrationBuilder.DropIndex( - name: "IX_ClientGrantTypes_ClientId_GrantType", - table: "ClientGrantTypes"); - - migrationBuilder.DropIndex( - name: "IX_ClientCorsOrigins_ClientId_Origin", - table: "ClientCorsOrigins"); - - migrationBuilder.DropIndex( - name: "IX_ClientClaims_ClientId_Type_Value", - table: "ClientClaims"); - - migrationBuilder.DropIndex( - name: "IX_ApiScopeProperties_ScopeId_Key", - table: "ApiScopeProperties"); - - migrationBuilder.DropIndex( - name: "IX_ApiScopeClaims_ScopeId_Type", - table: "ApiScopeClaims"); - - migrationBuilder.DropIndex( - name: "IX_ApiResourceScopes_ApiResourceId_Scope", - table: "ApiResourceScopes"); - - migrationBuilder.DropIndex( - name: "IX_ApiResourceProperties_ApiResourceId_Key", - table: "ApiResourceProperties"); - - migrationBuilder.DropIndex( - name: "IX_ApiResourceClaims_ApiResourceId_Type", - table: "ApiResourceClaims"); - - migrationBuilder.DropColumn( - name: "Created", - table: "IdentityProviders"); - - migrationBuilder.DropColumn( - name: "LastAccessed", - table: "IdentityProviders"); - - migrationBuilder.DropColumn( - name: "NonEditable", - table: "IdentityProviders"); - - migrationBuilder.DropColumn( - name: "Updated", - table: "IdentityProviders"); - - migrationBuilder.DropColumn( - name: "CibaLifetime", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "CoordinateLifetimeWithUserSession", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "PollingInterval", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "Created", - table: "ApiScopes"); - - migrationBuilder.DropColumn( - name: "LastAccessed", - table: "ApiScopes"); - - migrationBuilder.DropColumn( - name: "NonEditable", - table: "ApiScopes"); - - migrationBuilder.DropColumn( - name: "Updated", - table: "ApiScopes"); - - migrationBuilder.AlterColumn( - name: "RedirectUri", - table: "ClientRedirectUris", - type: "varchar(2000)", - maxLength: 2000, - nullable: false, - oldClrType: typeof(string), - oldType: "varchar(400)", - oldMaxLength: 400) - .Annotation("MySql:CharSet", "utf8mb4") - .OldAnnotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AlterColumn( - name: "PostLogoutRedirectUri", - table: "ClientPostLogoutRedirectUris", - type: "varchar(2000)", - maxLength: 2000, - nullable: false, - oldClrType: typeof(string), - oldType: "varchar(400)", - oldMaxLength: 400) - .Annotation("MySql:CharSet", "utf8mb4") - .OldAnnotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateIndex( - name: "IX_IdentityResourceProperties_IdentityResourceId", - table: "IdentityResourceProperties", - column: "IdentityResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_IdentityResourceClaims_IdentityResourceId", - table: "IdentityResourceClaims", - column: "IdentityResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientScopes_ClientId", - table: "ClientScopes", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientRedirectUris_ClientId", - table: "ClientRedirectUris", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientProperties_ClientId", - table: "ClientProperties", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientPostLogoutRedirectUris_ClientId", - table: "ClientPostLogoutRedirectUris", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientIdPRestrictions_ClientId", - table: "ClientIdPRestrictions", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientGrantTypes_ClientId", - table: "ClientGrantTypes", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientCorsOrigins_ClientId", - table: "ClientCorsOrigins", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientClaims_ClientId", - table: "ClientClaims", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopeProperties_ScopeId", - table: "ApiScopeProperties", - column: "ScopeId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopeClaims_ScopeId", - table: "ApiScopeClaims", - column: "ScopeId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceScopes_ApiResourceId", - table: "ApiResourceScopes", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceProperties_ApiResourceId", - table: "ApiResourceProperties", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceClaims_ApiResourceId", - table: "ApiResourceClaims", - column: "ApiResourceId"); - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/ConfigurationDb/20240325172125_net8upgrade.Designer.cs b/archive/SecurityService.MySqlMigrations/ConfigurationDb/20240325172125_net8upgrade.Designer.cs deleted file mode 100644 index 21562bb9..00000000 --- a/archive/SecurityService.MySqlMigrations/ConfigurationDb/20240325172125_net8upgrade.Designer.cs +++ /dev/null @@ -1,1116 +0,0 @@ -// -using System; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace SecurityService.MySqlMigrations.ConfigurationDb -{ - [DbContext(typeof(ConfigurationDbContext))] - [Migration("20240325172125_net8upgrade")] - partial class net8upgrade - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("AllowedAccessTokenSigningAlgorithms") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("LastAccessed") - .HasColumnType("datetime(6)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("NonEditable") - .HasColumnType("tinyint(1)"); - - b.Property("RequireResourceIndicator") - .HasColumnType("tinyint(1)"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("tinyint(1)"); - - b.Property("Updated") - .HasColumnType("datetime(6)"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiResources", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId", "Type") - .IsUnique(); - - b.ToTable("ApiResourceClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId", "Key") - .IsUnique(); - - b.ToTable("ApiResourceProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Scope") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId", "Scope") - .IsUnique(); - - b.ToTable("ApiResourceScopes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("Expiration") - .HasColumnType("datetime(6)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(4000) - .HasColumnType("varchar(4000)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiResourceSecrets", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Emphasize") - .HasColumnType("tinyint(1)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("LastAccessed") - .HasColumnType("datetime(6)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("NonEditable") - .HasColumnType("tinyint(1)"); - - b.Property("Required") - .HasColumnType("tinyint(1)"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("tinyint(1)"); - - b.Property("Updated") - .HasColumnType("datetime(6)"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiScopes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ScopeId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ScopeId", "Type") - .IsUnique(); - - b.ToTable("ApiScopeClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("ScopeId") - .HasColumnType("int"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ScopeId", "Key") - .IsUnique(); - - b.ToTable("ApiScopeProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("AbsoluteRefreshTokenLifetime") - .HasColumnType("int"); - - b.Property("AccessTokenLifetime") - .HasColumnType("int"); - - b.Property("AccessTokenType") - .HasColumnType("int"); - - b.Property("AllowAccessTokensViaBrowser") - .HasColumnType("tinyint(1)"); - - b.Property("AllowOfflineAccess") - .HasColumnType("tinyint(1)"); - - b.Property("AllowPlainTextPkce") - .HasColumnType("tinyint(1)"); - - b.Property("AllowRememberConsent") - .HasColumnType("tinyint(1)"); - - b.Property("AllowedIdentityTokenSigningAlgorithms") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("AlwaysIncludeUserClaimsInIdToken") - .HasColumnType("tinyint(1)"); - - b.Property("AlwaysSendClientClaims") - .HasColumnType("tinyint(1)"); - - b.Property("AuthorizationCodeLifetime") - .HasColumnType("int"); - - b.Property("BackChannelLogoutSessionRequired") - .HasColumnType("tinyint(1)"); - - b.Property("BackChannelLogoutUri") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("CibaLifetime") - .HasColumnType("int"); - - b.Property("ClientClaimsPrefix") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ClientName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ClientUri") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("ConsentLifetime") - .HasColumnType("int"); - - b.Property("CoordinateLifetimeWithUserSession") - .HasColumnType("tinyint(1)"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("DPoPClockSkew") - .HasColumnType("time(6)"); - - b.Property("DPoPValidationMode") - .HasColumnType("int"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("DeviceCodeLifetime") - .HasColumnType("int"); - - b.Property("EnableLocalLogin") - .HasColumnType("tinyint(1)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("FrontChannelLogoutSessionRequired") - .HasColumnType("tinyint(1)"); - - b.Property("FrontChannelLogoutUri") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("IdentityTokenLifetime") - .HasColumnType("int"); - - b.Property("IncludeJwtId") - .HasColumnType("tinyint(1)"); - - b.Property("InitiateLoginUri") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("LastAccessed") - .HasColumnType("datetime(6)"); - - b.Property("LogoUri") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("NonEditable") - .HasColumnType("tinyint(1)"); - - b.Property("PairWiseSubjectSalt") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("PollingInterval") - .HasColumnType("int"); - - b.Property("ProtocolType") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("PushedAuthorizationLifetime") - .HasColumnType("int"); - - b.Property("RefreshTokenExpiration") - .HasColumnType("int"); - - b.Property("RefreshTokenUsage") - .HasColumnType("int"); - - b.Property("RequireClientSecret") - .HasColumnType("tinyint(1)"); - - b.Property("RequireConsent") - .HasColumnType("tinyint(1)"); - - b.Property("RequireDPoP") - .HasColumnType("tinyint(1)"); - - b.Property("RequirePkce") - .HasColumnType("tinyint(1)"); - - b.Property("RequirePushedAuthorization") - .HasColumnType("tinyint(1)"); - - b.Property("RequireRequestObject") - .HasColumnType("tinyint(1)"); - - b.Property("SlidingRefreshTokenLifetime") - .HasColumnType("int"); - - b.Property("UpdateAccessTokenClaimsOnRefresh") - .HasColumnType("tinyint(1)"); - - b.Property("Updated") - .HasColumnType("datetime(6)"); - - b.Property("UserCodeType") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("UserSsoLifetime") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ClientId") - .IsUnique(); - - b.ToTable("Clients", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Type", "Value") - .IsUnique(); - - b.ToTable("ClientClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Origin") - .IsRequired() - .HasMaxLength(150) - .HasColumnType("varchar(150)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Origin") - .IsUnique(); - - b.ToTable("ClientCorsOrigins", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("GrantType") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "GrantType") - .IsUnique(); - - b.ToTable("ClientGrantTypes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Provider") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Provider") - .IsUnique(); - - b.ToTable("ClientIdPRestrictions", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("PostLogoutRedirectUri") - .IsRequired() - .HasMaxLength(400) - .HasColumnType("varchar(400)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "PostLogoutRedirectUri") - .IsUnique(); - - b.ToTable("ClientPostLogoutRedirectUris", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Key") - .IsUnique(); - - b.ToTable("ClientProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("RedirectUri") - .IsRequired() - .HasMaxLength(400) - .HasColumnType("varchar(400)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "RedirectUri") - .IsUnique(); - - b.ToTable("ClientRedirectUris", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Scope") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Scope") - .IsUnique(); - - b.ToTable("ClientScopes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("Expiration") - .HasColumnType("datetime(6)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(4000) - .HasColumnType("varchar(4000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientSecrets", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityProvider", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("LastAccessed") - .HasColumnType("datetime(6)"); - - b.Property("NonEditable") - .HasColumnType("tinyint(1)"); - - b.Property("Properties") - .HasColumnType("longtext"); - - b.Property("Scheme") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("varchar(20)"); - - b.Property("Updated") - .HasColumnType("datetime(6)"); - - b.HasKey("Id"); - - b.HasIndex("Scheme") - .IsUnique(); - - b.ToTable("IdentityProviders", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Emphasize") - .HasColumnType("tinyint(1)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("NonEditable") - .HasColumnType("tinyint(1)"); - - b.Property("Required") - .HasColumnType("tinyint(1)"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("tinyint(1)"); - - b.Property("Updated") - .HasColumnType("datetime(6)"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("IdentityResources", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("IdentityResourceId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId", "Type") - .IsUnique(); - - b.ToTable("IdentityResourceClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("IdentityResourceId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId", "Key") - .IsUnique(); - - b.ToTable("IdentityResourceProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Properties") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Scopes") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Secrets") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") - .WithMany("UserClaims") - .HasForeignKey("ScopeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Scope"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") - .WithMany("Properties") - .HasForeignKey("ScopeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Scope"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("Claims") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedCorsOrigins") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedGrantTypes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("IdentityProviderRestrictions") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("PostLogoutRedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("Properties") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("RedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedScopes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("ClientSecrets") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("UserClaims") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("IdentityResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("Properties") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("IdentityResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => - { - b.Navigation("Properties"); - - b.Navigation("Scopes"); - - b.Navigation("Secrets"); - - b.Navigation("UserClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => - { - b.Navigation("Properties"); - - b.Navigation("UserClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => - { - b.Navigation("AllowedCorsOrigins"); - - b.Navigation("AllowedGrantTypes"); - - b.Navigation("AllowedScopes"); - - b.Navigation("Claims"); - - b.Navigation("ClientSecrets"); - - b.Navigation("IdentityProviderRestrictions"); - - b.Navigation("PostLogoutRedirectUris"); - - b.Navigation("Properties"); - - b.Navigation("RedirectUris"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => - { - b.Navigation("Properties"); - - b.Navigation("UserClaims"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/ConfigurationDb/20240325172125_net8upgrade.cs b/archive/SecurityService.MySqlMigrations/ConfigurationDb/20240325172125_net8upgrade.cs deleted file mode 100644 index 346aad08..00000000 --- a/archive/SecurityService.MySqlMigrations/ConfigurationDb/20240325172125_net8upgrade.cs +++ /dev/null @@ -1,482 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace SecurityService.MySqlMigrations.ConfigurationDb -{ - /// - public partial class net8upgrade : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "Id", - table: "IdentityResources", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "IdentityResourceProperties", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "IdentityResourceClaims", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "IdentityProviders", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ClientSecrets", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ClientScopes", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "Clients", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AddColumn( - name: "DPoPClockSkew", - table: "Clients", - type: "time(6)", - nullable: false, - defaultValue: new TimeSpan(0, 0, 0, 0, 0)); - - migrationBuilder.AddColumn( - name: "DPoPValidationMode", - table: "Clients", - type: "int", - nullable: false, - defaultValue: 0); - - migrationBuilder.AddColumn( - name: "InitiateLoginUri", - table: "Clients", - type: "varchar(2000)", - maxLength: 2000, - nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AddColumn( - name: "PushedAuthorizationLifetime", - table: "Clients", - type: "int", - nullable: true); - - migrationBuilder.AddColumn( - name: "RequireDPoP", - table: "Clients", - type: "tinyint(1)", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "RequirePushedAuthorization", - table: "Clients", - type: "tinyint(1)", - nullable: false, - defaultValue: false); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ClientRedirectUris", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ClientProperties", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ClientPostLogoutRedirectUris", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ClientIdPRestrictions", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ClientGrantTypes", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ClientCorsOrigins", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ClientClaims", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ApiScopes", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ApiScopeProperties", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ApiScopeClaims", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ApiResourceSecrets", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ApiResourceScopes", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ApiResources", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ApiResourceProperties", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ApiResourceClaims", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "DPoPClockSkew", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "DPoPValidationMode", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "InitiateLoginUri", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "PushedAuthorizationLifetime", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "RequireDPoP", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "RequirePushedAuthorization", - table: "Clients"); - - migrationBuilder.AlterColumn( - name: "Id", - table: "IdentityResources", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "IdentityResourceProperties", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "IdentityResourceClaims", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "IdentityProviders", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ClientSecrets", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ClientScopes", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "Clients", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ClientRedirectUris", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ClientProperties", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ClientPostLogoutRedirectUris", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ClientIdPRestrictions", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ClientGrantTypes", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ClientCorsOrigins", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ClientClaims", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ApiScopes", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ApiScopeProperties", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ApiScopeClaims", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ApiResourceSecrets", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ApiResourceScopes", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ApiResources", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ApiResourceProperties", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ApiResourceClaims", - type: "int", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs b/archive/SecurityService.MySqlMigrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs deleted file mode 100644 index 8c2d90fb..00000000 --- a/archive/SecurityService.MySqlMigrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs +++ /dev/null @@ -1,1113 +0,0 @@ -// -using System; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace SecurityService.MySqlMigrations.ConfigurationDb -{ - [DbContext(typeof(ConfigurationDbContext))] - partial class ConfigurationDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("AllowedAccessTokenSigningAlgorithms") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("LastAccessed") - .HasColumnType("datetime(6)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("NonEditable") - .HasColumnType("tinyint(1)"); - - b.Property("RequireResourceIndicator") - .HasColumnType("tinyint(1)"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("tinyint(1)"); - - b.Property("Updated") - .HasColumnType("datetime(6)"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiResources", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId", "Type") - .IsUnique(); - - b.ToTable("ApiResourceClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId", "Key") - .IsUnique(); - - b.ToTable("ApiResourceProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Scope") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId", "Scope") - .IsUnique(); - - b.ToTable("ApiResourceScopes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("Expiration") - .HasColumnType("datetime(6)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(4000) - .HasColumnType("varchar(4000)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiResourceSecrets", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Emphasize") - .HasColumnType("tinyint(1)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("LastAccessed") - .HasColumnType("datetime(6)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("NonEditable") - .HasColumnType("tinyint(1)"); - - b.Property("Required") - .HasColumnType("tinyint(1)"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("tinyint(1)"); - - b.Property("Updated") - .HasColumnType("datetime(6)"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiScopes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ScopeId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ScopeId", "Type") - .IsUnique(); - - b.ToTable("ApiScopeClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("ScopeId") - .HasColumnType("int"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ScopeId", "Key") - .IsUnique(); - - b.ToTable("ApiScopeProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("AbsoluteRefreshTokenLifetime") - .HasColumnType("int"); - - b.Property("AccessTokenLifetime") - .HasColumnType("int"); - - b.Property("AccessTokenType") - .HasColumnType("int"); - - b.Property("AllowAccessTokensViaBrowser") - .HasColumnType("tinyint(1)"); - - b.Property("AllowOfflineAccess") - .HasColumnType("tinyint(1)"); - - b.Property("AllowPlainTextPkce") - .HasColumnType("tinyint(1)"); - - b.Property("AllowRememberConsent") - .HasColumnType("tinyint(1)"); - - b.Property("AllowedIdentityTokenSigningAlgorithms") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("AlwaysIncludeUserClaimsInIdToken") - .HasColumnType("tinyint(1)"); - - b.Property("AlwaysSendClientClaims") - .HasColumnType("tinyint(1)"); - - b.Property("AuthorizationCodeLifetime") - .HasColumnType("int"); - - b.Property("BackChannelLogoutSessionRequired") - .HasColumnType("tinyint(1)"); - - b.Property("BackChannelLogoutUri") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("CibaLifetime") - .HasColumnType("int"); - - b.Property("ClientClaimsPrefix") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ClientName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ClientUri") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("ConsentLifetime") - .HasColumnType("int"); - - b.Property("CoordinateLifetimeWithUserSession") - .HasColumnType("tinyint(1)"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("DPoPClockSkew") - .HasColumnType("time(6)"); - - b.Property("DPoPValidationMode") - .HasColumnType("int"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("DeviceCodeLifetime") - .HasColumnType("int"); - - b.Property("EnableLocalLogin") - .HasColumnType("tinyint(1)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("FrontChannelLogoutSessionRequired") - .HasColumnType("tinyint(1)"); - - b.Property("FrontChannelLogoutUri") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("IdentityTokenLifetime") - .HasColumnType("int"); - - b.Property("IncludeJwtId") - .HasColumnType("tinyint(1)"); - - b.Property("InitiateLoginUri") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("LastAccessed") - .HasColumnType("datetime(6)"); - - b.Property("LogoUri") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("NonEditable") - .HasColumnType("tinyint(1)"); - - b.Property("PairWiseSubjectSalt") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("PollingInterval") - .HasColumnType("int"); - - b.Property("ProtocolType") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("PushedAuthorizationLifetime") - .HasColumnType("int"); - - b.Property("RefreshTokenExpiration") - .HasColumnType("int"); - - b.Property("RefreshTokenUsage") - .HasColumnType("int"); - - b.Property("RequireClientSecret") - .HasColumnType("tinyint(1)"); - - b.Property("RequireConsent") - .HasColumnType("tinyint(1)"); - - b.Property("RequireDPoP") - .HasColumnType("tinyint(1)"); - - b.Property("RequirePkce") - .HasColumnType("tinyint(1)"); - - b.Property("RequirePushedAuthorization") - .HasColumnType("tinyint(1)"); - - b.Property("RequireRequestObject") - .HasColumnType("tinyint(1)"); - - b.Property("SlidingRefreshTokenLifetime") - .HasColumnType("int"); - - b.Property("UpdateAccessTokenClaimsOnRefresh") - .HasColumnType("tinyint(1)"); - - b.Property("Updated") - .HasColumnType("datetime(6)"); - - b.Property("UserCodeType") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("UserSsoLifetime") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ClientId") - .IsUnique(); - - b.ToTable("Clients", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Type", "Value") - .IsUnique(); - - b.ToTable("ClientClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Origin") - .IsRequired() - .HasMaxLength(150) - .HasColumnType("varchar(150)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Origin") - .IsUnique(); - - b.ToTable("ClientCorsOrigins", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("GrantType") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "GrantType") - .IsUnique(); - - b.ToTable("ClientGrantTypes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Provider") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Provider") - .IsUnique(); - - b.ToTable("ClientIdPRestrictions", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("PostLogoutRedirectUri") - .IsRequired() - .HasMaxLength(400) - .HasColumnType("varchar(400)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "PostLogoutRedirectUri") - .IsUnique(); - - b.ToTable("ClientPostLogoutRedirectUris", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Key") - .IsUnique(); - - b.ToTable("ClientProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("RedirectUri") - .IsRequired() - .HasMaxLength(400) - .HasColumnType("varchar(400)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "RedirectUri") - .IsUnique(); - - b.ToTable("ClientRedirectUris", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Scope") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Scope") - .IsUnique(); - - b.ToTable("ClientScopes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.Property("Expiration") - .HasColumnType("datetime(6)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(4000) - .HasColumnType("varchar(4000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientSecrets", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityProvider", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("LastAccessed") - .HasColumnType("datetime(6)"); - - b.Property("NonEditable") - .HasColumnType("tinyint(1)"); - - b.Property("Properties") - .HasColumnType("longtext"); - - b.Property("Scheme") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("varchar(20)"); - - b.Property("Updated") - .HasColumnType("datetime(6)"); - - b.HasKey("Id"); - - b.HasIndex("Scheme") - .IsUnique(); - - b.ToTable("IdentityProviders", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("varchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Emphasize") - .HasColumnType("tinyint(1)"); - - b.Property("Enabled") - .HasColumnType("tinyint(1)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("NonEditable") - .HasColumnType("tinyint(1)"); - - b.Property("Required") - .HasColumnType("tinyint(1)"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("tinyint(1)"); - - b.Property("Updated") - .HasColumnType("datetime(6)"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("IdentityResources", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("IdentityResourceId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId", "Type") - .IsUnique(); - - b.ToTable("IdentityResourceClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("IdentityResourceId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("varchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("varchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId", "Key") - .IsUnique(); - - b.ToTable("IdentityResourceProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Properties") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Scopes") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Secrets") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") - .WithMany("UserClaims") - .HasForeignKey("ScopeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Scope"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") - .WithMany("Properties") - .HasForeignKey("ScopeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Scope"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("Claims") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedCorsOrigins") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedGrantTypes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("IdentityProviderRestrictions") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("PostLogoutRedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("Properties") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("RedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedScopes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("ClientSecrets") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("UserClaims") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("IdentityResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("Properties") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("IdentityResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => - { - b.Navigation("Properties"); - - b.Navigation("Scopes"); - - b.Navigation("Secrets"); - - b.Navigation("UserClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => - { - b.Navigation("Properties"); - - b.Navigation("UserClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => - { - b.Navigation("AllowedCorsOrigins"); - - b.Navigation("AllowedGrantTypes"); - - b.Navigation("AllowedScopes"); - - b.Navigation("Claims"); - - b.Navigation("ClientSecrets"); - - b.Navigation("IdentityProviderRestrictions"); - - b.Navigation("PostLogoutRedirectUris"); - - b.Navigation("Properties"); - - b.Navigation("RedirectUris"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => - { - b.Navigation("Properties"); - - b.Navigation("UserClaims"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/PersistedGrantDb/20211201220148_InitialCreate.Designer.cs b/archive/SecurityService.MySqlMigrations/PersistedGrantDb/20211201220148_InitialCreate.Designer.cs deleted file mode 100644 index 9f2c56cb..00000000 --- a/archive/SecurityService.MySqlMigrations/PersistedGrantDb/20211201220148_InitialCreate.Designer.cs +++ /dev/null @@ -1,165 +0,0 @@ -// -using System; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace SecurityService.MySqlMigrations.PersistedGrantDb -{ - [DbContext(typeof(PersistedGrantDbContext))] - [Migration("20211201220148_InitialCreate")] - partial class InitialCreate - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("Relational:MaxIdentifierLength", 64) - .HasAnnotation("ProductVersion", "5.0.12"); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("CreationTime") - .HasColumnType("datetime(6)"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("longtext"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("DeviceCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("datetime(6)"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => - { - b.Property("Id") - .HasColumnType("varchar(255)"); - - b.Property("Algorithm") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Data") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("DataProtected") - .HasColumnType("tinyint(1)"); - - b.Property("IsX509Certificate") - .HasColumnType("tinyint(1)"); - - b.Property("Use") - .HasColumnType("varchar(255)"); - - b.Property("Version") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("Use"); - - b.ToTable("Keys"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ConsumedTime") - .HasColumnType("datetime(6)"); - - b.Property("CreationTime") - .HasColumnType("datetime(6)"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("longtext"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Expiration") - .HasColumnType("datetime(6)"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("varchar(50)"); - - b.HasKey("Key"); - - b.HasIndex("ConsumedTime"); - - b.HasIndex("Expiration"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.HasIndex("SubjectId", "SessionId", "Type"); - - b.ToTable("PersistedGrants"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/PersistedGrantDb/20211201220148_InitialCreate.cs b/archive/SecurityService.MySqlMigrations/PersistedGrantDb/20211201220148_InitialCreate.cs deleted file mode 100644 index 57b976ed..00000000 --- a/archive/SecurityService.MySqlMigrations/PersistedGrantDb/20211201220148_InitialCreate.cs +++ /dev/null @@ -1,140 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace SecurityService.MySqlMigrations.PersistedGrantDb -{ - public partial class InitialCreate : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterDatabase() - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "DeviceCodes", - columns: table => new - { - UserCode = table.Column(type: "varchar(200)", maxLength: 200, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - DeviceCode = table.Column(type: "varchar(200)", maxLength: 200, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - SubjectId = table.Column(type: "varchar(200)", maxLength: 200, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - SessionId = table.Column(type: "varchar(100)", maxLength: 100, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - ClientId = table.Column(type: "varchar(200)", maxLength: 200, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Description = table.Column(type: "varchar(200)", maxLength: 200, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - CreationTime = table.Column(type: "datetime(6)", nullable: false), - Expiration = table.Column(type: "datetime(6)", nullable: false), - Data = table.Column(type: "longtext", maxLength: 50000, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_DeviceCodes", x => x.UserCode); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "Keys", - columns: table => new - { - Id = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Version = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime(6)", nullable: false), - Use = table.Column(type: "varchar(255)", nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Algorithm = table.Column(type: "varchar(100)", maxLength: 100, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - IsX509Certificate = table.Column(type: "tinyint(1)", nullable: false), - DataProtected = table.Column(type: "tinyint(1)", nullable: false), - Data = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_Keys", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "PersistedGrants", - columns: table => new - { - Key = table.Column(type: "varchar(200)", maxLength: 200, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Type = table.Column(type: "varchar(50)", maxLength: 50, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - SubjectId = table.Column(type: "varchar(200)", maxLength: 200, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - SessionId = table.Column(type: "varchar(100)", maxLength: 100, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - ClientId = table.Column(type: "varchar(200)", maxLength: 200, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Description = table.Column(type: "varchar(200)", maxLength: 200, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - CreationTime = table.Column(type: "datetime(6)", nullable: false), - Expiration = table.Column(type: "datetime(6)", nullable: true), - ConsumedTime = table.Column(type: "datetime(6)", nullable: true), - Data = table.Column(type: "longtext", maxLength: 50000, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_PersistedGrants", x => x.Key); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateIndex( - name: "IX_DeviceCodes_DeviceCode", - table: "DeviceCodes", - column: "DeviceCode", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_DeviceCodes_Expiration", - table: "DeviceCodes", - column: "Expiration"); - - migrationBuilder.CreateIndex( - name: "IX_Keys_Use", - table: "Keys", - column: "Use"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_ConsumedTime", - table: "PersistedGrants", - column: "ConsumedTime"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_Expiration", - table: "PersistedGrants", - column: "Expiration"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_SubjectId_ClientId_Type", - table: "PersistedGrants", - columns: new[] { "SubjectId", "ClientId", "Type" }); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_SubjectId_SessionId_Type", - table: "PersistedGrants", - columns: new[] { "SubjectId", "SessionId", "Type" }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "DeviceCodes"); - - migrationBuilder.DropTable( - name: "Keys"); - - migrationBuilder.DropTable( - name: "PersistedGrants"); - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/PersistedGrantDb/20220609181938_Net6Update.Designer.cs b/archive/SecurityService.MySqlMigrations/PersistedGrantDb/20220609181938_Net6Update.Designer.cs deleted file mode 100644 index 689e1371..00000000 --- a/archive/SecurityService.MySqlMigrations/PersistedGrantDb/20220609181938_Net6Update.Designer.cs +++ /dev/null @@ -1,232 +0,0 @@ -// -using System; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace SecurityService.MySqlMigrations.PersistedGrantDb -{ - [DbContext(typeof(PersistedGrantDbContext))] - [Migration("20220609181938_Net6Update")] - partial class Net6Update - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "6.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("CreationTime") - .HasColumnType("datetime(6)"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("longtext"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("DeviceCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("datetime(6)"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => - { - b.Property("Id") - .HasColumnType("varchar(255)"); - - b.Property("Algorithm") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Data") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("DataProtected") - .HasColumnType("tinyint(1)"); - - b.Property("IsX509Certificate") - .HasColumnType("tinyint(1)"); - - b.Property("Use") - .HasColumnType("varchar(255)"); - - b.Property("Version") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("Use"); - - b.ToTable("Keys", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ConsumedTime") - .HasColumnType("datetime(6)"); - - b.Property("CreationTime") - .HasColumnType("datetime(6)"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("longtext"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Expiration") - .HasColumnType("datetime(6)"); - - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("varchar(50)"); - - b.HasKey("Id"); - - b.HasIndex("ConsumedTime"); - - b.HasIndex("Expiration"); - - b.HasIndex("Key") - .IsUnique(); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.HasIndex("SubjectId", "SessionId", "Type"); - - b.ToTable("PersistedGrants", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ServerSideSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Data") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("DisplayName") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("Expires") - .HasColumnType("datetime(6)"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("Renewed") - .HasColumnType("datetime(6)"); - - b.Property("Scheme") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("SubjectId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.HasKey("Id"); - - b.HasIndex("DisplayName"); - - b.HasIndex("Expires"); - - b.HasIndex("Key") - .IsUnique(); - - b.HasIndex("SessionId"); - - b.HasIndex("SubjectId"); - - b.ToTable("ServerSideSessions", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/PersistedGrantDb/20220609181938_Net6Update.cs b/archive/SecurityService.MySqlMigrations/PersistedGrantDb/20220609181938_Net6Update.cs deleted file mode 100644 index e5256a32..00000000 --- a/archive/SecurityService.MySqlMigrations/PersistedGrantDb/20220609181938_Net6Update.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace SecurityService.MySqlMigrations.PersistedGrantDb -{ - public partial class Net6Update : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - name: "PK_PersistedGrants", - table: "PersistedGrants"); - - migrationBuilder.AlterColumn( - name: "Key", - table: "PersistedGrants", - type: "varchar(200)", - maxLength: 200, - nullable: true, - oldClrType: typeof(string), - oldType: "varchar(200)", - oldMaxLength: 200) - .Annotation("MySql:CharSet", "utf8mb4") - .OldAnnotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AddColumn( - name: "Id", - table: "PersistedGrants", - type: "bigint", - nullable: false, - defaultValue: 0L) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AddPrimaryKey( - name: "PK_PersistedGrants", - table: "PersistedGrants", - column: "Id"); - - migrationBuilder.CreateTable( - name: "ServerSideSessions", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - Key = table.Column(type: "varchar(100)", maxLength: 100, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Scheme = table.Column(type: "varchar(100)", maxLength: 100, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - SubjectId = table.Column(type: "varchar(100)", maxLength: 100, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - SessionId = table.Column(type: "varchar(100)", maxLength: 100, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - DisplayName = table.Column(type: "varchar(100)", maxLength: 100, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Created = table.Column(type: "datetime(6)", nullable: false), - Renewed = table.Column(type: "datetime(6)", nullable: false), - Expires = table.Column(type: "datetime(6)", nullable: true), - Data = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_ServerSideSessions", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_Key", - table: "PersistedGrants", - column: "Key", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ServerSideSessions_DisplayName", - table: "ServerSideSessions", - column: "DisplayName"); - - migrationBuilder.CreateIndex( - name: "IX_ServerSideSessions_Expires", - table: "ServerSideSessions", - column: "Expires"); - - migrationBuilder.CreateIndex( - name: "IX_ServerSideSessions_Key", - table: "ServerSideSessions", - column: "Key", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ServerSideSessions_SessionId", - table: "ServerSideSessions", - column: "SessionId"); - - migrationBuilder.CreateIndex( - name: "IX_ServerSideSessions_SubjectId", - table: "ServerSideSessions", - column: "SubjectId"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "ServerSideSessions"); - - migrationBuilder.DropPrimaryKey( - name: "PK_PersistedGrants", - table: "PersistedGrants"); - - migrationBuilder.DropIndex( - name: "IX_PersistedGrants_Key", - table: "PersistedGrants"); - - migrationBuilder.DropColumn( - name: "Id", - table: "PersistedGrants"); - - migrationBuilder.UpdateData( - table: "PersistedGrants", - keyColumn: "Key", - keyValue: null, - column: "Key", - value: ""); - - migrationBuilder.AlterColumn( - name: "Key", - table: "PersistedGrants", - type: "varchar(200)", - maxLength: 200, - nullable: false, - oldClrType: typeof(string), - oldType: "varchar(200)", - oldMaxLength: 200, - oldNullable: true) - .Annotation("MySql:CharSet", "utf8mb4") - .OldAnnotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AddPrimaryKey( - name: "PK_PersistedGrants", - table: "PersistedGrants", - column: "Key"); - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/PersistedGrantDb/20240325172134_net8upgrade.Designer.cs b/archive/SecurityService.MySqlMigrations/PersistedGrantDb/20240325172134_net8upgrade.Designer.cs deleted file mode 100644 index 994b0d65..00000000 --- a/archive/SecurityService.MySqlMigrations/PersistedGrantDb/20240325172134_net8upgrade.Designer.cs +++ /dev/null @@ -1,270 +0,0 @@ -// -using System; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace SecurityService.MySqlMigrations.PersistedGrantDb -{ - [DbContext(typeof(PersistedGrantDbContext))] - [Migration("20240325172134_net8upgrade")] - partial class net8upgrade - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("CreationTime") - .HasColumnType("datetime(6)"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("longtext"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("DeviceCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("datetime(6)"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => - { - b.Property("Id") - .HasColumnType("varchar(255)"); - - b.Property("Algorithm") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Data") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("DataProtected") - .HasColumnType("tinyint(1)"); - - b.Property("IsX509Certificate") - .HasColumnType("tinyint(1)"); - - b.Property("Use") - .HasColumnType("varchar(255)"); - - b.Property("Version") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("Use"); - - b.ToTable("Keys", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ConsumedTime") - .HasColumnType("datetime(6)"); - - b.Property("CreationTime") - .HasColumnType("datetime(6)"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("longtext"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Expiration") - .HasColumnType("datetime(6)"); - - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("varchar(50)"); - - b.HasKey("Id"); - - b.HasIndex("ConsumedTime"); - - b.HasIndex("Expiration"); - - b.HasIndex("Key") - .IsUnique(); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.HasIndex("SubjectId", "SessionId", "Type"); - - b.ToTable("PersistedGrants", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PushedAuthorizationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ExpiresAtUtc") - .HasColumnType("datetime(6)"); - - b.Property("Parameters") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ReferenceValueHash") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("varchar(64)"); - - b.HasKey("Id"); - - b.HasIndex("ExpiresAtUtc"); - - b.HasIndex("ReferenceValueHash") - .IsUnique(); - - b.ToTable("PushedAuthorizationRequests", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ServerSideSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Data") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("DisplayName") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("Expires") - .HasColumnType("datetime(6)"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("Renewed") - .HasColumnType("datetime(6)"); - - b.Property("Scheme") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("SubjectId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.HasKey("Id"); - - b.HasIndex("DisplayName"); - - b.HasIndex("Expires"); - - b.HasIndex("Key") - .IsUnique(); - - b.HasIndex("SessionId"); - - b.HasIndex("SubjectId"); - - b.ToTable("ServerSideSessions", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/PersistedGrantDb/20240325172134_net8upgrade.cs b/archive/SecurityService.MySqlMigrations/PersistedGrantDb/20240325172134_net8upgrade.cs deleted file mode 100644 index 48f9a9b3..00000000 --- a/archive/SecurityService.MySqlMigrations/PersistedGrantDb/20240325172134_net8upgrade.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace SecurityService.MySqlMigrations.PersistedGrantDb -{ - /// - public partial class net8upgrade : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey("PK_ServerSideSessions", "ServerSideSessions"); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ServerSideSessions", - type: "bigint", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AddPrimaryKey("PK_ServerSideSessions", "ServerSideSessions", "Id"); - - migrationBuilder.AlterColumn( - name: "Id", - table: "PersistedGrants", - type: "bigint", - nullable: false, - oldClrType: typeof(long), - oldType: "bigint") - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.CreateTable( - name: "PushedAuthorizationRequests", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - ReferenceValueHash = table.Column(type: "varchar(64)", maxLength: 64, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ExpiresAtUtc = table.Column(type: "datetime(6)", nullable: false), - Parameters = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_PushedAuthorizationRequests", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateIndex( - name: "IX_PushedAuthorizationRequests_ExpiresAtUtc", - table: "PushedAuthorizationRequests", - column: "ExpiresAtUtc"); - - migrationBuilder.CreateIndex( - name: "IX_PushedAuthorizationRequests_ReferenceValueHash", - table: "PushedAuthorizationRequests", - column: "ReferenceValueHash", - unique: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "PushedAuthorizationRequests"); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ServerSideSessions", - type: "int", - nullable: false, - oldClrType: typeof(long), - oldType: "bigint") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - - migrationBuilder.AlterColumn( - name: "Id", - table: "PersistedGrants", - type: "bigint", - nullable: false, - oldClrType: typeof(long), - oldType: "bigint") - .OldAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn); - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/PersistedGrantDb/PersistedGrantDbContextModelSnapshot.cs b/archive/SecurityService.MySqlMigrations/PersistedGrantDb/PersistedGrantDbContextModelSnapshot.cs deleted file mode 100644 index 901f4784..00000000 --- a/archive/SecurityService.MySqlMigrations/PersistedGrantDb/PersistedGrantDbContextModelSnapshot.cs +++ /dev/null @@ -1,267 +0,0 @@ -// -using System; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace SecurityService.MySqlMigrations.PersistedGrantDb -{ - [DbContext(typeof(PersistedGrantDbContext))] - partial class PersistedGrantDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("CreationTime") - .HasColumnType("datetime(6)"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("longtext"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("DeviceCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("datetime(6)"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => - { - b.Property("Id") - .HasColumnType("varchar(255)"); - - b.Property("Algorithm") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Data") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("DataProtected") - .HasColumnType("tinyint(1)"); - - b.Property("IsX509Certificate") - .HasColumnType("tinyint(1)"); - - b.Property("Use") - .HasColumnType("varchar(255)"); - - b.Property("Version") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("Use"); - - b.ToTable("Keys", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("ConsumedTime") - .HasColumnType("datetime(6)"); - - b.Property("CreationTime") - .HasColumnType("datetime(6)"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("longtext"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Expiration") - .HasColumnType("datetime(6)"); - - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("varchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("varchar(50)"); - - b.HasKey("Id"); - - b.HasIndex("ConsumedTime"); - - b.HasIndex("Expiration"); - - b.HasIndex("Key") - .IsUnique(); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.HasIndex("SubjectId", "SessionId", "Type"); - - b.ToTable("PersistedGrants", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PushedAuthorizationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ExpiresAtUtc") - .HasColumnType("datetime(6)"); - - b.Property("Parameters") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ReferenceValueHash") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("varchar(64)"); - - b.HasKey("Id"); - - b.HasIndex("ExpiresAtUtc"); - - b.HasIndex("ReferenceValueHash") - .IsUnique(); - - b.ToTable("PushedAuthorizationRequests", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ServerSideSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime(6)"); - - b.Property("Data") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("DisplayName") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("Expires") - .HasColumnType("datetime(6)"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("Renewed") - .HasColumnType("datetime(6)"); - - b.Property("Scheme") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.Property("SubjectId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("varchar(100)"); - - b.HasKey("Id"); - - b.HasIndex("DisplayName"); - - b.HasIndex("Expires"); - - b.HasIndex("Key") - .IsUnique(); - - b.HasIndex("SessionId"); - - b.HasIndex("SubjectId"); - - b.ToTable("ServerSideSessions", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.MySqlMigrations/SecurityService.MySqlMigrations.csproj b/archive/SecurityService.MySqlMigrations/SecurityService.MySqlMigrations.csproj deleted file mode 100644 index 36d4c4e7..00000000 --- a/archive/SecurityService.MySqlMigrations/SecurityService.MySqlMigrations.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - net9.0 - None - - - - - - - - - - - - - diff --git a/archive/SecurityService.OpenIdConnect.IntegrationTests/AssemblyInfo.cs b/archive/SecurityService.OpenIdConnect.IntegrationTests/AssemblyInfo.cs deleted file mode 100644 index f52f64d8..00000000 --- a/archive/SecurityService.OpenIdConnect.IntegrationTests/AssemblyInfo.cs +++ /dev/null @@ -1,20 +0,0 @@ -using NUnit.Framework; -using System.Runtime.InteropServices; - -// In SDK-style projects such as this one, several assembly attributes that were historically -// defined in this file are now automatically added during build and populated with -// values defined in project properties. For details of which attributes are included -// and how to customise this process see: https://aka.ms/assembly-info-properties - - -// Setting ComVisible to false makes the types in this assembly not visible to COM -// components. If you need to access a type in this assembly from COM, set the ComVisible -// attribute to true on that type. - -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM. - -[assembly: Guid("70c8d747-842f-4d4d-8c60-f7c46bf81088")] -[assembly: LevelOfParallelism(1)] -[assembly: Parallelizable(ParallelScope.Fixtures)] diff --git a/archive/SecurityService.OpenIdConnect.IntegrationTests/ChangePassword/ChangePassword.feature b/archive/SecurityService.OpenIdConnect.IntegrationTests/ChangePassword/ChangePassword.feature deleted file mode 100644 index 77f8bdce..00000000 --- a/archive/SecurityService.OpenIdConnect.IntegrationTests/ChangePassword/ChangePassword.feature +++ /dev/null @@ -1,45 +0,0 @@ -@base @shared @userlogin @changepassword -Feature: Change Password - -Background: - - Given I create the following roles - | Role Name | - | Estate | - - Given I create the following api resources - | Name | DisplayName | Secret | Scopes | UserClaims | - | transactionProcessor | Transaction Processor REST | Secret1 | transactionProcessor | MerchantId,EstateId,role | - - Given I create the following identity resources - | Name | DisplayName | Description | UserClaims | - | openid | Your user identifier | | sub | - | profile | User profile | Your user profile information (first name, last name, etc.) | name,role,email,given_name,middle_name,family_name,EstateId,MerchantId | - | email | Email | Email and Email Verified Flags | email_verified,email | - - Given I create the following clients - | ClientId | Name | Secret | Scopes | GrantTypes | RedirectUris | PostLogoutRedirectUris | RequireConsent | AllowOfflineAccess | ClientUri | - | estateUIClient | Merchant Client | Secret1 | transactionProcessor,openid,email,profile | hybrid | https://[url]:[port]/signin-oidc | https://[url]:[port]/signout-oidc | false | true | https://[url]:[port] | - - -@PRTest -Scenario: Change Passwword - Given I create the following users - | Email Address | Phone Number | Given Name | Middle Name | Family Name | Claims | Roles | Password | - | estateuser@testestate1.co.uk | 123456789 | Test | | User 1 | EstateId:1 | Estate | 123456 | - Then I get an email with a confirm email address link - When I navigate to the confirm email address - Then I am presented with the confirm email address successful screen - And I get a welcome email with my login details - Given I am on the application home page - When I click the 'Privacy' link - Then I am presented with a login screen - When I login with the username 'estateuser@testestate1.co.uk' and the provided password - Then I am presented with the privacy screen - When I click the 'ChangePassword' link - Then I am presented with a change password screen - When I enter my old password - When I enter my new password 'Pa55word!' - And I confirm my new password 'Pa55word!' - And I click the change password button - Then I am returned to the application home page \ No newline at end of file diff --git a/archive/SecurityService.OpenIdConnect.IntegrationTests/ChangePassword/ChangePassword.feature.cs b/archive/SecurityService.OpenIdConnect.IntegrationTests/ChangePassword/ChangePassword.feature.cs deleted file mode 100644 index 1e172814..00000000 --- a/archive/SecurityService.OpenIdConnect.IntegrationTests/ChangePassword/ChangePassword.feature.cs +++ /dev/null @@ -1,296 +0,0 @@ -// ------------------------------------------------------------------------------ -// -// This code was generated by Reqnroll (https://reqnroll.net/). -// Reqnroll Version:3.0.0.0 -// Reqnroll Generator Version:3.0.0.0 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -// ------------------------------------------------------------------------------ -#region Designer generated code -#pragma warning disable -using Reqnroll; -namespace SecurityService.OpenIdConnect.IntegrationTests.ChangePassword -{ - - - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Reqnroll", "3.0.0.0")] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::NUnit.Framework.TestFixtureAttribute()] - [global::NUnit.Framework.DescriptionAttribute("Change Password")] - [global::NUnit.Framework.FixtureLifeCycleAttribute(global::NUnit.Framework.LifeCycle.InstancePerTestCase)] - [global::NUnit.Framework.CategoryAttribute("base")] - [global::NUnit.Framework.CategoryAttribute("shared")] - [global::NUnit.Framework.CategoryAttribute("userlogin")] - [global::NUnit.Framework.CategoryAttribute("changepassword")] - public partial class ChangePasswordFeature - { - - private global::Reqnroll.ITestRunner testRunner; - - private static string[] featureTags = new string[] { - "base", - "shared", - "userlogin", - "changepassword"}; - - private static global::Reqnroll.FeatureInfo featureInfo = new global::Reqnroll.FeatureInfo(new global::System.Globalization.CultureInfo("en-US"), "ChangePassword", "Change Password", null, global::Reqnroll.ProgrammingLanguage.CSharp, featureTags, InitializeCucumberMessages()); - -#line 1 "ChangePassword.feature" -#line hidden - - [global::NUnit.Framework.OneTimeSetUpAttribute()] - public static async global::System.Threading.Tasks.Task FeatureSetupAsync() - { - } - - [global::NUnit.Framework.OneTimeTearDownAttribute()] - public static async global::System.Threading.Tasks.Task FeatureTearDownAsync() - { - await global::Reqnroll.TestRunnerManager.ReleaseFeatureAsync(featureInfo); - } - - [global::NUnit.Framework.SetUpAttribute()] - public async global::System.Threading.Tasks.Task TestInitializeAsync() - { - testRunner = global::Reqnroll.TestRunnerManager.GetTestRunnerForAssembly(featureHint: featureInfo); - try - { - if (((testRunner.FeatureContext != null) - && (testRunner.FeatureContext.FeatureInfo.Equals(featureInfo) == false))) - { - await testRunner.OnFeatureEndAsync(); - } - } - finally - { - if (((testRunner.FeatureContext != null) - && testRunner.FeatureContext.BeforeFeatureHookFailed)) - { - throw new global::Reqnroll.ReqnrollException("Scenario skipped because of previous before feature hook error"); - } - if ((testRunner.FeatureContext == null)) - { - await testRunner.OnFeatureStartAsync(featureInfo); - } - } - } - - [global::NUnit.Framework.TearDownAttribute()] - public async global::System.Threading.Tasks.Task TestTearDownAsync() - { - if ((testRunner == null)) - { - return; - } - try - { - await testRunner.OnScenarioEndAsync(); - } - finally - { - global::Reqnroll.TestRunnerManager.ReleaseTestRunner(testRunner); - testRunner = null; - } - } - - public void ScenarioInitialize(global::Reqnroll.ScenarioInfo scenarioInfo, global::Reqnroll.RuleInfo ruleInfo) - { - testRunner.OnScenarioInitialize(scenarioInfo, ruleInfo); - testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(global::NUnit.Framework.TestContext.CurrentContext); - } - - public async global::System.Threading.Tasks.Task ScenarioStartAsync() - { - await testRunner.OnScenarioStartAsync(); - } - - public async global::System.Threading.Tasks.Task ScenarioCleanupAsync() - { - await testRunner.CollectScenarioErrorsAsync(); - } - - public virtual async global::System.Threading.Tasks.Task FeatureBackgroundAsync() - { -#line 4 -#line hidden - global::Reqnroll.Table table1 = new global::Reqnroll.Table(new string[] { - "Role Name"}); - table1.AddRow(new string[] { - "Estate"}); -#line 6 - await testRunner.GivenAsync("I create the following roles", ((string)(null)), table1, "Given "); -#line hidden - global::Reqnroll.Table table2 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Secret", - "Scopes", - "UserClaims"}); - table2.AddRow(new string[] { - "transactionProcessor", - "Transaction Processor REST", - "Secret1", - "transactionProcessor", - "MerchantId,EstateId,role"}); -#line 10 - await testRunner.GivenAsync("I create the following api resources", ((string)(null)), table2, "Given "); -#line hidden - global::Reqnroll.Table table3 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Description", - "UserClaims"}); - table3.AddRow(new string[] { - "openid", - "Your user identifier", - "", - "sub"}); - table3.AddRow(new string[] { - "profile", - "User profile", - "Your user profile information (first name, last name, etc.)", - "name,role,email,given_name,middle_name,family_name,EstateId,MerchantId"}); - table3.AddRow(new string[] { - "email", - "Email", - "Email and Email Verified Flags", - "email_verified,email"}); -#line 14 - await testRunner.GivenAsync("I create the following identity resources", ((string)(null)), table3, "Given "); -#line hidden - global::Reqnroll.Table table4 = new global::Reqnroll.Table(new string[] { - "ClientId", - "Name", - "Secret", - "Scopes", - "GrantTypes", - "RedirectUris", - "PostLogoutRedirectUris", - "RequireConsent", - "AllowOfflineAccess", - "ClientUri"}); - table4.AddRow(new string[] { - "estateUIClient", - "Merchant Client", - "Secret1", - "transactionProcessor,openid,email,profile", - "hybrid", - "https://[url]:[port]/signin-oidc", - "https://[url]:[port]/signout-oidc", - "false", - "true", - "https://[url]:[port]"}); -#line 20 - await testRunner.GivenAsync("I create the following clients", ((string)(null)), table4, "Given "); -#line hidden - } - - private static global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages InitializeCucumberMessages() - { - return new global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages("ChangePassword/ChangePassword.feature.ndjson", 3); - } - - [global::NUnit.Framework.TestAttribute()] - [global::NUnit.Framework.DescriptionAttribute("Change Passwword")] - [global::NUnit.Framework.CategoryAttribute("PRTest")] - public async global::System.Threading.Tasks.Task ChangePasswword() - { - string[] tagsOfScenario = new string[] { - "PRTest"}; - global::System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new global::System.Collections.Specialized.OrderedDictionary(); - string pickleIndex = "0"; - global::Reqnroll.ScenarioInfo scenarioInfo = new global::Reqnroll.ScenarioInfo("Change Passwword", null, tagsOfScenario, argumentsOfScenario, featureTags, pickleIndex); - string[] tagsOfRule = ((string[])(null)); - global::Reqnroll.RuleInfo ruleInfo = null; -#line 26 -this.ScenarioInitialize(scenarioInfo, ruleInfo); -#line hidden - if ((global::Reqnroll.TagHelper.ContainsIgnoreTag(scenarioInfo.CombinedTags) || global::Reqnroll.TagHelper.ContainsIgnoreTag(featureTags))) - { - await testRunner.SkipScenarioAsync(); - } - else - { - await this.ScenarioStartAsync(); -#line 4 -await this.FeatureBackgroundAsync(); -#line hidden - global::Reqnroll.Table table5 = new global::Reqnroll.Table(new string[] { - "Email Address", - "Phone Number", - "Given Name", - "Middle Name", - "Family Name", - "Claims", - "Roles", - "Password"}); - table5.AddRow(new string[] { - "estateuser@testestate1.co.uk", - "123456789", - "Test", - "", - "User 1", - "EstateId:1", - "Estate", - "123456"}); -#line 27 - await testRunner.GivenAsync("I create the following users", ((string)(null)), table5, "Given "); -#line hidden -#line 30 - await testRunner.ThenAsync("I get an email with a confirm email address link", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden -#line 31 - await testRunner.WhenAsync("I navigate to the confirm email address", ((string)(null)), ((global::Reqnroll.Table)(null)), "When "); -#line hidden -#line 32 - await testRunner.ThenAsync("I am presented with the confirm email address successful screen", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden -#line 33 - await testRunner.AndAsync("I get a welcome email with my login details", ((string)(null)), ((global::Reqnroll.Table)(null)), "And "); -#line hidden -#line 34 - await testRunner.GivenAsync("I am on the application home page", ((string)(null)), ((global::Reqnroll.Table)(null)), "Given "); -#line hidden -#line 35 - await testRunner.WhenAsync("I click the \'Privacy\' link", ((string)(null)), ((global::Reqnroll.Table)(null)), "When "); -#line hidden -#line 36 - await testRunner.ThenAsync("I am presented with a login screen", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden -#line 37 - await testRunner.WhenAsync("I login with the username \'estateuser@testestate1.co.uk\' and the provided passwor" + - "d", ((string)(null)), ((global::Reqnroll.Table)(null)), "When "); -#line hidden -#line 38 - await testRunner.ThenAsync("I am presented with the privacy screen", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden -#line 39 - await testRunner.WhenAsync("I click the \'ChangePassword\' link", ((string)(null)), ((global::Reqnroll.Table)(null)), "When "); -#line hidden -#line 40 - await testRunner.ThenAsync("I am presented with a change password screen", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden -#line 41 - await testRunner.WhenAsync("I enter my old password", ((string)(null)), ((global::Reqnroll.Table)(null)), "When "); -#line hidden -#line 42 - await testRunner.WhenAsync("I enter my new password \'Pa55word!\'", ((string)(null)), ((global::Reqnroll.Table)(null)), "When "); -#line hidden -#line 43 - await testRunner.AndAsync("I confirm my new password \'Pa55word!\'", ((string)(null)), ((global::Reqnroll.Table)(null)), "And "); -#line hidden -#line 44 - await testRunner.AndAsync("I click the change password button", ((string)(null)), ((global::Reqnroll.Table)(null)), "And "); -#line hidden -#line 45 - await testRunner.ThenAsync("I am returned to the application home page", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden - } - await this.ScenarioCleanupAsync(); - } - } -} -#pragma warning restore -#endregion diff --git a/archive/SecurityService.OpenIdConnect.IntegrationTests/ChangePassword/ChangePasswordSteps.cs b/archive/SecurityService.OpenIdConnect.IntegrationTests/ChangePassword/ChangePasswordSteps.cs deleted file mode 100644 index 80ad2e7d..00000000 --- a/archive/SecurityService.OpenIdConnect.IntegrationTests/ChangePassword/ChangePasswordSteps.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SecurityService.OpenIdConnect.IntegrationTests.ChangePassword -{ - using IntergrationTests.Common; - using OpenQA.Selenium; - using Reqnroll; - using SecurityService.IntegrationTests.UserLogin; - using Shouldly; - - [Binding] - [Scope(Tag = "changepassword")] - public class ChangePasswordSteps - { - #region Fields - - /// - /// The testing context - /// - private readonly TestingContext TestingContext; - - /// - /// The browser session - /// - private readonly IWebDriver WebDriver; - - #endregion - - public ChangePasswordSteps(TestingContext testingContext, - IWebDriver webDriver) - { - this.TestingContext = testingContext; - this.WebDriver = webDriver; - } - - [Then(@"I am presented with a change password screen")] - public async Task ThenIAmPresentedWithAChangePasswordScreen() - { - IWebElement changePasswordButton = await this.WebDriver.FindButton("Change Password"); - changePasswordButton.ShouldNotBeNull(); - } - - //[When(@"I enter my old password '([^']*)'")] - //public async Task WhenIEnterMyOldPassword(string oldPassword) - //{ - // this.WebDriver.FillIn("Input.CurrentPassword", oldPassword); - //} - - [When("I enter my old password")] - public void WhenIEnterMyOldPassword() - { - this.WebDriver.FillIn("Input.CurrentPassword", this.TestingContext.Password); - } - - [When(@"I enter my new password '([^']*)'")] - public async Task WhenIEnterMyNewPassword(string newPassword) - { - this.WebDriver.FillIn("Input.NewPassword", newPassword); - } - - [When(@"I confirm my new password '([^']*)'")] - public async Task WhenIConfirmMyNewPassword(string newPassword) - { - this.WebDriver.FillIn("Input.ConfirmPassword", newPassword); - } - - [When(@"I click the change password button")] - public async Task WhenIClickTheChangePasswordButton() - { - await this.WebDriver.ClickButton("Change Password"); - } - - [Then(@"I am returned to the application home page")] - public void ThenIAmReturnedToTheApplicationHomePage() - { - this.WebDriver.Title.ShouldBe("Home Page - SecurityServiceTestUI"); - } - - } -} diff --git a/archive/SecurityService.OpenIdConnect.IntegrationTests/Common/DockerHelper.cs b/archive/SecurityService.OpenIdConnect.IntegrationTests/Common/DockerHelper.cs deleted file mode 100644 index 60a4229b..00000000 --- a/archive/SecurityService.OpenIdConnect.IntegrationTests/Common/DockerHelper.cs +++ /dev/null @@ -1,259 +0,0 @@ -using System.Runtime.InteropServices; -using DotNet.Testcontainers.Builders; -using DotNet.Testcontainers.Configurations; -using DotNet.Testcontainers.Containers; -using DotNet.Testcontainers.Networks; -using Shared.IntegrationTesting.TestContainers; - -namespace SecurityService.IntergrationTests.Common -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.IO; - using System.Linq; - using System.Net.Http; - using System.Runtime.CompilerServices; - using System.Threading; - using System.Threading.Tasks; - using Client; - using Newtonsoft.Json; - using Shared.HealthChecks; - using Shared.IntegrationTesting; - using Shared.Logger; - using Shouldly; - - /// - /// - /// - /// - public class DockerHelper : Shared.IntegrationTesting.TestContainers.DockerHelper - { - #region Fields - - /// - /// The security service client - /// - public ISecurityServiceClient SecurityServiceClient; - - /// - /// The security service test UI container name - /// - public String SecurityServiceTestUIContainerName; - - /// - /// The security service test UI port - /// - public Int32 SecurityServiceTestUIPort; - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The logger. - public DockerHelper() : base() - { - - } - - #endregion - - #region Methods - - public Func securityServiceBaseAddressResolver; - public HttpClient httpClient = new HttpClient(); - - public override void SetupContainerNames() - { - base.SetupContainerNames(); - - // Setup the container names - this.SecurityServiceContainerName = $"identity-server"; - this.SecurityServiceTestUIContainerName = $"securityservicetestui{this.TestId:N}"; - } - - public override async Task CreateSubscriptions(){ - // Nothing to set up here - } - - /// - /// Starts the containers for scenario run. - /// - /// Name of the scenario. - public override async Task StartContainersForScenarioRun(String scenarioName, DockerServices dockerServices) - { - this.Trace($"Test Id is {this.TestId} and Scenario {scenarioName}"); - - await base.StartContainersForScenarioRun(scenarioName,dockerServices); - - await StartContainer(SetupSecurityServiceTestUIContainer, this.TestNetworks); - - securityServiceBaseAddressResolver = api => $"https://localhost:{this.SecurityServicePort}"; - - this.SecurityServiceClient = new SecurityServiceClient(securityServiceBaseAddressResolver, httpClient); - - DockerHelper.AddEntryToHostsFile("127.0.0.1", SecurityServiceContainerName); - DockerHelper.AddEntryToHostsFile("localhost", SecurityServiceContainerName); - } - - protected async Task DoTestUIHealthCheck() - { - await Retry.For(async () => { - this.Trace($"About to do health check for Test UI"); - - SimpleResults.Result healthCheck = - await this.HealthCheckClient.PerformHealthCheck("https", "127.0.0.1", this.SecurityServiceTestUIPort, CancellationToken.None); - - healthCheck.IsSuccess.ShouldBeTrue($"Health check for Test UI failed with [{healthCheck.Message}]"); - HealthCheckResult result = JsonConvert.DeserializeObject(healthCheck.Data); - - this.Trace($"health check complete for Test UI result is [{healthCheck}]"); - - result.Status.ShouldBe(HealthCheckStatus.Healthy.ToString(), $"Service Type: Test UI Details {healthCheck}"); - this.Trace($"health check complete for Test UI"); - }, - TimeSpan.FromMinutes(3), - TimeSpan.FromSeconds(20)); - } - - protected async Task StartContainer(Func buildContainerFunc, List networkServices) - { - try - { - var containerBuilder = buildContainerFunc(); - - foreach (INetwork networkService in networkServices) { - containerBuilder = containerBuilder.WithNetwork(networkService); - } - IContainer builtContainer = containerBuilder.Build(); - await builtContainer.StartAsync(); - this.Trace($"Test UI Container Started"); - - this.SecurityServiceTestUIPort = builtContainer.GetMappedPublicPort(5004); - - this.Containers.AddRange(new List<(DockerServices, IContainer)> { - (DockerServices.None,builtContainer) - }); - - await this.DoTestUIHealthCheck(); - } - catch (Exception ex) - { - this.Error($"Error starting container [{buildContainerFunc.Method.Name}]", ex); - throw; - } - } - - /// - /// Adds the entry to hosts file. - /// - /// The ipaddress. - /// The hostname. - private static void AddEntryToHostsFile(String ipaddress, - String hostname) - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - using(StreamWriter w = File.AppendText(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), @"drivers\etc\hosts"))) - { - w.WriteLine($"{ipaddress} {hostname}"); - } - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - DockerHelper.ExecuteBashCommand($"echo {ipaddress} {hostname} | sudo tee -a /etc/hosts"); - } - } - - /// - /// Executes the bash command. - /// - /// The command. - /// - private static void ExecuteBashCommand(String command) - { - // according to: https://stackoverflow.com/a/15262019/637142 - // thans to this we will pass everything as one command - command = command.Replace("\"", "\"\""); - - var proc = new Process - { - StartInfo = new ProcessStartInfo - { - FileName = "/bin/bash", - Arguments = "-c \"" + command + "\"", - UseShellExecute = false, - RedirectStandardOutput = true, - CreateNoWindow = true - } - }; - Console.WriteLine(proc.StartInfo.Arguments); - - proc.Start(); - proc.WaitForExit(); - } - - private ContainerBuilder SetupSecurityServiceTestUIContainer(){ - - var clientDetails = ("estateUIClient", "Secret1"); - Dictionary environmentVariables = new Dictionary(); - environmentVariables.Add($"AppSettings:Authority",$"https://identity-server:{this.SecurityServicePort}"); - environmentVariables.Add($"AppSettings:ClientId",clientDetails.Item1); - environmentVariables.Add($"AppSettings:ClientSecret",clientDetails.Item2); - //environmentVariables.Add("urls","https://*:5004"); - environmentVariables.Add("Logging:LogLevel:Microsoft","Information"); - environmentVariables.Add("Logging:LogLevel:Default","Information"); - environmentVariables.Add("Logging:EventLog:LogLevel:Default","None"); - - - - ContainerBuilder securityServiceTestUIContainer = new ContainerBuilder().WithName(this.SecurityServiceTestUIContainerName) - .WithEnvironment(environmentVariables).WithImage("securityservicetestui").WithPortBinding(5004, true); - - return securityServiceTestUIContainer; - } - - public override ContainerBuilder SetupSecurityServiceContainer() - { - this.Trace("About to Start Security Container"); - - var environmentVariables = this.GetCommonEnvironmentVariables(); - environmentVariables.Add($"ServiceOptions:PublicOrigin",$"https://{this.SecurityServiceContainerName}:{DockerPorts.SecurityServiceDockerPort}"); - environmentVariables.Add($"ServiceOptions:IssuerUrl",$"https://{this.SecurityServiceContainerName}:{DockerPorts.SecurityServiceDockerPort}"); - environmentVariables.Add("ASPNETCORE_ENVIRONMENT","IntegrationTest"); - environmentVariables.Add($"urls",$"https://*:{DockerPorts.SecurityServiceDockerPort}"); - - environmentVariables.Add($"ServiceOptions:PasswordOptions:RequiredLength","6"); - environmentVariables.Add($"ServiceOptions:PasswordOptions:RequireDigit","false"); - environmentVariables.Add($"ServiceOptions:PasswordOptions:RequireUpperCase","false"); - environmentVariables.Add($"ServiceOptions:UserOptions:RequireUniqueEmail","false"); - environmentVariables.Add($"ServiceOptions:SignInOptions:RequireConfirmedEmail","false"); - - environmentVariables.Add("ConnectionStrings:PersistedGrantDbContext",this.SetConnectionString($"PersistedGrantStore-{this.TestId}", this.UseSecureSqlServerDatabase)); - environmentVariables.Add("ConnectionStrings:ConfigurationDbContext", this.SetConnectionString( $"Configuration-{this.TestId}", this.UseSecureSqlServerDatabase)); - environmentVariables.Add("ConnectionStrings:AuthenticationDbContext", this.SetConnectionString($"Authentication-{this.TestId}", this.UseSecureSqlServerDatabase)); - - Dictionary additionalEnvironmentVariables = this.GetAdditionalVariables(ContainerType.SecurityService); - - if (additionalEnvironmentVariables != null) - { - foreach (KeyValuePair additionalEnvironmentVariable in additionalEnvironmentVariables) { - environmentVariables.Add(additionalEnvironmentVariable.Key, additionalEnvironmentVariable.Value); - } - } - - var imageDetailsResult = this.GetImageDetails(ContainerType.SecurityService); - if (imageDetailsResult.IsFailed) - throw new Exception($"Image details not found for {ContainerType.SecurityService}"); - - ContainerBuilder securityServiceContainer = new ContainerBuilder().WithName(this.SecurityServiceContainerName).WithEnvironment(environmentVariables).WithImage(imageDetailsResult.Data.imageName).WithPortBinding(DockerPorts.SecurityServiceDockerPort, DockerPorts.SecurityServiceDockerPort).MountHostFolder(this.DockerPlatform, this.HostTraceFolder); - - return securityServiceContainer; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.OpenIdConnect.IntegrationTests/Common/GenericSteps.cs b/archive/SecurityService.OpenIdConnect.IntegrationTests/Common/GenericSteps.cs deleted file mode 100644 index 472bb5cd..00000000 --- a/archive/SecurityService.OpenIdConnect.IntegrationTests/Common/GenericSteps.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace SecurityService.IntergrationTests.Common -{ - using System.Threading.Tasks; - using NLog; - using Reqnroll; - using Shared.IntegrationTesting; - using Shared.Logger; - - [Binding] - [Scope(Tag = "base")] - public class GenericSteps - { - private readonly ScenarioContext ScenarioContext; - - private readonly TestingContext TestingContext; - - public GenericSteps(ScenarioContext scenarioContext, - TestingContext testingContext) - { - this.ScenarioContext = scenarioContext; - this.TestingContext = testingContext; - } - - [BeforeScenario] - public async Task StartSystem() - { - // Initialise a logger - String scenarioName = this.ScenarioContext.ScenarioInfo.Title.Replace(" ", ""); - NlogLogger logger = new NlogLogger(); - logger.Initialise(LogManager.GetLogger(scenarioName), scenarioName); - LogManager.AddHiddenAssembly(typeof(NlogLogger).Assembly); - - DockerServices dockerServices = DockerServices.SecurityService | DockerServices.SqlServer | DockerServices.MessagingService | DockerServices.EventStore; - - this.TestingContext.DockerHelper = new DockerHelper(); - this.TestingContext.DockerHelper.Logger = logger; - this.TestingContext.Logger = logger; - this.TestingContext.DockerHelper.RequiredDockerServices = dockerServices; - this.TestingContext.Logger.LogInformation("About to Start Global Setup"); - - await Setup.GlobalSetup(this.TestingContext.DockerHelper); - - this.TestingContext.DockerHelper.DockerCredentials = Setup.DockerCredentials; - this.TestingContext.DockerHelper.SqlCredentials = Setup.SqlCredentials; - this.TestingContext.DockerHelper.SqlServerContainerName = "sharedsqlserver"; - - this.TestingContext.DockerHelper.SetImageDetails(ContainerType.SecurityService, ("securityservice", false)); - - this.TestingContext.Logger = logger; - this.TestingContext.Logger.LogInformation("About to Start Containers for Scenario Run"); - await this.TestingContext.DockerHelper.StartContainersForScenarioRun(scenarioName, dockerServices).ConfigureAwait(false); - this.TestingContext.Logger.LogInformation("Containers for Scenario Run Started"); - } - - [AfterScenario] - public async Task StopSystem(){ - DockerServices sharedDockerServices = DockerServices.None; - this.TestingContext.DockerHelper.Logger.LogInformation("About to Stop Containers for Scenario Run"); - await this.TestingContext.DockerHelper.StopContainersForScenarioRun(sharedDockerServices).ConfigureAwait(false); - this.TestingContext.DockerHelper.Logger.LogInformation("Containers for Scenario Run Stopped"); - } - } -} diff --git a/archive/SecurityService.OpenIdConnect.IntegrationTests/Common/Hooks.cs b/archive/SecurityService.OpenIdConnect.IntegrationTests/Common/Hooks.cs deleted file mode 100644 index 17c652ed..00000000 --- a/archive/SecurityService.OpenIdConnect.IntegrationTests/Common/Hooks.cs +++ /dev/null @@ -1,118 +0,0 @@ -using Reqnroll.BoDi; - -namespace SecurityService.IntergrationTests.Common -{ - using System; - using System.Threading.Tasks; - using OpenQA.Selenium; - using OpenQA.Selenium.Chrome; - using OpenQA.Selenium.Edge; - using OpenQA.Selenium.Firefox; - using OpenQA.Selenium.Remote; - using Reqnroll; - using Shared.IntegrationTesting; - - /// - /// - /// - [Binding] - public class Hooks - { - #region Fields - - /// - /// The object container - /// - private readonly IObjectContainer ObjectContainer; - - /// - /// The web driver - /// - private IWebDriver WebDriver; - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The object container. - public Hooks(IObjectContainer objectContainer) - { - this.ObjectContainer = objectContainer; - } - - #endregion - - #region Methods - - /// - /// Afters the scenario. - /// - [AfterScenario(Order = 0)] - public void AfterScenario() - { - if (this.WebDriver != null) - { - this.WebDriver.Dispose(); - } - } - - /// - /// Befores the scenario. - /// - [BeforeScenario(Order = 0)] - public async Task BeforeScenario() - { - String? browser = Environment.GetEnvironmentVariable("Browser"); - //browser = "Firefox"; - if (browser == null || browser == "Chrome") - { - ChromeOptions options = new ChromeOptions(); - options.AddArguments("--disable-gpu"); - //options.AddArguments("--headless"); - options.AddArguments("--no-sandbox"); - options.AddArguments("--disable-dev-shm-usage"); - options.AddArguments("disable-infobars"); - options.AddArguments("--disable-extensions"); - options.AddArguments("--window-size=1280x1024"); - options.AcceptInsecureCertificates = true; - this.WebDriver = new ChromeDriver(options); - this.WebDriver.Manage().Window.Maximize(); - } - - if (browser == "Firefox") - { - FirefoxOptions options = new FirefoxOptions(); - options.AddArguments("--headless"); - options.SetPreference("network.cookie.cookieBehavior", 0); - options.AcceptInsecureCertificates = true; - - await Retry.For(async () => - { - this.WebDriver = new FirefoxDriver(options); - }, TimeSpan.FromMinutes(5), TimeSpan.FromSeconds(60)); - - this.WebDriver.Manage().Window.Maximize(); - } - - if (browser == "Edge") - { - EdgeOptions options = new EdgeOptions(); - options.AcceptInsecureCertificates = true; - options.AddArguments("--headless"); - options.AddArguments("--window-size=1280x1024"); - await Retry.For(async () => - { - this.WebDriver = new EdgeDriver(options); - }, TimeSpan.FromMinutes(5), TimeSpan.FromSeconds(60)); - this.WebDriver.Manage().Window.Maximize(); - } - - this.ObjectContainer.RegisterInstanceAs(this.WebDriver); - } - - #endregion - } -} diff --git a/archive/SecurityService.OpenIdConnect.IntegrationTests/Common/Setup.cs b/archive/SecurityService.OpenIdConnect.IntegrationTests/Common/Setup.cs deleted file mode 100644 index 6e522bd6..00000000 --- a/archive/SecurityService.OpenIdConnect.IntegrationTests/Common/Setup.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; - -namespace SecurityService.IntergrationTests.Common -{ - using System.Threading.Tasks; - using Ductus.FluentDocker.Services; - using Ductus.FluentDocker.Services.Extensions; - using NLog; - using Reqnroll; - using Shared.IntegrationTesting; - using Shared.Logger; - using Shouldly; - - [Binding] - public class Setup - { - public static IContainerService DatabaseServerContainer; - public static INetworkService DatabaseServerNetwork; - public static (String usename, String password) SqlCredentials = ("sa", "thisisalongpassword123!"); - public static (String url, String username, String password) DockerCredentials = ("https://www.docker.com", "stuartferguson", "Sc0tland"); - static object padLock = new object(); // Object to lock on - - public static async Task GlobalSetup(DockerHelper dockerHelper) - { - ShouldlyConfiguration.DefaultTaskTimeout = TimeSpan.FromMinutes(1); - } - - } -} diff --git a/archive/SecurityService.OpenIdConnect.IntegrationTests/Common/SharedSteps.cs b/archive/SecurityService.OpenIdConnect.IntegrationTests/Common/SharedSteps.cs deleted file mode 100644 index 7b8215b4..00000000 --- a/archive/SecurityService.OpenIdConnect.IntegrationTests/Common/SharedSteps.cs +++ /dev/null @@ -1,132 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using SimpleResults; - -namespace SecurityService.OpenIdConnect.IntegrationTests.Common -{ - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - using DataTransferObjects; - using DataTransferObjects.Requests; - using DataTransferObjects.Responses; - using IntegrationTesting.Helpers; - using IntergrationTests.Common; - using Reqnroll; - using Shared.IntegrationTesting; - using Shouldly; - - [Binding] - [Scope(Tag = "shared")] - public class SharedSteps - { - private readonly TestingContext TestingContext; - - private readonly SecurityServiceSteps SecurityServiceSteps; - - public SharedSteps(TestingContext testingContext) - { - this.TestingContext = testingContext; - this.SecurityServiceSteps = new SecurityServiceSteps(this.TestingContext.DockerHelper.SecurityServiceClient); - } - - [Given(@"I create the following roles")] - public async Task GivenICreateTheFollowingRoles(DataTable table) - { - List requests = table.Rows.ToCreateRoleRequests(); - List<(String, Guid)> responses = await this.SecurityServiceSteps.GivenICreateTheFollowingRoles(requests, CancellationToken.None); - foreach ((String, Guid) response in responses) - { - this.TestingContext.Roles.Add(response.Item1, response.Item2); - } - } - - [Given(@"I create the following identity resources")] - public async Task GivenICreateTheFollowingIdentityResources(DataTable table) - { - foreach (DataTableRow tableRow in table.Rows) - { - // Get the scopes - String userClaims = ReqnrollTableHelper.GetStringRowValue(tableRow, "UserClaims"); - - CreateIdentityResourceRequest createIdentityResourceRequest = new CreateIdentityResourceRequest - { - Name = ReqnrollTableHelper - .GetStringRowValue(tableRow, "Name") - .Replace("[id]", this.TestingContext.DockerHelper.TestId.ToString("N")), - Claims = string.IsNullOrEmpty(userClaims) ? null : userClaims.Split(",").ToList(), - Description = ReqnrollTableHelper.GetStringRowValue(tableRow, "Description"), - DisplayName = ReqnrollTableHelper.GetStringRowValue(tableRow, "DisplayName") - }; - - await this.CreateIdentityResource(createIdentityResourceRequest, CancellationToken.None).ConfigureAwait(false); - } - } - - [Given(@"I create the following api resources")] - public async Task GivenICreateTheFollowingApiResources(DataTable table) - { - List requests = table.Rows.ToCreateApiResourceRequests(this.TestingContext.DockerHelper.TestId); - await this.SecurityServiceSteps.GivenTheFollowingApiResourcesExist(requests); - foreach (CreateApiResourceRequest createApiResourceRequest in requests){ - this.TestingContext.ApiResources.Add(createApiResourceRequest.Name); - } - } - - private async Task CreateIdentityResource(CreateIdentityResourceRequest createIdentityResourceRequest, - CancellationToken cancellationToken) - { - Result> identityResourceListResult = await this.TestingContext.DockerHelper.SecurityServiceClient.GetIdentityResources(cancellationToken); - identityResourceListResult.IsSuccess.ShouldBeTrue(); - List identityResourceList = identityResourceListResult.Data; - if (identityResourceList == null || identityResourceList.Any() == false) { - Result result = await this.TestingContext.DockerHelper.SecurityServiceClient.CreateIdentityResource(createIdentityResourceRequest, cancellationToken).ConfigureAwait(false); - result.IsSuccess.ShouldBeTrue(); - - this.TestingContext.IdentityResources.Add(createIdentityResourceRequest.Name); - } - else - { - if (identityResourceList.Any(i => i.Name == createIdentityResourceRequest.Name)) - { - return; - } - - Result result = await this - .TestingContext.DockerHelper.SecurityServiceClient - .CreateIdentityResource(createIdentityResourceRequest, cancellationToken) - .ConfigureAwait(false); - result.IsSuccess.ShouldBeTrue(); - - - this.TestingContext.IdentityResources.Add(createIdentityResourceRequest.Name); - } - } - - [Given(@"I create the following clients")] - public async Task GivenICreateTheFollowingClients(DataTable table) - { - List requests = table.Rows.ToCreateClientRequests(this.TestingContext.DockerHelper.TestId, this.TestingContext.DockerHelper.SecurityServiceTestUIPort); - List<(String clientId, String secret, List allowedGrantTypes)> clients = await this.SecurityServiceSteps.GivenTheFollowingClientsExist(requests); - - foreach ((String clientId, String secret, List allowedGrantTypes) client in clients) - { - this.TestingContext.Clients.Add(client.clientId); - } - } - - [Given(@"I create the following users")] - public async Task GivenICreateTheFollowingUsers(DataTable table) - { - List requests = table.Rows.ToCreateUserRequests(); - - List<(String, Guid)> results = await this.SecurityServiceSteps.GivenICreateTheFollowingUsers(requests, CancellationToken.None); - - foreach ((String, Guid) response in results) - { - this.TestingContext.Users.Add(response.Item1, response.Item2); - } - } - } -} diff --git a/archive/SecurityService.OpenIdConnect.IntegrationTests/Common/TestingContext.cs b/archive/SecurityService.OpenIdConnect.IntegrationTests/Common/TestingContext.cs deleted file mode 100644 index 21999f31..00000000 --- a/archive/SecurityService.OpenIdConnect.IntegrationTests/Common/TestingContext.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace SecurityService.IntergrationTests.Common -{ - using System; - using System.Collections.Generic; - using DataTransferObjects.Responses; - using Shared.Logger; - - public class TestingContext - { - public DockerHelper DockerHelper { get; set; } - - public Dictionary Users; - public Dictionary Roles; - - public List Clients; - - public List ApiResources; - - public List IdentityResources; - - public TokenResponse TokenResponse; - - public NlogLogger Logger { get; set; } - - public String ResetPasswordLink { get; set; } - public String ConfirmEmailAddressLink { get; set; } - public String EmailAddress { get; set; } - public String Password { get; set; } - - public TestingContext() - { - this.Users = new Dictionary(); - this.Roles= new Dictionary(); - this.Clients=new List(); - this.ApiResources=new List(); - this.IdentityResources= new List(); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService.OpenIdConnect.IntegrationTests/ForgotPassword/ForgotPassword.feature b/archive/SecurityService.OpenIdConnect.IntegrationTests/ForgotPassword/ForgotPassword.feature deleted file mode 100644 index 2bd72e06..00000000 --- a/archive/SecurityService.OpenIdConnect.IntegrationTests/ForgotPassword/ForgotPassword.feature +++ /dev/null @@ -1,49 +0,0 @@ -@base @shared @userlogin @forgotpassword -Feature: ForgotPassword - -Background: - - Given I create the following roles - | Role Name | - | Estate | - - Given I create the following api resources - | Name | DisplayName | Secret | Scopes | UserClaims | - | transactionProcessor | Transaction Processor REST | Secret1 | transactionProcessor | MerchantId,EstateId,role | - - Given I create the following identity resources - | Name | DisplayName | Description | UserClaims | - | openid | Your user identifier | | sub | - | profile | User profile | Your user profile information (first name, last name, etc.) | name,role,email,given_name,middle_name,family_name,EstateId,MerchantId | - | email | Email | Email and Email Verified Flags | email_verified,email | - - Given I create the following clients - | ClientId | Name | Secret | Scopes | GrantTypes | RedirectUris | PostLogoutRedirectUris | RequireConsent | AllowOfflineAccess | ClientUri | - | estateUIClient | Merchant Client | Secret1 | transactionProcessor,openid,email,profile | hybrid | https://[url]:[port]/signin-oidc | https://[url]:[port]/signout-oidc | false | true | https://[url]:[port] | - - Given I create the following users - | Email Address | Password | Phone Number | Given Name | Middle Name | Family Name | Claims | Roles | - | estateuser@testestate1.co.uk | 123456 | 123456789 | Test | | User 1 | EstateId:1 | Estate | - Then I get an email with a confirm email address link - When I navigate to the confirm email address - Then I am presented with the confirm email address successful screen - And I get a welcome email with my login details - -@PRTest -Scenario: Forgot Password - Given I am on the application home page - When I click the 'Privacy' link - Then I am presented with a login screen - When I click on the Forgot Password Button - Then I am presented with the forgot password screen - When I enter my username 'estateuser@testestate1.co.uk' - And I enter my email address 'estateuser@testestate1.co.uk' - And I click on the Reset Password button - Then I am presented with the reset password request sent screen - Then I get an email with a forgot password link - When I navigate to the forgot password link - Then I am presented with the reset password screen - When I enter my new password 'Pa55word!' - And I confirm my new password 'Pa55word!' - And I click the reset password button - Then my password is reset successfully \ No newline at end of file diff --git a/archive/SecurityService.OpenIdConnect.IntegrationTests/ForgotPassword/ForgotPassword.feature.cs b/archive/SecurityService.OpenIdConnect.IntegrationTests/ForgotPassword/ForgotPassword.feature.cs deleted file mode 100644 index 97fd1696..00000000 --- a/archive/SecurityService.OpenIdConnect.IntegrationTests/ForgotPassword/ForgotPassword.feature.cs +++ /dev/null @@ -1,307 +0,0 @@ -// ------------------------------------------------------------------------------ -// -// This code was generated by Reqnroll (https://reqnroll.net/). -// Reqnroll Version:3.0.0.0 -// Reqnroll Generator Version:3.0.0.0 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -// ------------------------------------------------------------------------------ -#region Designer generated code -#pragma warning disable -using Reqnroll; -namespace SecurityService.OpenIdConnect.IntegrationTests.ForgotPassword -{ - - - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Reqnroll", "3.0.0.0")] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::NUnit.Framework.TestFixtureAttribute()] - [global::NUnit.Framework.DescriptionAttribute("ForgotPassword")] - [global::NUnit.Framework.FixtureLifeCycleAttribute(global::NUnit.Framework.LifeCycle.InstancePerTestCase)] - [global::NUnit.Framework.CategoryAttribute("base")] - [global::NUnit.Framework.CategoryAttribute("shared")] - [global::NUnit.Framework.CategoryAttribute("userlogin")] - [global::NUnit.Framework.CategoryAttribute("forgotpassword")] - public partial class ForgotPasswordFeature - { - - private global::Reqnroll.ITestRunner testRunner; - - private static string[] featureTags = new string[] { - "base", - "shared", - "userlogin", - "forgotpassword"}; - - private static global::Reqnroll.FeatureInfo featureInfo = new global::Reqnroll.FeatureInfo(new global::System.Globalization.CultureInfo("en-US"), "ForgotPassword", "ForgotPassword", null, global::Reqnroll.ProgrammingLanguage.CSharp, featureTags, InitializeCucumberMessages()); - -#line 1 "ForgotPassword.feature" -#line hidden - - [global::NUnit.Framework.OneTimeSetUpAttribute()] - public static async global::System.Threading.Tasks.Task FeatureSetupAsync() - { - } - - [global::NUnit.Framework.OneTimeTearDownAttribute()] - public static async global::System.Threading.Tasks.Task FeatureTearDownAsync() - { - await global::Reqnroll.TestRunnerManager.ReleaseFeatureAsync(featureInfo); - } - - [global::NUnit.Framework.SetUpAttribute()] - public async global::System.Threading.Tasks.Task TestInitializeAsync() - { - testRunner = global::Reqnroll.TestRunnerManager.GetTestRunnerForAssembly(featureHint: featureInfo); - try - { - if (((testRunner.FeatureContext != null) - && (testRunner.FeatureContext.FeatureInfo.Equals(featureInfo) == false))) - { - await testRunner.OnFeatureEndAsync(); - } - } - finally - { - if (((testRunner.FeatureContext != null) - && testRunner.FeatureContext.BeforeFeatureHookFailed)) - { - throw new global::Reqnroll.ReqnrollException("Scenario skipped because of previous before feature hook error"); - } - if ((testRunner.FeatureContext == null)) - { - await testRunner.OnFeatureStartAsync(featureInfo); - } - } - } - - [global::NUnit.Framework.TearDownAttribute()] - public async global::System.Threading.Tasks.Task TestTearDownAsync() - { - if ((testRunner == null)) - { - return; - } - try - { - await testRunner.OnScenarioEndAsync(); - } - finally - { - global::Reqnroll.TestRunnerManager.ReleaseTestRunner(testRunner); - testRunner = null; - } - } - - public void ScenarioInitialize(global::Reqnroll.ScenarioInfo scenarioInfo, global::Reqnroll.RuleInfo ruleInfo) - { - testRunner.OnScenarioInitialize(scenarioInfo, ruleInfo); - testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(global::NUnit.Framework.TestContext.CurrentContext); - } - - public async global::System.Threading.Tasks.Task ScenarioStartAsync() - { - await testRunner.OnScenarioStartAsync(); - } - - public async global::System.Threading.Tasks.Task ScenarioCleanupAsync() - { - await testRunner.CollectScenarioErrorsAsync(); - } - - public virtual async global::System.Threading.Tasks.Task FeatureBackgroundAsync() - { -#line 4 -#line hidden - global::Reqnroll.Table table6 = new global::Reqnroll.Table(new string[] { - "Role Name"}); - table6.AddRow(new string[] { - "Estate"}); -#line 6 - await testRunner.GivenAsync("I create the following roles", ((string)(null)), table6, "Given "); -#line hidden - global::Reqnroll.Table table7 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Secret", - "Scopes", - "UserClaims"}); - table7.AddRow(new string[] { - "transactionProcessor", - "Transaction Processor REST", - "Secret1", - "transactionProcessor", - "MerchantId,EstateId,role"}); -#line 10 - await testRunner.GivenAsync("I create the following api resources", ((string)(null)), table7, "Given "); -#line hidden - global::Reqnroll.Table table8 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Description", - "UserClaims"}); - table8.AddRow(new string[] { - "openid", - "Your user identifier", - "", - "sub"}); - table8.AddRow(new string[] { - "profile", - "User profile", - "Your user profile information (first name, last name, etc.)", - "name,role,email,given_name,middle_name,family_name,EstateId,MerchantId"}); - table8.AddRow(new string[] { - "email", - "Email", - "Email and Email Verified Flags", - "email_verified,email"}); -#line 14 - await testRunner.GivenAsync("I create the following identity resources", ((string)(null)), table8, "Given "); -#line hidden - global::Reqnroll.Table table9 = new global::Reqnroll.Table(new string[] { - "ClientId", - "Name", - "Secret", - "Scopes", - "GrantTypes", - "RedirectUris", - "PostLogoutRedirectUris", - "RequireConsent", - "AllowOfflineAccess", - "ClientUri"}); - table9.AddRow(new string[] { - "estateUIClient", - "Merchant Client", - "Secret1", - "transactionProcessor,openid,email,profile", - "hybrid", - "https://[url]:[port]/signin-oidc", - "https://[url]:[port]/signout-oidc", - "false", - "true", - "https://[url]:[port]"}); -#line 20 - await testRunner.GivenAsync("I create the following clients", ((string)(null)), table9, "Given "); -#line hidden - global::Reqnroll.Table table10 = new global::Reqnroll.Table(new string[] { - "Email Address", - "Password", - "Phone Number", - "Given Name", - "Middle Name", - "Family Name", - "Claims", - "Roles"}); - table10.AddRow(new string[] { - "estateuser@testestate1.co.uk", - "123456", - "123456789", - "Test", - "", - "User 1", - "EstateId:1", - "Estate"}); -#line 24 - await testRunner.GivenAsync("I create the following users", ((string)(null)), table10, "Given "); -#line hidden -#line 27 - await testRunner.ThenAsync("I get an email with a confirm email address link", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden -#line 28 - await testRunner.WhenAsync("I navigate to the confirm email address", ((string)(null)), ((global::Reqnroll.Table)(null)), "When "); -#line hidden -#line 29 - await testRunner.ThenAsync("I am presented with the confirm email address successful screen", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden -#line 30 - await testRunner.AndAsync("I get a welcome email with my login details", ((string)(null)), ((global::Reqnroll.Table)(null)), "And "); -#line hidden - } - - private static global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages InitializeCucumberMessages() - { - return new global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages("ForgotPassword/ForgotPassword.feature.ndjson", 3); - } - - [global::NUnit.Framework.TestAttribute()] - [global::NUnit.Framework.DescriptionAttribute("Forgot Password")] - [global::NUnit.Framework.CategoryAttribute("PRTest")] - public async global::System.Threading.Tasks.Task ForgotPassword() - { - string[] tagsOfScenario = new string[] { - "PRTest"}; - global::System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new global::System.Collections.Specialized.OrderedDictionary(); - string pickleIndex = "0"; - global::Reqnroll.ScenarioInfo scenarioInfo = new global::Reqnroll.ScenarioInfo("Forgot Password", null, tagsOfScenario, argumentsOfScenario, featureTags, pickleIndex); - string[] tagsOfRule = ((string[])(null)); - global::Reqnroll.RuleInfo ruleInfo = null; -#line 33 -this.ScenarioInitialize(scenarioInfo, ruleInfo); -#line hidden - if ((global::Reqnroll.TagHelper.ContainsIgnoreTag(scenarioInfo.CombinedTags) || global::Reqnroll.TagHelper.ContainsIgnoreTag(featureTags))) - { - await testRunner.SkipScenarioAsync(); - } - else - { - await this.ScenarioStartAsync(); -#line 4 -await this.FeatureBackgroundAsync(); -#line hidden -#line 34 - await testRunner.GivenAsync("I am on the application home page", ((string)(null)), ((global::Reqnroll.Table)(null)), "Given "); -#line hidden -#line 35 - await testRunner.WhenAsync("I click the \'Privacy\' link", ((string)(null)), ((global::Reqnroll.Table)(null)), "When "); -#line hidden -#line 36 - await testRunner.ThenAsync("I am presented with a login screen", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden -#line 37 - await testRunner.WhenAsync("I click on the Forgot Password Button", ((string)(null)), ((global::Reqnroll.Table)(null)), "When "); -#line hidden -#line 38 - await testRunner.ThenAsync("I am presented with the forgot password screen", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden -#line 39 - await testRunner.WhenAsync("I enter my username \'estateuser@testestate1.co.uk\'", ((string)(null)), ((global::Reqnroll.Table)(null)), "When "); -#line hidden -#line 40 - await testRunner.AndAsync("I enter my email address \'estateuser@testestate1.co.uk\'", ((string)(null)), ((global::Reqnroll.Table)(null)), "And "); -#line hidden -#line 41 - await testRunner.AndAsync("I click on the Reset Password button", ((string)(null)), ((global::Reqnroll.Table)(null)), "And "); -#line hidden -#line 42 - await testRunner.ThenAsync("I am presented with the reset password request sent screen", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden -#line 43 - await testRunner.ThenAsync("I get an email with a forgot password link", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden -#line 44 - await testRunner.WhenAsync("I navigate to the forgot password link", ((string)(null)), ((global::Reqnroll.Table)(null)), "When "); -#line hidden -#line 45 - await testRunner.ThenAsync("I am presented with the reset password screen", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden -#line 46 - await testRunner.WhenAsync("I enter my new password \'Pa55word!\'", ((string)(null)), ((global::Reqnroll.Table)(null)), "When "); -#line hidden -#line 47 - await testRunner.AndAsync("I confirm my new password \'Pa55word!\'", ((string)(null)), ((global::Reqnroll.Table)(null)), "And "); -#line hidden -#line 48 - await testRunner.AndAsync("I click the reset password button", ((string)(null)), ((global::Reqnroll.Table)(null)), "And "); -#line hidden -#line 49 - await testRunner.ThenAsync("my password is reset successfully", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden - } - await this.ScenarioCleanupAsync(); - } - } -} -#pragma warning restore -#endregion diff --git a/archive/SecurityService.OpenIdConnect.IntegrationTests/ForgotPassword/ForgotPasswordSteps.cs b/archive/SecurityService.OpenIdConnect.IntegrationTests/ForgotPassword/ForgotPasswordSteps.cs deleted file mode 100644 index bfcea9e3..00000000 --- a/archive/SecurityService.OpenIdConnect.IntegrationTests/ForgotPassword/ForgotPasswordSteps.cs +++ /dev/null @@ -1,156 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SecurityService.OpenIdConnect.IntegrationTests.ForgotPassword -{ - using System.Net; - using System.Net.Http; - using System.Threading; - using HtmlAgilityPack; - using IntergrationTests.Common; - using Newtonsoft.Json; - using OpenQA.Selenium; - using Reqnroll; - using SecurityService.IntegrationTests.UserLogin; - using Shared.IntegrationTesting; - using Shouldly; - - [Binding] - [Scope(Tag = "forgotpassword")] - public class ForgotPasswordSteps - { - #region Fields - - /// - /// The testing context - /// - private readonly TestingContext TestingContext; - - /// - /// The browser session - /// - private readonly IWebDriver WebDriver; - - #endregion - - public ForgotPasswordSteps(TestingContext testingContext, - IWebDriver webDriver) - { - this.TestingContext = testingContext; - this.WebDriver = webDriver; - } - - [When(@"I click on the Forgot Password Button")] - public async Task WhenIClickOnTheForgotPasswordButton() - { - await this.WebDriver.ClickButton("Forgot Password"); - } - - [Then(@"I am presented with the forgot password screen")] - public async Task ThenIAmPresentedWithTheForgotPasswordScreen() - { - IWebElement resetPasswordButton = await this.WebDriver.FindButton("Reset Password"); - resetPasswordButton.ShouldNotBeNull(); - } - - [When(@"I enter my username '([^']*)'")] - public void WhenIEnterMyUsername(string userName) - { - this.WebDriver.FillIn("Input.Username", userName.Replace("[id]", this.TestingContext.DockerHelper.TestId.ToString("N"))); - } - - [When(@"I enter my email address '([^']*)'")] - public void WhenIEnterMyEmailAddress(string emailAddress) - { - this.WebDriver.FillIn("Input.EmailAddress", emailAddress.Replace("[id]", this.TestingContext.DockerHelper.TestId.ToString("N"))); - } - - [When(@"I click on the Reset Password button")] - public async Task WhenIClickOnTheResetPasswordButton() - { - await this.WebDriver.ClickButton("Reset Password"); - } - - [Then(@"I get an email with a forgot password link")] - public async Task ThenIGetAnEmailWithAForgotPasswordLink() { - String requestUri = $"{this.TestingContext.DockerHelper.securityServiceBaseAddressResolver("")}/api/developer/lastemail"; - HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, requestUri); - - var response = await this.TestingContext.DockerHelper.httpClient.SendAsync(requestMessage, CancellationToken.None); - - response.StatusCode.ShouldBe(HttpStatusCode.OK); - - var emailMessage = new { - MessageId = Guid.Empty, - Body = String.Empty - }; - var x = JsonConvert.DeserializeAnonymousType(await response.Content.ReadAsStringAsync(CancellationToken.None), emailMessage); - - var doc = new HtmlDocument(); - doc.LoadHtml(x.Body); - var nodes = doc.DocumentNode.SelectNodes("//a[@href]"); - var resetPasswordLink = nodes[0].GetAttributeValue("href", string.Empty); - resetPasswordLink.ShouldNotBeNullOrEmpty(); - - // Cache the link - this.TestingContext.ResetPasswordLink = resetPasswordLink; - } - - [When(@"I navigate to the forgot password link")] - public void WhenINavigateToTheForgotPasswordLink() - { - this.WebDriver.Navigate().GoToUrl(this.TestingContext.ResetPasswordLink); - } - - [Then(@"I am presented with the reset password screen")] - public async Task ThenIAmPresentedWithTheResetPasswordScreen() - { - IWebElement resetPasswordButton = await this.WebDriver.FindButton("Confirm Reset Password"); - resetPasswordButton.ShouldNotBeNull(); - } - - [Then("I am presented with the reset password request sent screen")] - public async Task ThenIAmPresentedWithTheResetPasswordRequestSentScreen() - { - IWebElement resetPasswordLabel = this.WebDriver.FindElement(By.Id("forgotPasswordMessage")); - await Retry.For(async () => { - resetPasswordLabel.ShouldNotBeNull(); - }); - } - - - [When(@"I enter my new password '([^']*)'")] - public void WhenIEnterMyNewPassword(string newpassword) - { - this.WebDriver.FillIn("Input.Password", newpassword); - } - - [When(@"I confirm my new password '([^']*)'")] - public void WhenIConfirmMyNewPassword(string confirmpassword) - { - this.WebDriver.FillIn("Input.ConfirmPassword", confirmpassword); - } - - [When(@"I click the reset password button")] - public async Task WhenIClickTheResetPasswordButton() - { - await this.WebDriver.ClickButton("Confirm Reset Password"); - } - - [Then(@"my password is reset successfully")] - public async Task ThenMyPasswordIsResetSuccessfully() - { - await Retry.For(async () => - { - var page = this.WebDriver.PageSource; - - Console.WriteLine($"Source Is [{page}"); - - this.WebDriver.Title.ShouldBe("Home Page - SecurityServiceTestUI"); - }); - } - } -} diff --git a/archive/SecurityService.OpenIdConnect.IntegrationTests/SecurityService.OpenIdConnect.IntegrationTests.csproj b/archive/SecurityService.OpenIdConnect.IntegrationTests/SecurityService.OpenIdConnect.IntegrationTests.csproj deleted file mode 100644 index 8fcc786e..00000000 --- a/archive/SecurityService.OpenIdConnect.IntegrationTests/SecurityService.OpenIdConnect.IntegrationTests.csproj +++ /dev/null @@ -1,55 +0,0 @@ - - - - net10.0 - - false - - - - - - - - - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - - Always - - - $(UsingMicrosoftNETSdk) - %(RelativeDir)%(Filename).feature$(DefaultLanguageSourceExtension) - - - Always - - - - diff --git a/archive/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLogin.feature b/archive/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLogin.feature deleted file mode 100644 index 070266e2..00000000 --- a/archive/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLogin.feature +++ /dev/null @@ -1,39 +0,0 @@ -@base @shared @userlogin -Feature: User Login - -Background: - - Given I create the following roles - | Role Name | - | Estate | - - Given I create the following api resources - | Name | DisplayName | Secret | Scopes | UserClaims | - | transactionProcessor | Transaction Processor REST | Secret1 | transactionProcessor | MerchantId,EstateId,role | - - Given I create the following identity resources - | Name | DisplayName | Description | UserClaims | - | openid | Your user identifier | | sub | - | profile | User profile | Your user profile information (first name, last name, etc.) | name,role,email,given_name,middle_name,family_name,EstateId,MerchantId | - | email | Email | Email and Email Verified Flags | email_verified,email | - - Given I create the following clients - | ClientId | Name | Secret | Scopes | GrantTypes | RedirectUris | PostLogoutRedirectUris | RequireConsent | AllowOfflineAccess | ClientUri | - | estateUIClient | Merchant Client | Secret1 | transactionProcessor,openid,email,profile | hybrid | https://[url]:[port]/signin-oidc | https://[url]:[port]/signout-oidc | false | true | https://[url]:[port] | - -@PRTest -Scenario: Create User and Login - Given I create the following users - | Email Address | Phone Number | Given Name | Middle Name | Family Name | Claims | Roles | - | estateuser@testestate1.co.uk | 123456789 | Test | | User 1 | EstateId:1 | Estate | - Then I get an email with a confirm email address link - When I navigate to the confirm email address - Then I am presented with the confirm email address successful screen - And I get a welcome email with my login details - Given I am on the application home page - When I click the 'Privacy' link - Then I am presented with a login screen - When I login with the username 'estateuser@testestate1.co.uk' and the provided password - Then I am presented with the privacy screen - - diff --git a/archive/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLogin.feature.cs b/archive/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLogin.feature.cs deleted file mode 100644 index d68f2567..00000000 --- a/archive/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLogin.feature.cs +++ /dev/null @@ -1,271 +0,0 @@ -// ------------------------------------------------------------------------------ -// -// This code was generated by Reqnroll (https://reqnroll.net/). -// Reqnroll Version:3.0.0.0 -// Reqnroll Generator Version:3.0.0.0 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -// ------------------------------------------------------------------------------ -#region Designer generated code -#pragma warning disable -using Reqnroll; -namespace SecurityService.OpenIdConnect.IntegrationTests.UserLogin -{ - - - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Reqnroll", "3.0.0.0")] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::NUnit.Framework.TestFixtureAttribute()] - [global::NUnit.Framework.DescriptionAttribute("User Login")] - [global::NUnit.Framework.FixtureLifeCycleAttribute(global::NUnit.Framework.LifeCycle.InstancePerTestCase)] - [global::NUnit.Framework.CategoryAttribute("base")] - [global::NUnit.Framework.CategoryAttribute("shared")] - [global::NUnit.Framework.CategoryAttribute("userlogin")] - public partial class UserLoginFeature - { - - private global::Reqnroll.ITestRunner testRunner; - - private static string[] featureTags = new string[] { - "base", - "shared", - "userlogin"}; - - private static global::Reqnroll.FeatureInfo featureInfo = new global::Reqnroll.FeatureInfo(new global::System.Globalization.CultureInfo("en-US"), "UserLogin", "User Login", null, global::Reqnroll.ProgrammingLanguage.CSharp, featureTags, InitializeCucumberMessages()); - -#line 1 "UserLogin.feature" -#line hidden - - [global::NUnit.Framework.OneTimeSetUpAttribute()] - public static async global::System.Threading.Tasks.Task FeatureSetupAsync() - { - } - - [global::NUnit.Framework.OneTimeTearDownAttribute()] - public static async global::System.Threading.Tasks.Task FeatureTearDownAsync() - { - await global::Reqnroll.TestRunnerManager.ReleaseFeatureAsync(featureInfo); - } - - [global::NUnit.Framework.SetUpAttribute()] - public async global::System.Threading.Tasks.Task TestInitializeAsync() - { - testRunner = global::Reqnroll.TestRunnerManager.GetTestRunnerForAssembly(featureHint: featureInfo); - try - { - if (((testRunner.FeatureContext != null) - && (testRunner.FeatureContext.FeatureInfo.Equals(featureInfo) == false))) - { - await testRunner.OnFeatureEndAsync(); - } - } - finally - { - if (((testRunner.FeatureContext != null) - && testRunner.FeatureContext.BeforeFeatureHookFailed)) - { - throw new global::Reqnroll.ReqnrollException("Scenario skipped because of previous before feature hook error"); - } - if ((testRunner.FeatureContext == null)) - { - await testRunner.OnFeatureStartAsync(featureInfo); - } - } - } - - [global::NUnit.Framework.TearDownAttribute()] - public async global::System.Threading.Tasks.Task TestTearDownAsync() - { - if ((testRunner == null)) - { - return; - } - try - { - await testRunner.OnScenarioEndAsync(); - } - finally - { - global::Reqnroll.TestRunnerManager.ReleaseTestRunner(testRunner); - testRunner = null; - } - } - - public void ScenarioInitialize(global::Reqnroll.ScenarioInfo scenarioInfo, global::Reqnroll.RuleInfo ruleInfo) - { - testRunner.OnScenarioInitialize(scenarioInfo, ruleInfo); - testRunner.ScenarioContext.ScenarioContainer.RegisterInstanceAs(global::NUnit.Framework.TestContext.CurrentContext); - } - - public async global::System.Threading.Tasks.Task ScenarioStartAsync() - { - await testRunner.OnScenarioStartAsync(); - } - - public async global::System.Threading.Tasks.Task ScenarioCleanupAsync() - { - await testRunner.CollectScenarioErrorsAsync(); - } - - public virtual async global::System.Threading.Tasks.Task FeatureBackgroundAsync() - { -#line 4 -#line hidden - global::Reqnroll.Table table11 = new global::Reqnroll.Table(new string[] { - "Role Name"}); - table11.AddRow(new string[] { - "Estate"}); -#line 6 - await testRunner.GivenAsync("I create the following roles", ((string)(null)), table11, "Given "); -#line hidden - global::Reqnroll.Table table12 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Secret", - "Scopes", - "UserClaims"}); - table12.AddRow(new string[] { - "transactionProcessor", - "Transaction Processor REST", - "Secret1", - "transactionProcessor", - "MerchantId,EstateId,role"}); -#line 10 - await testRunner.GivenAsync("I create the following api resources", ((string)(null)), table12, "Given "); -#line hidden - global::Reqnroll.Table table13 = new global::Reqnroll.Table(new string[] { - "Name", - "DisplayName", - "Description", - "UserClaims"}); - table13.AddRow(new string[] { - "openid", - "Your user identifier", - "", - "sub"}); - table13.AddRow(new string[] { - "profile", - "User profile", - "Your user profile information (first name, last name, etc.)", - "name,role,email,given_name,middle_name,family_name,EstateId,MerchantId"}); - table13.AddRow(new string[] { - "email", - "Email", - "Email and Email Verified Flags", - "email_verified,email"}); -#line 14 - await testRunner.GivenAsync("I create the following identity resources", ((string)(null)), table13, "Given "); -#line hidden - global::Reqnroll.Table table14 = new global::Reqnroll.Table(new string[] { - "ClientId", - "Name", - "Secret", - "Scopes", - "GrantTypes", - "RedirectUris", - "PostLogoutRedirectUris", - "RequireConsent", - "AllowOfflineAccess", - "ClientUri"}); - table14.AddRow(new string[] { - "estateUIClient", - "Merchant Client", - "Secret1", - "transactionProcessor,openid,email,profile", - "hybrid", - "https://[url]:[port]/signin-oidc", - "https://[url]:[port]/signout-oidc", - "false", - "true", - "https://[url]:[port]"}); -#line 20 - await testRunner.GivenAsync("I create the following clients", ((string)(null)), table14, "Given "); -#line hidden - } - - private static global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages InitializeCucumberMessages() - { - return new global::Reqnroll.Formatters.RuntimeSupport.FeatureLevelCucumberMessages("UserLogin/UserLogin.feature.ndjson", 3); - } - - [global::NUnit.Framework.TestAttribute()] - [global::NUnit.Framework.DescriptionAttribute("Create User and Login")] - [global::NUnit.Framework.CategoryAttribute("PRTest")] - public async global::System.Threading.Tasks.Task CreateUserAndLogin() - { - string[] tagsOfScenario = new string[] { - "PRTest"}; - global::System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new global::System.Collections.Specialized.OrderedDictionary(); - string pickleIndex = "0"; - global::Reqnroll.ScenarioInfo scenarioInfo = new global::Reqnroll.ScenarioInfo("Create User and Login", null, tagsOfScenario, argumentsOfScenario, featureTags, pickleIndex); - string[] tagsOfRule = ((string[])(null)); - global::Reqnroll.RuleInfo ruleInfo = null; -#line 25 -this.ScenarioInitialize(scenarioInfo, ruleInfo); -#line hidden - if ((global::Reqnroll.TagHelper.ContainsIgnoreTag(scenarioInfo.CombinedTags) || global::Reqnroll.TagHelper.ContainsIgnoreTag(featureTags))) - { - await testRunner.SkipScenarioAsync(); - } - else - { - await this.ScenarioStartAsync(); -#line 4 -await this.FeatureBackgroundAsync(); -#line hidden - global::Reqnroll.Table table15 = new global::Reqnroll.Table(new string[] { - "Email Address", - "Phone Number", - "Given Name", - "Middle Name", - "Family Name", - "Claims", - "Roles"}); - table15.AddRow(new string[] { - "estateuser@testestate1.co.uk", - "123456789", - "Test", - "", - "User 1", - "EstateId:1", - "Estate"}); -#line 26 - await testRunner.GivenAsync("I create the following users", ((string)(null)), table15, "Given "); -#line hidden -#line 29 - await testRunner.ThenAsync("I get an email with a confirm email address link", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden -#line 30 - await testRunner.WhenAsync("I navigate to the confirm email address", ((string)(null)), ((global::Reqnroll.Table)(null)), "When "); -#line hidden -#line 31 - await testRunner.ThenAsync("I am presented with the confirm email address successful screen", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden -#line 32 - await testRunner.AndAsync("I get a welcome email with my login details", ((string)(null)), ((global::Reqnroll.Table)(null)), "And "); -#line hidden -#line 33 - await testRunner.GivenAsync("I am on the application home page", ((string)(null)), ((global::Reqnroll.Table)(null)), "Given "); -#line hidden -#line 34 - await testRunner.WhenAsync("I click the \'Privacy\' link", ((string)(null)), ((global::Reqnroll.Table)(null)), "When "); -#line hidden -#line 35 - await testRunner.ThenAsync("I am presented with a login screen", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden -#line 36 - await testRunner.WhenAsync("I login with the username \'estateuser@testestate1.co.uk\' and the provided passwor" + - "d", ((string)(null)), ((global::Reqnroll.Table)(null)), "When "); -#line hidden -#line 37 - await testRunner.ThenAsync("I am presented with the privacy screen", ((string)(null)), ((global::Reqnroll.Table)(null)), "Then "); -#line hidden - } - await this.ScenarioCleanupAsync(); - } - } -} -#pragma warning restore -#endregion diff --git a/archive/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLoginSteps.cs b/archive/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLoginSteps.cs deleted file mode 100644 index 3f42726d..00000000 --- a/archive/SecurityService.OpenIdConnect.IntegrationTests/UserLogin/UserLoginSteps.cs +++ /dev/null @@ -1,222 +0,0 @@ -using System; - -namespace SecurityService.IntegrationTests.UserLogin -{ - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Linq; - using System.Net; - using System.Net.Http; - using System.Text; - using System.Threading; - using System.Threading.Tasks; - using HtmlAgilityPack; - using IntergrationTests.Common; - using Newtonsoft.Json; - using OpenQA.Selenium; - using Reqnroll; - using Shared.IntegrationTesting; - using Shouldly; - - [Binding] - [Scope(Tag = "userlogin")] - public class UserLoginSteps - { - #region Fields - - /// - /// The testing context - /// - private readonly TestingContext TestingContext; - - /// - /// The browser session - /// - private readonly IWebDriver WebDriver; - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The testing context. - /// The web driver. - public UserLoginSteps(TestingContext testingContext, - IWebDriver webDriver) - { - this.TestingContext = testingContext; - this.WebDriver = webDriver; - } - - #endregion - - [Given(@"I am on the application home page")] - public void GivenIAmOnTheApplicationHomePage() - { - this.WebDriver.Navigate().GoToUrl($"https://localhost:{this.TestingContext.DockerHelper.SecurityServiceTestUIPort}"); - this.WebDriver.Title.ShouldBe("Home Page - SecurityServiceTestUI"); - } - - [When(@"I click the '(.*)' link")] - public void WhenIClickTheLink(string linkText) - { - this.WebDriver.ClickLink(linkText); - } - - [Then(@"I am presented with a login screen")] - public async Task ThenIAmPresentedWithALoginScreen() - { - IWebElement loginButton = await this.WebDriver.FindButton("Login"); - loginButton.ShouldNotBeNull(); - } - - [When(@"I login with the username '([^']*)' and the provided password")] - public void WhenILoginWithTheUsernameAndTheProvidedPassword(string userName) - { - this.WebDriver.FillIn("Input.Username", userName); - this.WebDriver.FillIn("Input.Password", this.TestingContext.Password); - this.WebDriver.ClickButton("Login"); - } - - - - [Then(@"I am presented with the privacy screen")] - public async Task ThenIAmPresentedWithThePrivacyScreen() - { - await Retry.For(async () => - { - var page = this.WebDriver.PageSource; - - Console.WriteLine($"Source Is [{page}"); - - this.WebDriver.Title.ShouldBe("Privacy Policy - SecurityServiceTestUI"); - }); - - - } - - [Then(@"I get an email with a confirm email address link")] - public async Task ThenIGetAnEmailWithAConfirmEmailAddressLink() - { - String requestUri = $"{this.TestingContext.DockerHelper.securityServiceBaseAddressResolver("")}/api/developer/lastemail"; - HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, requestUri); - - var response = await this.TestingContext.DockerHelper.httpClient.SendAsync(requestMessage, CancellationToken.None); - - response.StatusCode.ShouldBe(HttpStatusCode.OK); - - var emailMessage = new - { - MessageId = Guid.Empty, - Body = String.Empty - }; - var x = JsonConvert.DeserializeAnonymousType(await response.Content.ReadAsStringAsync(CancellationToken.None), emailMessage); - - HtmlDocument doc = new HtmlDocument(); - doc.LoadHtml(x.Body); - HtmlNodeCollection nodes = doc.DocumentNode.SelectNodes("//a[@href]"); - String confirmEmailAddressLink = nodes[0].GetAttributeValue("href", string.Empty); - confirmEmailAddressLink.ShouldNotBeNullOrEmpty(); - - // Cache the link - this.TestingContext.DockerHelper.Logger.LogInformation($"ConfirmEmailAddressLink: [{confirmEmailAddressLink}]"); - this.TestingContext.ConfirmEmailAddressLink = confirmEmailAddressLink; - } - - [Then(@"I get a welcome email with my login details")] - public async Task ThenIGetAWelcomeEmailWithMyLoginDetails() - { - String requestUri = $"{this.TestingContext.DockerHelper.securityServiceBaseAddressResolver("")}/api/developer/lastemail"; - HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, requestUri); - - var response = await this.TestingContext.DockerHelper.httpClient.SendAsync(requestMessage, CancellationToken.None); - - response.StatusCode.ShouldBe(HttpStatusCode.OK); - - var emailMessage = new - { - MessageId = Guid.Empty, - Body = String.Empty - }; - var x = JsonConvert.DeserializeAnonymousType(await response.Content.ReadAsStringAsync(CancellationToken.None), emailMessage); - - HtmlDocument doc = new HtmlDocument(); - doc.LoadHtml(x.Body); - - - var emailNode = doc.DocumentNode.SelectNodes("//*[@id='username']"); - var passwordNode = doc.DocumentNode.SelectNodes("//*[@id='password']"); - - emailNode.ShouldHaveSingleItem(); - emailNode.Single().InnerText.ShouldNotBeNullOrEmpty(); - passwordNode.ShouldHaveSingleItem(); - passwordNode.Single().InnerText.ShouldNotBeNullOrEmpty(); - - this.TestingContext.EmailAddress = emailNode.Single().InnerText.Trim(); - this.TestingContext.Password = passwordNode.Single().InnerText.Trim(); - } - - - [When(@"I navigate to the confirm email address")] - public void WhenINavigateToTheConfirmEmailAddress() { - this.WebDriver.Navigate().GoToUrl(this.TestingContext.ConfirmEmailAddressLink); - } - - [Then(@"I am presented with the confirm email address successful screen")] - public void ThenIAmPresentedWithTheConfirmEmailAddressSuccessfulScreen() { - IWebElement webElement = this.WebDriver.FindElement(By.Id("userMessage")); - webElement.Text.ShouldBe("Thanks for confirming your email address, you should receive a welcome email soon."); - } - - } - - public static class Extensions - { - public static void FillIn(this IWebDriver webDriver, - String elementName, - String value) - { - IWebElement webElement = webDriver.FindElement(By.Name(elementName)); - webElement.ShouldNotBeNull(); - webElement.SendKeys(value); - } - - public static async Task FindButton(this IWebDriver webDriver, - String buttonText) - { - IWebElement e = null; - await Retry.For(async () => - { - - - ReadOnlyCollection elements = webDriver.FindElements(By.TagName("button")); - - var foundElements = elements.Where(e => e.GetAttribute("innerText") == buttonText).ToList(); - foundElements.ShouldHaveSingleItem(); - - e = foundElements.Single(); - }); - - return e; - } - - public static void ClickLink(this IWebDriver webDriver, - String linkText) - { - IWebElement webElement = webDriver.FindElement(By.LinkText(linkText)); - webElement.ShouldNotBeNull(); - webElement.Click(); - } - - public static async Task ClickButton(this IWebDriver webDriver, - String buttonText) - { - IWebElement webElement = await webDriver.FindButton(buttonText); - webElement.ShouldNotBeNull(); - webElement.Click(); - } - - } -} diff --git a/archive/SecurityService.OpenIdConnect.IntegrationTests/nlog.config b/archive/SecurityService.OpenIdConnect.IntegrationTests/nlog.config deleted file mode 100644 index 00ad1430..00000000 --- a/archive/SecurityService.OpenIdConnect.IntegrationTests/nlog.config +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/archive/SecurityService.OpenIdConnect.IntegrationTests/xunit.runner.json b/archive/SecurityService.OpenIdConnect.IntegrationTests/xunit.runner.json deleted file mode 100644 index e402888d..00000000 --- a/archive/SecurityService.OpenIdConnect.IntegrationTests/xunit.runner.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "maxParallelThreads": 1, - "parallelizeTestCollections": false -} diff --git a/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20211201220354_InitialCreate.Designer.cs b/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20211201220354_InitialCreate.Designer.cs deleted file mode 100644 index 422070c4..00000000 --- a/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20211201220354_InitialCreate.Designer.cs +++ /dev/null @@ -1,273 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SecurityService.Database.DbContexts; - -namespace SecurityService.SqlServerMigrations.AuthenticationDb -{ - [DbContext(typeof(AuthenticationDbContext))] - [Migration("20211201220354_InitialCreate")] - partial class InitialCreate - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.12") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20211201220354_InitialCreate.cs b/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20211201220354_InitialCreate.cs deleted file mode 100644 index f8934d38..00000000 --- a/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20211201220354_InitialCreate.cs +++ /dev/null @@ -1,219 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace SecurityService.SqlServerMigrations.AuthenticationDb -{ - public partial class InitialCreate : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "AspNetRoles", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoles", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AspNetUsers", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - EmailConfirmed = table.Column(type: "bit", nullable: false), - PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), - SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), - ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), - PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), - PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), - TwoFactorEnabled = table.Column(type: "bit", nullable: false), - LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), - LockoutEnabled = table.Column(type: "bit", nullable: false), - AccessFailedCount = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUsers", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AspNetRoleClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - RoleId = table.Column(type: "nvarchar(450)", nullable: false), - ClaimType = table.Column(type: "nvarchar(max)", nullable: true), - ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - UserId = table.Column(type: "nvarchar(450)", nullable: false), - ClaimType = table.Column(type: "nvarchar(max)", nullable: true), - ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetUserClaims_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserLogins", - columns: table => new - { - LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), - ProviderKey = table.Column(type: "nvarchar(450)", nullable: false), - ProviderDisplayName = table.Column(type: "nvarchar(max)", nullable: true), - UserId = table.Column(type: "nvarchar(450)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); - table.ForeignKey( - name: "FK_AspNetUserLogins_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserRoles", - columns: table => new - { - UserId = table.Column(type: "nvarchar(450)", nullable: false), - RoleId = table.Column(type: "nvarchar(450)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserTokens", - columns: table => new - { - UserId = table.Column(type: "nvarchar(450)", nullable: false), - LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), - Name = table.Column(type: "nvarchar(450)", nullable: false), - Value = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); - table.ForeignKey( - name: "FK_AspNetUserTokens_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_AspNetRoleClaims_RoleId", - table: "AspNetRoleClaims", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "RoleNameIndex", - table: "AspNetRoles", - column: "NormalizedName", - unique: true, - filter: "[NormalizedName] IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserClaims_UserId", - table: "AspNetUserClaims", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserLogins_UserId", - table: "AspNetUserLogins", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserRoles_RoleId", - table: "AspNetUserRoles", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "EmailIndex", - table: "AspNetUsers", - column: "NormalizedEmail"); - - migrationBuilder.CreateIndex( - name: "UserNameIndex", - table: "AspNetUsers", - column: "NormalizedUserName", - unique: true, - filter: "[NormalizedUserName] IS NOT NULL"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "AspNetRoleClaims"); - - migrationBuilder.DropTable( - name: "AspNetUserClaims"); - - migrationBuilder.DropTable( - name: "AspNetUserLogins"); - - migrationBuilder.DropTable( - name: "AspNetUserRoles"); - - migrationBuilder.DropTable( - name: "AspNetUserTokens"); - - migrationBuilder.DropTable( - name: "AspNetRoles"); - - migrationBuilder.DropTable( - name: "AspNetUsers"); - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20220609181551_Net6Update.Designer.cs b/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20220609181551_Net6Update.Designer.cs deleted file mode 100644 index 71e26100..00000000 --- a/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20220609181551_Net6Update.Designer.cs +++ /dev/null @@ -1,278 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SecurityService.Database.DbContexts; - -#nullable disable - -namespace SecurityService.SqlServerMigrations.AuthenticationDb -{ - [DbContext(typeof(AuthenticationDbContext))] - [Migration("20220609181551_Net6Update")] - partial class Net6Update - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "6.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20220609181551_Net6Update.cs b/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20220609181551_Net6Update.cs deleted file mode 100644 index 74ab58e7..00000000 --- a/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20220609181551_Net6Update.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace SecurityService.SqlServerMigrations.AuthenticationDb -{ - public partial class Net6Update : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20240325171854_net8upgrade.Designer.cs b/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20240325171854_net8upgrade.Designer.cs deleted file mode 100644 index 3cb4cab9..00000000 --- a/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20240325171854_net8upgrade.Designer.cs +++ /dev/null @@ -1,279 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SecurityService.Database.DbContexts; - -#nullable disable - -namespace SecurityService.SqlServerMigrations.AuthenticationDb -{ - [DbContext(typeof(AuthenticationDbContext))] - [Migration("20240325171854_net8upgrade")] - partial class net8upgrade - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20240325171854_net8upgrade.cs b/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20240325171854_net8upgrade.cs deleted file mode 100644 index f0b06048..00000000 --- a/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20240325171854_net8upgrade.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace SecurityService.SqlServerMigrations.AuthenticationDb -{ - /// - public partial class net8upgrade : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20250318231606_record_registration_date.Designer.cs b/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20250318231606_record_registration_date.Designer.cs deleted file mode 100644 index 1105bb4a..00000000 --- a/archive/SecurityService.SqlServerMigrations/AuthenticationDb/20250318231606_record_registration_date.Designer.cs +++ /dev/null @@ -1,282 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SecurityService.Database.DbContexts; - -#nullable disable - -namespace SecurityService.SqlServerMigrations.AuthenticationDb -{ - [DbContext(typeof(AuthenticationDbContext))] - [Migration("20250318231606_record_registration_date")] - partial class record_registration_date - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("SecurityService.BusinessLogic.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("RegistrationDateTime") - .HasColumnType("datetime2"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("SecurityService.BusinessLogic.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("SecurityService.BusinessLogic.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SecurityService.BusinessLogic.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("SecurityService.BusinessLogic.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/AuthenticationDb/AuthenticationDbContextModelSnapshot.cs b/archive/SecurityService.SqlServerMigrations/AuthenticationDb/AuthenticationDbContextModelSnapshot.cs deleted file mode 100644 index b30a0ac6..00000000 --- a/archive/SecurityService.SqlServerMigrations/AuthenticationDb/AuthenticationDbContextModelSnapshot.cs +++ /dev/null @@ -1,279 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using SecurityService.Database.DbContexts; - -#nullable disable - -namespace SecurityService.SqlServerMigrations.AuthenticationDb -{ - [DbContext(typeof(AuthenticationDbContext))] - partial class AuthenticationDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("SecurityService.BusinessLogic.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("RegistrationDateTime") - .HasColumnType("datetime2"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("SecurityService.BusinessLogic.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("SecurityService.BusinessLogic.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("SecurityService.BusinessLogic.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("SecurityService.BusinessLogic.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/ConfigurationDb/20211201220252_InitialCreate.Designer.cs b/archive/SecurityService.SqlServerMigrations/ConfigurationDb/20211201220252_InitialCreate.Designer.cs deleted file mode 100644 index 76b4689e..00000000 --- a/archive/SecurityService.SqlServerMigrations/ConfigurationDb/20211201220252_InitialCreate.Designer.cs +++ /dev/null @@ -1,1020 +0,0 @@ -// -using System; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace SecurityService.SqlServerMigrations.ConfigurationDb -{ - [DbContext(typeof(ConfigurationDbContext))] - [Migration("20211201220252_InitialCreate")] - partial class InitialCreate - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.12") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("AllowedAccessTokenSigningAlgorithms") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("LastAccessed") - .HasColumnType("datetime2"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("RequireResourceIndicator") - .HasColumnType("bit"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("bit"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiResources"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiResourceClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiResourceProperties"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Scope") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiResourceScopes"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(4000) - .HasColumnType("nvarchar(4000)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiResourceSecrets"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Emphasize") - .HasColumnType("bit"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Required") - .HasColumnType("bit"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("bit"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiScopes"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ScopeId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ScopeId"); - - b.ToTable("ApiScopeClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("ScopeId") - .HasColumnType("int"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ScopeId"); - - b.ToTable("ApiScopeProperties"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("AbsoluteRefreshTokenLifetime") - .HasColumnType("int"); - - b.Property("AccessTokenLifetime") - .HasColumnType("int"); - - b.Property("AccessTokenType") - .HasColumnType("int"); - - b.Property("AllowAccessTokensViaBrowser") - .HasColumnType("bit"); - - b.Property("AllowOfflineAccess") - .HasColumnType("bit"); - - b.Property("AllowPlainTextPkce") - .HasColumnType("bit"); - - b.Property("AllowRememberConsent") - .HasColumnType("bit"); - - b.Property("AllowedIdentityTokenSigningAlgorithms") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("AlwaysIncludeUserClaimsInIdToken") - .HasColumnType("bit"); - - b.Property("AlwaysSendClientClaims") - .HasColumnType("bit"); - - b.Property("AuthorizationCodeLifetime") - .HasColumnType("int"); - - b.Property("BackChannelLogoutSessionRequired") - .HasColumnType("bit"); - - b.Property("BackChannelLogoutUri") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("ClientClaimsPrefix") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientUri") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("ConsentLifetime") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("DeviceCodeLifetime") - .HasColumnType("int"); - - b.Property("EnableLocalLogin") - .HasColumnType("bit"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("FrontChannelLogoutSessionRequired") - .HasColumnType("bit"); - - b.Property("FrontChannelLogoutUri") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("IdentityTokenLifetime") - .HasColumnType("int"); - - b.Property("IncludeJwtId") - .HasColumnType("bit"); - - b.Property("LastAccessed") - .HasColumnType("datetime2"); - - b.Property("LogoUri") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("PairWiseSubjectSalt") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ProtocolType") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("RefreshTokenExpiration") - .HasColumnType("int"); - - b.Property("RefreshTokenUsage") - .HasColumnType("int"); - - b.Property("RequireClientSecret") - .HasColumnType("bit"); - - b.Property("RequireConsent") - .HasColumnType("bit"); - - b.Property("RequirePkce") - .HasColumnType("bit"); - - b.Property("RequireRequestObject") - .HasColumnType("bit"); - - b.Property("SlidingRefreshTokenLifetime") - .HasColumnType("int"); - - b.Property("UpdateAccessTokenClaimsOnRefresh") - .HasColumnType("bit"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.Property("UserCodeType") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("UserSsoLifetime") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ClientId") - .IsUnique(); - - b.ToTable("Clients"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Origin") - .IsRequired() - .HasMaxLength(150) - .HasColumnType("nvarchar(150)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientCorsOrigins"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("GrantType") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientGrantTypes"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Provider") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientIdPRestrictions"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("PostLogoutRedirectUri") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientPostLogoutRedirectUris"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientProperties"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("RedirectUri") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientRedirectUris"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Scope") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientScopes"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(4000) - .HasColumnType("nvarchar(4000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientSecrets"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityProvider", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("Properties") - .HasColumnType("nvarchar(max)"); - - b.Property("Scheme") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("nvarchar(20)"); - - b.HasKey("Id"); - - b.ToTable("IdentityProviders"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Emphasize") - .HasColumnType("bit"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("Required") - .HasColumnType("bit"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("bit"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("IdentityResources"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("IdentityResourceId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId"); - - b.ToTable("IdentityResourceClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("IdentityResourceId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId"); - - b.ToTable("IdentityResourceProperties"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Properties") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Scopes") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Secrets") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") - .WithMany("UserClaims") - .HasForeignKey("ScopeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Scope"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") - .WithMany("Properties") - .HasForeignKey("ScopeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Scope"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("Claims") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedCorsOrigins") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedGrantTypes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("IdentityProviderRestrictions") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("PostLogoutRedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("Properties") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("RedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedScopes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("ClientSecrets") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("UserClaims") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("IdentityResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("Properties") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("IdentityResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => - { - b.Navigation("Properties"); - - b.Navigation("Scopes"); - - b.Navigation("Secrets"); - - b.Navigation("UserClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => - { - b.Navigation("Properties"); - - b.Navigation("UserClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => - { - b.Navigation("AllowedCorsOrigins"); - - b.Navigation("AllowedGrantTypes"); - - b.Navigation("AllowedScopes"); - - b.Navigation("Claims"); - - b.Navigation("ClientSecrets"); - - b.Navigation("IdentityProviderRestrictions"); - - b.Navigation("PostLogoutRedirectUris"); - - b.Navigation("Properties"); - - b.Navigation("RedirectUris"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => - { - b.Navigation("Properties"); - - b.Navigation("UserClaims"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/ConfigurationDb/20211201220252_InitialCreate.cs b/archive/SecurityService.SqlServerMigrations/ConfigurationDb/20211201220252_InitialCreate.cs deleted file mode 100644 index f3cd83c0..00000000 --- a/archive/SecurityService.SqlServerMigrations/ConfigurationDb/20211201220252_InitialCreate.cs +++ /dev/null @@ -1,678 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace SecurityService.SqlServerMigrations.ConfigurationDb -{ - public partial class InitialCreate : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "ApiResources", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Enabled = table.Column(type: "bit", nullable: false), - Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - DisplayName = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), - AllowedAccessTokenSigningAlgorithms = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - ShowInDiscoveryDocument = table.Column(type: "bit", nullable: false), - RequireResourceIndicator = table.Column(type: "bit", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - Updated = table.Column(type: "datetime2", nullable: true), - LastAccessed = table.Column(type: "datetime2", nullable: true), - NonEditable = table.Column(type: "bit", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiResources", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "ApiScopes", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Enabled = table.Column(type: "bit", nullable: false), - Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - DisplayName = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), - Required = table.Column(type: "bit", nullable: false), - Emphasize = table.Column(type: "bit", nullable: false), - ShowInDiscoveryDocument = table.Column(type: "bit", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiScopes", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Clients", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Enabled = table.Column(type: "bit", nullable: false), - ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - ProtocolType = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - RequireClientSecret = table.Column(type: "bit", nullable: false), - ClientName = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), - ClientUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), - LogoUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), - RequireConsent = table.Column(type: "bit", nullable: false), - AllowRememberConsent = table.Column(type: "bit", nullable: false), - AlwaysIncludeUserClaimsInIdToken = table.Column(type: "bit", nullable: false), - RequirePkce = table.Column(type: "bit", nullable: false), - AllowPlainTextPkce = table.Column(type: "bit", nullable: false), - RequireRequestObject = table.Column(type: "bit", nullable: false), - AllowAccessTokensViaBrowser = table.Column(type: "bit", nullable: false), - FrontChannelLogoutUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), - FrontChannelLogoutSessionRequired = table.Column(type: "bit", nullable: false), - BackChannelLogoutUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), - BackChannelLogoutSessionRequired = table.Column(type: "bit", nullable: false), - AllowOfflineAccess = table.Column(type: "bit", nullable: false), - IdentityTokenLifetime = table.Column(type: "int", nullable: false), - AllowedIdentityTokenSigningAlgorithms = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - AccessTokenLifetime = table.Column(type: "int", nullable: false), - AuthorizationCodeLifetime = table.Column(type: "int", nullable: false), - ConsentLifetime = table.Column(type: "int", nullable: true), - AbsoluteRefreshTokenLifetime = table.Column(type: "int", nullable: false), - SlidingRefreshTokenLifetime = table.Column(type: "int", nullable: false), - RefreshTokenUsage = table.Column(type: "int", nullable: false), - UpdateAccessTokenClaimsOnRefresh = table.Column(type: "bit", nullable: false), - RefreshTokenExpiration = table.Column(type: "int", nullable: false), - AccessTokenType = table.Column(type: "int", nullable: false), - EnableLocalLogin = table.Column(type: "bit", nullable: false), - IncludeJwtId = table.Column(type: "bit", nullable: false), - AlwaysSendClientClaims = table.Column(type: "bit", nullable: false), - ClientClaimsPrefix = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - PairWiseSubjectSalt = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - Updated = table.Column(type: "datetime2", nullable: true), - LastAccessed = table.Column(type: "datetime2", nullable: true), - UserSsoLifetime = table.Column(type: "int", nullable: true), - UserCodeType = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - DeviceCodeLifetime = table.Column(type: "int", nullable: false), - NonEditable = table.Column(type: "bit", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Clients", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "IdentityProviders", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Scheme = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - DisplayName = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - Enabled = table.Column(type: "bit", nullable: false), - Type = table.Column(type: "nvarchar(20)", maxLength: 20, nullable: false), - Properties = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_IdentityProviders", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "IdentityResources", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Enabled = table.Column(type: "bit", nullable: false), - Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - DisplayName = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), - Required = table.Column(type: "bit", nullable: false), - Emphasize = table.Column(type: "bit", nullable: false), - ShowInDiscoveryDocument = table.Column(type: "bit", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - Updated = table.Column(type: "datetime2", nullable: true), - NonEditable = table.Column(type: "bit", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_IdentityResources", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "ApiResourceClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ApiResourceId = table.Column(type: "int", nullable: false), - Type = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiResourceClaims", x => x.Id); - table.ForeignKey( - name: "FK_ApiResourceClaims_ApiResources_ApiResourceId", - column: x => x.ApiResourceId, - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ApiResourceProperties", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ApiResourceId = table.Column(type: "int", nullable: false), - Key = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), - Value = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiResourceProperties", x => x.Id); - table.ForeignKey( - name: "FK_ApiResourceProperties_ApiResources_ApiResourceId", - column: x => x.ApiResourceId, - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ApiResourceScopes", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Scope = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - ApiResourceId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiResourceScopes", x => x.Id); - table.ForeignKey( - name: "FK_ApiResourceScopes_ApiResources_ApiResourceId", - column: x => x.ApiResourceId, - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ApiResourceSecrets", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ApiResourceId = table.Column(type: "int", nullable: false), - Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), - Value = table.Column(type: "nvarchar(4000)", maxLength: 4000, nullable: false), - Expiration = table.Column(type: "datetime2", nullable: true), - Type = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), - Created = table.Column(type: "datetime2", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiResourceSecrets", x => x.Id); - table.ForeignKey( - name: "FK_ApiResourceSecrets_ApiResources_ApiResourceId", - column: x => x.ApiResourceId, - principalTable: "ApiResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ApiScopeClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ScopeId = table.Column(type: "int", nullable: false), - Type = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiScopeClaims", x => x.Id); - table.ForeignKey( - name: "FK_ApiScopeClaims_ApiScopes_ScopeId", - column: x => x.ScopeId, - principalTable: "ApiScopes", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ApiScopeProperties", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ScopeId = table.Column(type: "int", nullable: false), - Key = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), - Value = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiScopeProperties", x => x.Id); - table.ForeignKey( - name: "FK_ApiScopeProperties_ApiScopes_ScopeId", - column: x => x.ScopeId, - principalTable: "ApiScopes", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Type = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), - Value = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), - ClientId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientClaims", x => x.Id); - table.ForeignKey( - name: "FK_ClientClaims_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientCorsOrigins", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Origin = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: false), - ClientId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientCorsOrigins", x => x.Id); - table.ForeignKey( - name: "FK_ClientCorsOrigins_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientGrantTypes", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - GrantType = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), - ClientId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientGrantTypes", x => x.Id); - table.ForeignKey( - name: "FK_ClientGrantTypes_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientIdPRestrictions", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Provider = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - ClientId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientIdPRestrictions", x => x.Id); - table.ForeignKey( - name: "FK_ClientIdPRestrictions_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientPostLogoutRedirectUris", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - PostLogoutRedirectUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: false), - ClientId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientPostLogoutRedirectUris", x => x.Id); - table.ForeignKey( - name: "FK_ClientPostLogoutRedirectUris_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientProperties", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ClientId = table.Column(type: "int", nullable: false), - Key = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), - Value = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientProperties", x => x.Id); - table.ForeignKey( - name: "FK_ClientProperties_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientRedirectUris", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - RedirectUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: false), - ClientId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientRedirectUris", x => x.Id); - table.ForeignKey( - name: "FK_ClientRedirectUris_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientScopes", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Scope = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - ClientId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientScopes", x => x.Id); - table.ForeignKey( - name: "FK_ClientScopes_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ClientSecrets", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ClientId = table.Column(type: "int", nullable: false), - Description = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), - Value = table.Column(type: "nvarchar(4000)", maxLength: 4000, nullable: false), - Expiration = table.Column(type: "datetime2", nullable: true), - Type = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), - Created = table.Column(type: "datetime2", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ClientSecrets", x => x.Id); - table.ForeignKey( - name: "FK_ClientSecrets_Clients_ClientId", - column: x => x.ClientId, - principalTable: "Clients", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "IdentityResourceClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - IdentityResourceId = table.Column(type: "int", nullable: false), - Type = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_IdentityResourceClaims", x => x.Id); - table.ForeignKey( - name: "FK_IdentityResourceClaims_IdentityResources_IdentityResourceId", - column: x => x.IdentityResourceId, - principalTable: "IdentityResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "IdentityResourceProperties", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - IdentityResourceId = table.Column(type: "int", nullable: false), - Key = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), - Value = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_IdentityResourceProperties", x => x.Id); - table.ForeignKey( - name: "FK_IdentityResourceProperties_IdentityResources_IdentityResourceId", - column: x => x.IdentityResourceId, - principalTable: "IdentityResources", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceClaims_ApiResourceId", - table: "ApiResourceClaims", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceProperties_ApiResourceId", - table: "ApiResourceProperties", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiResources_Name", - table: "ApiResources", - column: "Name", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceScopes_ApiResourceId", - table: "ApiResourceScopes", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceSecrets_ApiResourceId", - table: "ApiResourceSecrets", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopeClaims_ScopeId", - table: "ApiScopeClaims", - column: "ScopeId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopeProperties_ScopeId", - table: "ApiScopeProperties", - column: "ScopeId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopes_Name", - table: "ApiScopes", - column: "Name", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientClaims_ClientId", - table: "ClientClaims", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientCorsOrigins_ClientId", - table: "ClientCorsOrigins", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientGrantTypes_ClientId", - table: "ClientGrantTypes", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientIdPRestrictions_ClientId", - table: "ClientIdPRestrictions", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientPostLogoutRedirectUris_ClientId", - table: "ClientPostLogoutRedirectUris", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientProperties_ClientId", - table: "ClientProperties", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientRedirectUris_ClientId", - table: "ClientRedirectUris", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_Clients_ClientId", - table: "Clients", - column: "ClientId", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientScopes_ClientId", - table: "ClientScopes", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientSecrets_ClientId", - table: "ClientSecrets", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_IdentityResourceClaims_IdentityResourceId", - table: "IdentityResourceClaims", - column: "IdentityResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_IdentityResourceProperties_IdentityResourceId", - table: "IdentityResourceProperties", - column: "IdentityResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_IdentityResources_Name", - table: "IdentityResources", - column: "Name", - unique: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "ApiResourceClaims"); - - migrationBuilder.DropTable( - name: "ApiResourceProperties"); - - migrationBuilder.DropTable( - name: "ApiResourceScopes"); - - migrationBuilder.DropTable( - name: "ApiResourceSecrets"); - - migrationBuilder.DropTable( - name: "ApiScopeClaims"); - - migrationBuilder.DropTable( - name: "ApiScopeProperties"); - - migrationBuilder.DropTable( - name: "ClientClaims"); - - migrationBuilder.DropTable( - name: "ClientCorsOrigins"); - - migrationBuilder.DropTable( - name: "ClientGrantTypes"); - - migrationBuilder.DropTable( - name: "ClientIdPRestrictions"); - - migrationBuilder.DropTable( - name: "ClientPostLogoutRedirectUris"); - - migrationBuilder.DropTable( - name: "ClientProperties"); - - migrationBuilder.DropTable( - name: "ClientRedirectUris"); - - migrationBuilder.DropTable( - name: "ClientScopes"); - - migrationBuilder.DropTable( - name: "ClientSecrets"); - - migrationBuilder.DropTable( - name: "IdentityProviders"); - - migrationBuilder.DropTable( - name: "IdentityResourceClaims"); - - migrationBuilder.DropTable( - name: "IdentityResourceProperties"); - - migrationBuilder.DropTable( - name: "ApiResources"); - - migrationBuilder.DropTable( - name: "ApiScopes"); - - migrationBuilder.DropTable( - name: "Clients"); - - migrationBuilder.DropTable( - name: "IdentityResources"); - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/ConfigurationDb/20220609181610_Net6Update.Designer.cs b/archive/SecurityService.SqlServerMigrations/ConfigurationDb/20220609181610_Net6Update.Designer.cs deleted file mode 100644 index 31faa306..00000000 --- a/archive/SecurityService.SqlServerMigrations/ConfigurationDb/20220609181610_Net6Update.Designer.cs +++ /dev/null @@ -1,1096 +0,0 @@ -// -using System; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace SecurityService.SqlServerMigrations.ConfigurationDb -{ - [DbContext(typeof(ConfigurationDbContext))] - [Migration("20220609181610_Net6Update")] - partial class Net6Update - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "6.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("AllowedAccessTokenSigningAlgorithms") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("LastAccessed") - .HasColumnType("datetime2"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("RequireResourceIndicator") - .HasColumnType("bit"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("bit"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiResources", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId", "Type") - .IsUnique(); - - b.ToTable("ApiResourceClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId", "Key") - .IsUnique(); - - b.ToTable("ApiResourceProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Scope") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId", "Scope") - .IsUnique(); - - b.ToTable("ApiResourceScopes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(4000) - .HasColumnType("nvarchar(4000)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiResourceSecrets", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Emphasize") - .HasColumnType("bit"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("LastAccessed") - .HasColumnType("datetime2"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("Required") - .HasColumnType("bit"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("bit"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiScopes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ScopeId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ScopeId", "Type") - .IsUnique(); - - b.ToTable("ApiScopeClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("ScopeId") - .HasColumnType("int"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ScopeId", "Key") - .IsUnique(); - - b.ToTable("ApiScopeProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("AbsoluteRefreshTokenLifetime") - .HasColumnType("int"); - - b.Property("AccessTokenLifetime") - .HasColumnType("int"); - - b.Property("AccessTokenType") - .HasColumnType("int"); - - b.Property("AllowAccessTokensViaBrowser") - .HasColumnType("bit"); - - b.Property("AllowOfflineAccess") - .HasColumnType("bit"); - - b.Property("AllowPlainTextPkce") - .HasColumnType("bit"); - - b.Property("AllowRememberConsent") - .HasColumnType("bit"); - - b.Property("AllowedIdentityTokenSigningAlgorithms") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("AlwaysIncludeUserClaimsInIdToken") - .HasColumnType("bit"); - - b.Property("AlwaysSendClientClaims") - .HasColumnType("bit"); - - b.Property("AuthorizationCodeLifetime") - .HasColumnType("int"); - - b.Property("BackChannelLogoutSessionRequired") - .HasColumnType("bit"); - - b.Property("BackChannelLogoutUri") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("CibaLifetime") - .HasColumnType("int"); - - b.Property("ClientClaimsPrefix") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientUri") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("ConsentLifetime") - .HasColumnType("int"); - - b.Property("CoordinateLifetimeWithUserSession") - .HasColumnType("bit"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("DeviceCodeLifetime") - .HasColumnType("int"); - - b.Property("EnableLocalLogin") - .HasColumnType("bit"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("FrontChannelLogoutSessionRequired") - .HasColumnType("bit"); - - b.Property("FrontChannelLogoutUri") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("IdentityTokenLifetime") - .HasColumnType("int"); - - b.Property("IncludeJwtId") - .HasColumnType("bit"); - - b.Property("LastAccessed") - .HasColumnType("datetime2"); - - b.Property("LogoUri") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("PairWiseSubjectSalt") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("PollingInterval") - .HasColumnType("int"); - - b.Property("ProtocolType") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("RefreshTokenExpiration") - .HasColumnType("int"); - - b.Property("RefreshTokenUsage") - .HasColumnType("int"); - - b.Property("RequireClientSecret") - .HasColumnType("bit"); - - b.Property("RequireConsent") - .HasColumnType("bit"); - - b.Property("RequirePkce") - .HasColumnType("bit"); - - b.Property("RequireRequestObject") - .HasColumnType("bit"); - - b.Property("SlidingRefreshTokenLifetime") - .HasColumnType("int"); - - b.Property("UpdateAccessTokenClaimsOnRefresh") - .HasColumnType("bit"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.Property("UserCodeType") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("UserSsoLifetime") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ClientId") - .IsUnique(); - - b.ToTable("Clients", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Type", "Value") - .IsUnique(); - - b.ToTable("ClientClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Origin") - .IsRequired() - .HasMaxLength(150) - .HasColumnType("nvarchar(150)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Origin") - .IsUnique(); - - b.ToTable("ClientCorsOrigins", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("GrantType") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "GrantType") - .IsUnique(); - - b.ToTable("ClientGrantTypes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Provider") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Provider") - .IsUnique(); - - b.ToTable("ClientIdPRestrictions", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("PostLogoutRedirectUri") - .IsRequired() - .HasMaxLength(400) - .HasColumnType("nvarchar(400)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "PostLogoutRedirectUri") - .IsUnique(); - - b.ToTable("ClientPostLogoutRedirectUris", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Key") - .IsUnique(); - - b.ToTable("ClientProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("RedirectUri") - .IsRequired() - .HasMaxLength(400) - .HasColumnType("nvarchar(400)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "RedirectUri") - .IsUnique(); - - b.ToTable("ClientRedirectUris", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Scope") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Scope") - .IsUnique(); - - b.ToTable("ClientScopes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(4000) - .HasColumnType("nvarchar(4000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientSecrets", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityProvider", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("LastAccessed") - .HasColumnType("datetime2"); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("Properties") - .HasColumnType("nvarchar(max)"); - - b.Property("Scheme") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("nvarchar(20)"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("Scheme") - .IsUnique(); - - b.ToTable("IdentityProviders", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Emphasize") - .HasColumnType("bit"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("Required") - .HasColumnType("bit"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("bit"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("IdentityResources", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("IdentityResourceId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId", "Type") - .IsUnique(); - - b.ToTable("IdentityResourceClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("IdentityResourceId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId", "Key") - .IsUnique(); - - b.ToTable("IdentityResourceProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Properties") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Scopes") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Secrets") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") - .WithMany("UserClaims") - .HasForeignKey("ScopeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Scope"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") - .WithMany("Properties") - .HasForeignKey("ScopeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Scope"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("Claims") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedCorsOrigins") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedGrantTypes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("IdentityProviderRestrictions") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("PostLogoutRedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("Properties") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("RedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedScopes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("ClientSecrets") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("UserClaims") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("IdentityResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("Properties") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("IdentityResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => - { - b.Navigation("Properties"); - - b.Navigation("Scopes"); - - b.Navigation("Secrets"); - - b.Navigation("UserClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => - { - b.Navigation("Properties"); - - b.Navigation("UserClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => - { - b.Navigation("AllowedCorsOrigins"); - - b.Navigation("AllowedGrantTypes"); - - b.Navigation("AllowedScopes"); - - b.Navigation("Claims"); - - b.Navigation("ClientSecrets"); - - b.Navigation("IdentityProviderRestrictions"); - - b.Navigation("PostLogoutRedirectUris"); - - b.Navigation("Properties"); - - b.Navigation("RedirectUris"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => - { - b.Navigation("Properties"); - - b.Navigation("UserClaims"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/ConfigurationDb/20220609181610_Net6Update.cs b/archive/SecurityService.SqlServerMigrations/ConfigurationDb/20220609181610_Net6Update.cs deleted file mode 100644 index 941b2d36..00000000 --- a/archive/SecurityService.SqlServerMigrations/ConfigurationDb/20220609181610_Net6Update.cs +++ /dev/null @@ -1,465 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace SecurityService.SqlServerMigrations.ConfigurationDb -{ - public partial class Net6Update : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_IdentityResourceProperties_IdentityResourceId", - table: "IdentityResourceProperties"); - - migrationBuilder.DropIndex( - name: "IX_IdentityResourceClaims_IdentityResourceId", - table: "IdentityResourceClaims"); - - migrationBuilder.DropIndex( - name: "IX_ClientScopes_ClientId", - table: "ClientScopes"); - - migrationBuilder.DropIndex( - name: "IX_ClientRedirectUris_ClientId", - table: "ClientRedirectUris"); - - migrationBuilder.DropIndex( - name: "IX_ClientProperties_ClientId", - table: "ClientProperties"); - - migrationBuilder.DropIndex( - name: "IX_ClientPostLogoutRedirectUris_ClientId", - table: "ClientPostLogoutRedirectUris"); - - migrationBuilder.DropIndex( - name: "IX_ClientIdPRestrictions_ClientId", - table: "ClientIdPRestrictions"); - - migrationBuilder.DropIndex( - name: "IX_ClientGrantTypes_ClientId", - table: "ClientGrantTypes"); - - migrationBuilder.DropIndex( - name: "IX_ClientCorsOrigins_ClientId", - table: "ClientCorsOrigins"); - - migrationBuilder.DropIndex( - name: "IX_ClientClaims_ClientId", - table: "ClientClaims"); - - migrationBuilder.DropIndex( - name: "IX_ApiScopeProperties_ScopeId", - table: "ApiScopeProperties"); - - migrationBuilder.DropIndex( - name: "IX_ApiScopeClaims_ScopeId", - table: "ApiScopeClaims"); - - migrationBuilder.DropIndex( - name: "IX_ApiResourceScopes_ApiResourceId", - table: "ApiResourceScopes"); - - migrationBuilder.DropIndex( - name: "IX_ApiResourceProperties_ApiResourceId", - table: "ApiResourceProperties"); - - migrationBuilder.DropIndex( - name: "IX_ApiResourceClaims_ApiResourceId", - table: "ApiResourceClaims"); - - migrationBuilder.AddColumn( - name: "Created", - table: "IdentityProviders", - type: "datetime2", - nullable: false, - defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); - - migrationBuilder.AddColumn( - name: "LastAccessed", - table: "IdentityProviders", - type: "datetime2", - nullable: true); - - migrationBuilder.AddColumn( - name: "NonEditable", - table: "IdentityProviders", - type: "bit", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "Updated", - table: "IdentityProviders", - type: "datetime2", - nullable: true); - - migrationBuilder.AddColumn( - name: "CibaLifetime", - table: "Clients", - type: "int", - nullable: true); - - migrationBuilder.AddColumn( - name: "CoordinateLifetimeWithUserSession", - table: "Clients", - type: "bit", - nullable: true); - - migrationBuilder.AddColumn( - name: "PollingInterval", - table: "Clients", - type: "int", - nullable: true); - - migrationBuilder.AlterColumn( - name: "RedirectUri", - table: "ClientRedirectUris", - type: "nvarchar(400)", - maxLength: 400, - nullable: false, - oldClrType: typeof(string), - oldType: "nvarchar(2000)", - oldMaxLength: 2000); - - migrationBuilder.AlterColumn( - name: "PostLogoutRedirectUri", - table: "ClientPostLogoutRedirectUris", - type: "nvarchar(400)", - maxLength: 400, - nullable: false, - oldClrType: typeof(string), - oldType: "nvarchar(2000)", - oldMaxLength: 2000); - - migrationBuilder.AddColumn( - name: "Created", - table: "ApiScopes", - type: "datetime2", - nullable: false, - defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); - - migrationBuilder.AddColumn( - name: "LastAccessed", - table: "ApiScopes", - type: "datetime2", - nullable: true); - - migrationBuilder.AddColumn( - name: "NonEditable", - table: "ApiScopes", - type: "bit", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "Updated", - table: "ApiScopes", - type: "datetime2", - nullable: true); - - migrationBuilder.CreateIndex( - name: "IX_IdentityResourceProperties_IdentityResourceId_Key", - table: "IdentityResourceProperties", - columns: new[] { "IdentityResourceId", "Key" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_IdentityResourceClaims_IdentityResourceId_Type", - table: "IdentityResourceClaims", - columns: new[] { "IdentityResourceId", "Type" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_IdentityProviders_Scheme", - table: "IdentityProviders", - column: "Scheme", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientScopes_ClientId_Scope", - table: "ClientScopes", - columns: new[] { "ClientId", "Scope" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientRedirectUris_ClientId_RedirectUri", - table: "ClientRedirectUris", - columns: new[] { "ClientId", "RedirectUri" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientProperties_ClientId_Key", - table: "ClientProperties", - columns: new[] { "ClientId", "Key" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientPostLogoutRedirectUris_ClientId_PostLogoutRedirectUri", - table: "ClientPostLogoutRedirectUris", - columns: new[] { "ClientId", "PostLogoutRedirectUri" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientIdPRestrictions_ClientId_Provider", - table: "ClientIdPRestrictions", - columns: new[] { "ClientId", "Provider" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientGrantTypes_ClientId_GrantType", - table: "ClientGrantTypes", - columns: new[] { "ClientId", "GrantType" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientCorsOrigins_ClientId_Origin", - table: "ClientCorsOrigins", - columns: new[] { "ClientId", "Origin" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ClientClaims_ClientId_Type_Value", - table: "ClientClaims", - columns: new[] { "ClientId", "Type", "Value" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopeProperties_ScopeId_Key", - table: "ApiScopeProperties", - columns: new[] { "ScopeId", "Key" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopeClaims_ScopeId_Type", - table: "ApiScopeClaims", - columns: new[] { "ScopeId", "Type" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceScopes_ApiResourceId_Scope", - table: "ApiResourceScopes", - columns: new[] { "ApiResourceId", "Scope" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceProperties_ApiResourceId_Key", - table: "ApiResourceProperties", - columns: new[] { "ApiResourceId", "Key" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceClaims_ApiResourceId_Type", - table: "ApiResourceClaims", - columns: new[] { "ApiResourceId", "Type" }, - unique: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_IdentityResourceProperties_IdentityResourceId_Key", - table: "IdentityResourceProperties"); - - migrationBuilder.DropIndex( - name: "IX_IdentityResourceClaims_IdentityResourceId_Type", - table: "IdentityResourceClaims"); - - migrationBuilder.DropIndex( - name: "IX_IdentityProviders_Scheme", - table: "IdentityProviders"); - - migrationBuilder.DropIndex( - name: "IX_ClientScopes_ClientId_Scope", - table: "ClientScopes"); - - migrationBuilder.DropIndex( - name: "IX_ClientRedirectUris_ClientId_RedirectUri", - table: "ClientRedirectUris"); - - migrationBuilder.DropIndex( - name: "IX_ClientProperties_ClientId_Key", - table: "ClientProperties"); - - migrationBuilder.DropIndex( - name: "IX_ClientPostLogoutRedirectUris_ClientId_PostLogoutRedirectUri", - table: "ClientPostLogoutRedirectUris"); - - migrationBuilder.DropIndex( - name: "IX_ClientIdPRestrictions_ClientId_Provider", - table: "ClientIdPRestrictions"); - - migrationBuilder.DropIndex( - name: "IX_ClientGrantTypes_ClientId_GrantType", - table: "ClientGrantTypes"); - - migrationBuilder.DropIndex( - name: "IX_ClientCorsOrigins_ClientId_Origin", - table: "ClientCorsOrigins"); - - migrationBuilder.DropIndex( - name: "IX_ClientClaims_ClientId_Type_Value", - table: "ClientClaims"); - - migrationBuilder.DropIndex( - name: "IX_ApiScopeProperties_ScopeId_Key", - table: "ApiScopeProperties"); - - migrationBuilder.DropIndex( - name: "IX_ApiScopeClaims_ScopeId_Type", - table: "ApiScopeClaims"); - - migrationBuilder.DropIndex( - name: "IX_ApiResourceScopes_ApiResourceId_Scope", - table: "ApiResourceScopes"); - - migrationBuilder.DropIndex( - name: "IX_ApiResourceProperties_ApiResourceId_Key", - table: "ApiResourceProperties"); - - migrationBuilder.DropIndex( - name: "IX_ApiResourceClaims_ApiResourceId_Type", - table: "ApiResourceClaims"); - - migrationBuilder.DropColumn( - name: "Created", - table: "IdentityProviders"); - - migrationBuilder.DropColumn( - name: "LastAccessed", - table: "IdentityProviders"); - - migrationBuilder.DropColumn( - name: "NonEditable", - table: "IdentityProviders"); - - migrationBuilder.DropColumn( - name: "Updated", - table: "IdentityProviders"); - - migrationBuilder.DropColumn( - name: "CibaLifetime", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "CoordinateLifetimeWithUserSession", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "PollingInterval", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "Created", - table: "ApiScopes"); - - migrationBuilder.DropColumn( - name: "LastAccessed", - table: "ApiScopes"); - - migrationBuilder.DropColumn( - name: "NonEditable", - table: "ApiScopes"); - - migrationBuilder.DropColumn( - name: "Updated", - table: "ApiScopes"); - - migrationBuilder.AlterColumn( - name: "RedirectUri", - table: "ClientRedirectUris", - type: "nvarchar(2000)", - maxLength: 2000, - nullable: false, - oldClrType: typeof(string), - oldType: "nvarchar(400)", - oldMaxLength: 400); - - migrationBuilder.AlterColumn( - name: "PostLogoutRedirectUri", - table: "ClientPostLogoutRedirectUris", - type: "nvarchar(2000)", - maxLength: 2000, - nullable: false, - oldClrType: typeof(string), - oldType: "nvarchar(400)", - oldMaxLength: 400); - - migrationBuilder.CreateIndex( - name: "IX_IdentityResourceProperties_IdentityResourceId", - table: "IdentityResourceProperties", - column: "IdentityResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_IdentityResourceClaims_IdentityResourceId", - table: "IdentityResourceClaims", - column: "IdentityResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientScopes_ClientId", - table: "ClientScopes", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientRedirectUris_ClientId", - table: "ClientRedirectUris", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientProperties_ClientId", - table: "ClientProperties", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientPostLogoutRedirectUris_ClientId", - table: "ClientPostLogoutRedirectUris", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientIdPRestrictions_ClientId", - table: "ClientIdPRestrictions", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientGrantTypes_ClientId", - table: "ClientGrantTypes", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientCorsOrigins_ClientId", - table: "ClientCorsOrigins", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ClientClaims_ClientId", - table: "ClientClaims", - column: "ClientId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopeProperties_ScopeId", - table: "ApiScopeProperties", - column: "ScopeId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiScopeClaims_ScopeId", - table: "ApiScopeClaims", - column: "ScopeId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceScopes_ApiResourceId", - table: "ApiResourceScopes", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceProperties_ApiResourceId", - table: "ApiResourceProperties", - column: "ApiResourceId"); - - migrationBuilder.CreateIndex( - name: "IX_ApiResourceClaims_ApiResourceId", - table: "ApiResourceClaims", - column: "ApiResourceId"); - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/ConfigurationDb/20240325172037_net8upgrade.Designer.cs b/archive/SecurityService.SqlServerMigrations/ConfigurationDb/20240325172037_net8upgrade.Designer.cs deleted file mode 100644 index c9fb772f..00000000 --- a/archive/SecurityService.SqlServerMigrations/ConfigurationDb/20240325172037_net8upgrade.Designer.cs +++ /dev/null @@ -1,1116 +0,0 @@ -// -using System; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace SecurityService.SqlServerMigrations.ConfigurationDb -{ - [DbContext(typeof(ConfigurationDbContext))] - [Migration("20240325172037_net8upgrade")] - partial class net8upgrade - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("AllowedAccessTokenSigningAlgorithms") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("LastAccessed") - .HasColumnType("datetime2"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("RequireResourceIndicator") - .HasColumnType("bit"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("bit"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiResources", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId", "Type") - .IsUnique(); - - b.ToTable("ApiResourceClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId", "Key") - .IsUnique(); - - b.ToTable("ApiResourceProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Scope") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId", "Scope") - .IsUnique(); - - b.ToTable("ApiResourceScopes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(4000) - .HasColumnType("nvarchar(4000)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiResourceSecrets", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Emphasize") - .HasColumnType("bit"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("LastAccessed") - .HasColumnType("datetime2"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("Required") - .HasColumnType("bit"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("bit"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiScopes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ScopeId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ScopeId", "Type") - .IsUnique(); - - b.ToTable("ApiScopeClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("ScopeId") - .HasColumnType("int"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ScopeId", "Key") - .IsUnique(); - - b.ToTable("ApiScopeProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("AbsoluteRefreshTokenLifetime") - .HasColumnType("int"); - - b.Property("AccessTokenLifetime") - .HasColumnType("int"); - - b.Property("AccessTokenType") - .HasColumnType("int"); - - b.Property("AllowAccessTokensViaBrowser") - .HasColumnType("bit"); - - b.Property("AllowOfflineAccess") - .HasColumnType("bit"); - - b.Property("AllowPlainTextPkce") - .HasColumnType("bit"); - - b.Property("AllowRememberConsent") - .HasColumnType("bit"); - - b.Property("AllowedIdentityTokenSigningAlgorithms") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("AlwaysIncludeUserClaimsInIdToken") - .HasColumnType("bit"); - - b.Property("AlwaysSendClientClaims") - .HasColumnType("bit"); - - b.Property("AuthorizationCodeLifetime") - .HasColumnType("int"); - - b.Property("BackChannelLogoutSessionRequired") - .HasColumnType("bit"); - - b.Property("BackChannelLogoutUri") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("CibaLifetime") - .HasColumnType("int"); - - b.Property("ClientClaimsPrefix") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientUri") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("ConsentLifetime") - .HasColumnType("int"); - - b.Property("CoordinateLifetimeWithUserSession") - .HasColumnType("bit"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("DPoPClockSkew") - .HasColumnType("time"); - - b.Property("DPoPValidationMode") - .HasColumnType("int"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("DeviceCodeLifetime") - .HasColumnType("int"); - - b.Property("EnableLocalLogin") - .HasColumnType("bit"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("FrontChannelLogoutSessionRequired") - .HasColumnType("bit"); - - b.Property("FrontChannelLogoutUri") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("IdentityTokenLifetime") - .HasColumnType("int"); - - b.Property("IncludeJwtId") - .HasColumnType("bit"); - - b.Property("InitiateLoginUri") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("LastAccessed") - .HasColumnType("datetime2"); - - b.Property("LogoUri") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("PairWiseSubjectSalt") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("PollingInterval") - .HasColumnType("int"); - - b.Property("ProtocolType") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("PushedAuthorizationLifetime") - .HasColumnType("int"); - - b.Property("RefreshTokenExpiration") - .HasColumnType("int"); - - b.Property("RefreshTokenUsage") - .HasColumnType("int"); - - b.Property("RequireClientSecret") - .HasColumnType("bit"); - - b.Property("RequireConsent") - .HasColumnType("bit"); - - b.Property("RequireDPoP") - .HasColumnType("bit"); - - b.Property("RequirePkce") - .HasColumnType("bit"); - - b.Property("RequirePushedAuthorization") - .HasColumnType("bit"); - - b.Property("RequireRequestObject") - .HasColumnType("bit"); - - b.Property("SlidingRefreshTokenLifetime") - .HasColumnType("int"); - - b.Property("UpdateAccessTokenClaimsOnRefresh") - .HasColumnType("bit"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.Property("UserCodeType") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("UserSsoLifetime") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ClientId") - .IsUnique(); - - b.ToTable("Clients", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Type", "Value") - .IsUnique(); - - b.ToTable("ClientClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Origin") - .IsRequired() - .HasMaxLength(150) - .HasColumnType("nvarchar(150)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Origin") - .IsUnique(); - - b.ToTable("ClientCorsOrigins", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("GrantType") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "GrantType") - .IsUnique(); - - b.ToTable("ClientGrantTypes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Provider") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Provider") - .IsUnique(); - - b.ToTable("ClientIdPRestrictions", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("PostLogoutRedirectUri") - .IsRequired() - .HasMaxLength(400) - .HasColumnType("nvarchar(400)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "PostLogoutRedirectUri") - .IsUnique(); - - b.ToTable("ClientPostLogoutRedirectUris", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Key") - .IsUnique(); - - b.ToTable("ClientProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("RedirectUri") - .IsRequired() - .HasMaxLength(400) - .HasColumnType("nvarchar(400)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "RedirectUri") - .IsUnique(); - - b.ToTable("ClientRedirectUris", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Scope") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Scope") - .IsUnique(); - - b.ToTable("ClientScopes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(4000) - .HasColumnType("nvarchar(4000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientSecrets", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityProvider", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("LastAccessed") - .HasColumnType("datetime2"); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("Properties") - .HasColumnType("nvarchar(max)"); - - b.Property("Scheme") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("nvarchar(20)"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("Scheme") - .IsUnique(); - - b.ToTable("IdentityProviders", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Emphasize") - .HasColumnType("bit"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("Required") - .HasColumnType("bit"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("bit"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("IdentityResources", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("IdentityResourceId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId", "Type") - .IsUnique(); - - b.ToTable("IdentityResourceClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("IdentityResourceId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId", "Key") - .IsUnique(); - - b.ToTable("IdentityResourceProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Properties") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Scopes") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Secrets") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") - .WithMany("UserClaims") - .HasForeignKey("ScopeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Scope"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") - .WithMany("Properties") - .HasForeignKey("ScopeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Scope"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("Claims") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedCorsOrigins") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedGrantTypes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("IdentityProviderRestrictions") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("PostLogoutRedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("Properties") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("RedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedScopes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("ClientSecrets") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("UserClaims") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("IdentityResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("Properties") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("IdentityResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => - { - b.Navigation("Properties"); - - b.Navigation("Scopes"); - - b.Navigation("Secrets"); - - b.Navigation("UserClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => - { - b.Navigation("Properties"); - - b.Navigation("UserClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => - { - b.Navigation("AllowedCorsOrigins"); - - b.Navigation("AllowedGrantTypes"); - - b.Navigation("AllowedScopes"); - - b.Navigation("Claims"); - - b.Navigation("ClientSecrets"); - - b.Navigation("IdentityProviderRestrictions"); - - b.Navigation("PostLogoutRedirectUris"); - - b.Navigation("Properties"); - - b.Navigation("RedirectUris"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => - { - b.Navigation("Properties"); - - b.Navigation("UserClaims"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/ConfigurationDb/20240325172037_net8upgrade.cs b/archive/SecurityService.SqlServerMigrations/ConfigurationDb/20240325172037_net8upgrade.cs deleted file mode 100644 index f3b95917..00000000 --- a/archive/SecurityService.SqlServerMigrations/ConfigurationDb/20240325172037_net8upgrade.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace SecurityService.SqlServerMigrations.ConfigurationDb -{ - /// - public partial class net8upgrade : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "DPoPClockSkew", - table: "Clients", - type: "time", - nullable: false, - defaultValue: new TimeSpan(0, 0, 0, 0, 0)); - - migrationBuilder.AddColumn( - name: "DPoPValidationMode", - table: "Clients", - type: "int", - nullable: false, - defaultValue: 0); - - migrationBuilder.AddColumn( - name: "InitiateLoginUri", - table: "Clients", - type: "nvarchar(2000)", - maxLength: 2000, - nullable: true); - - migrationBuilder.AddColumn( - name: "PushedAuthorizationLifetime", - table: "Clients", - type: "int", - nullable: true); - - migrationBuilder.AddColumn( - name: "RequireDPoP", - table: "Clients", - type: "bit", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "RequirePushedAuthorization", - table: "Clients", - type: "bit", - nullable: false, - defaultValue: false); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "DPoPClockSkew", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "DPoPValidationMode", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "InitiateLoginUri", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "PushedAuthorizationLifetime", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "RequireDPoP", - table: "Clients"); - - migrationBuilder.DropColumn( - name: "RequirePushedAuthorization", - table: "Clients"); - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs b/archive/SecurityService.SqlServerMigrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs deleted file mode 100644 index fa2c093d..00000000 --- a/archive/SecurityService.SqlServerMigrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs +++ /dev/null @@ -1,1113 +0,0 @@ -// -using System; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace SecurityService.SqlServerMigrations.ConfigurationDb -{ - [DbContext(typeof(ConfigurationDbContext))] - partial class ConfigurationDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("AllowedAccessTokenSigningAlgorithms") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("LastAccessed") - .HasColumnType("datetime2"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("RequireResourceIndicator") - .HasColumnType("bit"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("bit"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiResources", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId", "Type") - .IsUnique(); - - b.ToTable("ApiResourceClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId", "Key") - .IsUnique(); - - b.ToTable("ApiResourceProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Scope") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId", "Scope") - .IsUnique(); - - b.ToTable("ApiResourceScopes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ApiResourceId") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(4000) - .HasColumnType("nvarchar(4000)"); - - b.HasKey("Id"); - - b.HasIndex("ApiResourceId"); - - b.ToTable("ApiResourceSecrets", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Emphasize") - .HasColumnType("bit"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("LastAccessed") - .HasColumnType("datetime2"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("Required") - .HasColumnType("bit"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("bit"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("ApiScopes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ScopeId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ScopeId", "Type") - .IsUnique(); - - b.ToTable("ApiScopeClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("ScopeId") - .HasColumnType("int"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ScopeId", "Key") - .IsUnique(); - - b.ToTable("ApiScopeProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("AbsoluteRefreshTokenLifetime") - .HasColumnType("int"); - - b.Property("AccessTokenLifetime") - .HasColumnType("int"); - - b.Property("AccessTokenType") - .HasColumnType("int"); - - b.Property("AllowAccessTokensViaBrowser") - .HasColumnType("bit"); - - b.Property("AllowOfflineAccess") - .HasColumnType("bit"); - - b.Property("AllowPlainTextPkce") - .HasColumnType("bit"); - - b.Property("AllowRememberConsent") - .HasColumnType("bit"); - - b.Property("AllowedIdentityTokenSigningAlgorithms") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("AlwaysIncludeUserClaimsInIdToken") - .HasColumnType("bit"); - - b.Property("AlwaysSendClientClaims") - .HasColumnType("bit"); - - b.Property("AuthorizationCodeLifetime") - .HasColumnType("int"); - - b.Property("BackChannelLogoutSessionRequired") - .HasColumnType("bit"); - - b.Property("BackChannelLogoutUri") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("CibaLifetime") - .HasColumnType("int"); - - b.Property("ClientClaimsPrefix") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientUri") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("ConsentLifetime") - .HasColumnType("int"); - - b.Property("CoordinateLifetimeWithUserSession") - .HasColumnType("bit"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("DPoPClockSkew") - .HasColumnType("time"); - - b.Property("DPoPValidationMode") - .HasColumnType("int"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("DeviceCodeLifetime") - .HasColumnType("int"); - - b.Property("EnableLocalLogin") - .HasColumnType("bit"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("FrontChannelLogoutSessionRequired") - .HasColumnType("bit"); - - b.Property("FrontChannelLogoutUri") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("IdentityTokenLifetime") - .HasColumnType("int"); - - b.Property("IncludeJwtId") - .HasColumnType("bit"); - - b.Property("InitiateLoginUri") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("LastAccessed") - .HasColumnType("datetime2"); - - b.Property("LogoUri") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("PairWiseSubjectSalt") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("PollingInterval") - .HasColumnType("int"); - - b.Property("ProtocolType") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("PushedAuthorizationLifetime") - .HasColumnType("int"); - - b.Property("RefreshTokenExpiration") - .HasColumnType("int"); - - b.Property("RefreshTokenUsage") - .HasColumnType("int"); - - b.Property("RequireClientSecret") - .HasColumnType("bit"); - - b.Property("RequireConsent") - .HasColumnType("bit"); - - b.Property("RequireDPoP") - .HasColumnType("bit"); - - b.Property("RequirePkce") - .HasColumnType("bit"); - - b.Property("RequirePushedAuthorization") - .HasColumnType("bit"); - - b.Property("RequireRequestObject") - .HasColumnType("bit"); - - b.Property("SlidingRefreshTokenLifetime") - .HasColumnType("int"); - - b.Property("UpdateAccessTokenClaimsOnRefresh") - .HasColumnType("bit"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.Property("UserCodeType") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("UserSsoLifetime") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ClientId") - .IsUnique(); - - b.ToTable("Clients", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Type", "Value") - .IsUnique(); - - b.ToTable("ClientClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Origin") - .IsRequired() - .HasMaxLength(150) - .HasColumnType("nvarchar(150)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Origin") - .IsUnique(); - - b.ToTable("ClientCorsOrigins", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("GrantType") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "GrantType") - .IsUnique(); - - b.ToTable("ClientGrantTypes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Provider") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Provider") - .IsUnique(); - - b.ToTable("ClientIdPRestrictions", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("PostLogoutRedirectUri") - .IsRequired() - .HasMaxLength(400) - .HasColumnType("nvarchar(400)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "PostLogoutRedirectUri") - .IsUnique(); - - b.ToTable("ClientPostLogoutRedirectUris", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Key") - .IsUnique(); - - b.ToTable("ClientProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("RedirectUri") - .IsRequired() - .HasMaxLength(400) - .HasColumnType("nvarchar(400)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "RedirectUri") - .IsUnique(); - - b.ToTable("ClientRedirectUris", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Scope") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId", "Scope") - .IsUnique(); - - b.ToTable("ClientScopes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .HasColumnType("int"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(4000) - .HasColumnType("nvarchar(4000)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId"); - - b.ToTable("ClientSecrets", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityProvider", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("LastAccessed") - .HasColumnType("datetime2"); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("Properties") - .HasColumnType("nvarchar(max)"); - - b.Property("Scheme") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("nvarchar(20)"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("Scheme") - .IsUnique(); - - b.ToTable("IdentityProviders", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Description") - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("DisplayName") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Emphasize") - .HasColumnType("bit"); - - b.Property("Enabled") - .HasColumnType("bit"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("NonEditable") - .HasColumnType("bit"); - - b.Property("Required") - .HasColumnType("bit"); - - b.Property("ShowInDiscoveryDocument") - .HasColumnType("bit"); - - b.Property("Updated") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("IdentityResources", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("IdentityResourceId") - .HasColumnType("int"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId", "Type") - .IsUnique(); - - b.ToTable("IdentityResourceClaims", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("IdentityResourceId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(250) - .HasColumnType("nvarchar(250)"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000) - .HasColumnType("nvarchar(2000)"); - - b.HasKey("Id"); - - b.HasIndex("IdentityResourceId", "Key") - .IsUnique(); - - b.ToTable("IdentityResourceProperties", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Properties") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceScope", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Scopes") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResourceSecret", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiResource", "ApiResource") - .WithMany("Secrets") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("ApiResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") - .WithMany("UserClaims") - .HasForeignKey("ScopeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Scope"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScopeProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.ApiScope", "Scope") - .WithMany("Properties") - .HasForeignKey("ScopeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Scope"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("Claims") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientCorsOrigin", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedCorsOrigins") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientGrantType", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedGrantTypes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientIdPRestriction", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("IdentityProviderRestrictions") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("PostLogoutRedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("Properties") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientRedirectUri", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("RedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientScope", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("AllowedScopes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ClientSecret", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.Client", "Client") - .WithMany("ClientSecrets") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Client"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceClaim", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("UserClaims") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("IdentityResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResourceProperty", b => - { - b.HasOne("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", "IdentityResource") - .WithMany("Properties") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("IdentityResource"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiResource", b => - { - b.Navigation("Properties"); - - b.Navigation("Scopes"); - - b.Navigation("Secrets"); - - b.Navigation("UserClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ApiScope", b => - { - b.Navigation("Properties"); - - b.Navigation("UserClaims"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Client", b => - { - b.Navigation("AllowedCorsOrigins"); - - b.Navigation("AllowedGrantTypes"); - - b.Navigation("AllowedScopes"); - - b.Navigation("Claims"); - - b.Navigation("ClientSecrets"); - - b.Navigation("IdentityProviderRestrictions"); - - b.Navigation("PostLogoutRedirectUris"); - - b.Navigation("Properties"); - - b.Navigation("RedirectUris"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.IdentityResource", b => - { - b.Navigation("Properties"); - - b.Navigation("UserClaims"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/20211201220323_InitialCreate.Designer.cs b/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/20211201220323_InitialCreate.Designer.cs deleted file mode 100644 index 02714ba0..00000000 --- a/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/20211201220323_InitialCreate.Designer.cs +++ /dev/null @@ -1,167 +0,0 @@ -// -using System; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace SecurityService.SqlServerMigrations.PersistedGrantDb -{ - [DbContext(typeof(PersistedGrantDbContext))] - [Migration("20211201220323_InitialCreate")] - partial class InitialCreate - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.12") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("DeviceCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("Algorithm") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("DataProtected") - .HasColumnType("bit"); - - b.Property("IsX509Certificate") - .HasColumnType("bit"); - - b.Property("Use") - .HasColumnType("nvarchar(450)"); - - b.Property("Version") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("Use"); - - b.ToTable("Keys"); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ConsumedTime") - .HasColumnType("datetime2"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.HasKey("Key"); - - b.HasIndex("ConsumedTime"); - - b.HasIndex("Expiration"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.HasIndex("SubjectId", "SessionId", "Type"); - - b.ToTable("PersistedGrants"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/20211201220323_InitialCreate.cs b/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/20211201220323_InitialCreate.cs deleted file mode 100644 index 1dad880a..00000000 --- a/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/20211201220323_InitialCreate.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace SecurityService.SqlServerMigrations.PersistedGrantDb -{ - public partial class InitialCreate : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "DeviceCodes", - columns: table => new - { - UserCode = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - DeviceCode = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - SubjectId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - SessionId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Description = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - CreationTime = table.Column(type: "datetime2", nullable: false), - Expiration = table.Column(type: "datetime2", nullable: false), - Data = table.Column(type: "nvarchar(max)", maxLength: 50000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_DeviceCodes", x => x.UserCode); - }); - - migrationBuilder.CreateTable( - name: "Keys", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Version = table.Column(type: "int", nullable: false), - Created = table.Column(type: "datetime2", nullable: false), - Use = table.Column(type: "nvarchar(450)", nullable: true), - Algorithm = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), - IsX509Certificate = table.Column(type: "bit", nullable: false), - DataProtected = table.Column(type: "bit", nullable: false), - Data = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Keys", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "PersistedGrants", - columns: table => new - { - Key = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), - SubjectId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - SessionId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), - Description = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - CreationTime = table.Column(type: "datetime2", nullable: false), - Expiration = table.Column(type: "datetime2", nullable: true), - ConsumedTime = table.Column(type: "datetime2", nullable: true), - Data = table.Column(type: "nvarchar(max)", maxLength: 50000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_PersistedGrants", x => x.Key); - }); - - migrationBuilder.CreateIndex( - name: "IX_DeviceCodes_DeviceCode", - table: "DeviceCodes", - column: "DeviceCode", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_DeviceCodes_Expiration", - table: "DeviceCodes", - column: "Expiration"); - - migrationBuilder.CreateIndex( - name: "IX_Keys_Use", - table: "Keys", - column: "Use"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_ConsumedTime", - table: "PersistedGrants", - column: "ConsumedTime"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_Expiration", - table: "PersistedGrants", - column: "Expiration"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_SubjectId_ClientId_Type", - table: "PersistedGrants", - columns: new[] { "SubjectId", "ClientId", "Type" }); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_SubjectId_SessionId_Type", - table: "PersistedGrants", - columns: new[] { "SubjectId", "SessionId", "Type" }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "DeviceCodes"); - - migrationBuilder.DropTable( - name: "Keys"); - - migrationBuilder.DropTable( - name: "PersistedGrants"); - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/20220609181900_Net6Update.Designer.cs b/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/20220609181900_Net6Update.Designer.cs deleted file mode 100644 index 4ac97fbb..00000000 --- a/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/20220609181900_Net6Update.Designer.cs +++ /dev/null @@ -1,240 +0,0 @@ -// -using System; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace SecurityService.SqlServerMigrations.PersistedGrantDb -{ - [DbContext(typeof(PersistedGrantDbContext))] - [Migration("20220609181900_Net6Update")] - partial class Net6Update - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "6.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("DeviceCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("Algorithm") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("DataProtected") - .HasColumnType("bit"); - - b.Property("IsX509Certificate") - .HasColumnType("bit"); - - b.Property("Use") - .HasColumnType("nvarchar(450)"); - - b.Property("Version") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("Use"); - - b.ToTable("Keys", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ConsumedTime") - .HasColumnType("datetime2"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.HasKey("Id"); - - b.HasIndex("ConsumedTime"); - - b.HasIndex("Expiration"); - - b.HasIndex("Key") - .IsUnique() - .HasFilter("[Key] IS NOT NULL"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.HasIndex("SubjectId", "SessionId", "Type"); - - b.ToTable("PersistedGrants", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ServerSideSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("DisplayName") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Expires") - .HasColumnType("datetime2"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Renewed") - .HasColumnType("datetime2"); - - b.Property("Scheme") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.HasKey("Id"); - - b.HasIndex("DisplayName"); - - b.HasIndex("Expires"); - - b.HasIndex("Key") - .IsUnique(); - - b.HasIndex("SessionId"); - - b.HasIndex("SubjectId"); - - b.ToTable("ServerSideSessions", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/20220609181900_Net6Update.cs b/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/20220609181900_Net6Update.cs deleted file mode 100644 index d7f9a46a..00000000 --- a/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/20220609181900_Net6Update.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace SecurityService.SqlServerMigrations.PersistedGrantDb -{ - public partial class Net6Update : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - name: "PK_PersistedGrants", - table: "PersistedGrants"); - - migrationBuilder.AlterColumn( - name: "Key", - table: "PersistedGrants", - type: "nvarchar(200)", - maxLength: 200, - nullable: true, - oldClrType: typeof(string), - oldType: "nvarchar(200)", - oldMaxLength: 200); - - migrationBuilder.AddColumn( - name: "Id", - table: "PersistedGrants", - type: "bigint", - nullable: false, - defaultValue: 0L) - .Annotation("SqlServer:Identity", "1, 1"); - - migrationBuilder.AddPrimaryKey( - name: "PK_PersistedGrants", - table: "PersistedGrants", - column: "Id"); - - migrationBuilder.CreateTable( - name: "ServerSideSessions", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Key = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), - Scheme = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), - SubjectId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), - SessionId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - DisplayName = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - Renewed = table.Column(type: "datetime2", nullable: false), - Expires = table.Column(type: "datetime2", nullable: true), - Data = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ServerSideSessions", x => x.Id); - }); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_Key", - table: "PersistedGrants", - column: "Key", - unique: true, - filter: "[Key] IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "IX_ServerSideSessions_DisplayName", - table: "ServerSideSessions", - column: "DisplayName"); - - migrationBuilder.CreateIndex( - name: "IX_ServerSideSessions_Expires", - table: "ServerSideSessions", - column: "Expires"); - - migrationBuilder.CreateIndex( - name: "IX_ServerSideSessions_Key", - table: "ServerSideSessions", - column: "Key", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ServerSideSessions_SessionId", - table: "ServerSideSessions", - column: "SessionId"); - - migrationBuilder.CreateIndex( - name: "IX_ServerSideSessions_SubjectId", - table: "ServerSideSessions", - column: "SubjectId"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "ServerSideSessions"); - - migrationBuilder.DropPrimaryKey( - name: "PK_PersistedGrants", - table: "PersistedGrants"); - - migrationBuilder.DropIndex( - name: "IX_PersistedGrants_Key", - table: "PersistedGrants"); - - migrationBuilder.DropColumn( - name: "Id", - table: "PersistedGrants"); - - migrationBuilder.AlterColumn( - name: "Key", - table: "PersistedGrants", - type: "nvarchar(200)", - maxLength: 200, - nullable: false, - defaultValue: "", - oldClrType: typeof(string), - oldType: "nvarchar(200)", - oldMaxLength: 200, - oldNullable: true); - - migrationBuilder.AddPrimaryKey( - name: "PK_PersistedGrants", - table: "PersistedGrants", - column: "Key"); - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/20240325172049_net8upgrade.Designer.cs b/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/20240325172049_net8upgrade.Designer.cs deleted file mode 100644 index 757ea902..00000000 --- a/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/20240325172049_net8upgrade.Designer.cs +++ /dev/null @@ -1,271 +0,0 @@ -// -using System; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace SecurityService.SqlServerMigrations.PersistedGrantDb -{ - [DbContext(typeof(PersistedGrantDbContext))] - [Migration("20240325172049_net8upgrade")] - partial class net8upgrade - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("DeviceCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("Algorithm") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("DataProtected") - .HasColumnType("bit"); - - b.Property("IsX509Certificate") - .HasColumnType("bit"); - - b.Property("Use") - .HasColumnType("nvarchar(450)"); - - b.Property("Version") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("Use"); - - b.ToTable("Keys", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ConsumedTime") - .HasColumnType("datetime2"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.HasKey("Id"); - - b.HasIndex("ConsumedTime"); - - b.HasIndex("Expiration"); - - b.HasIndex("Key") - .IsUnique() - .HasFilter("[Key] IS NOT NULL"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.HasIndex("SubjectId", "SessionId", "Type"); - - b.ToTable("PersistedGrants", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PushedAuthorizationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ExpiresAtUtc") - .HasColumnType("datetime2"); - - b.Property("Parameters") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ReferenceValueHash") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.HasKey("Id"); - - b.HasIndex("ExpiresAtUtc"); - - b.HasIndex("ReferenceValueHash") - .IsUnique(); - - b.ToTable("PushedAuthorizationRequests", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ServerSideSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("DisplayName") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Expires") - .HasColumnType("datetime2"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Renewed") - .HasColumnType("datetime2"); - - b.Property("Scheme") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.HasKey("Id"); - - b.HasIndex("DisplayName"); - - b.HasIndex("Expires"); - - b.HasIndex("Key") - .IsUnique(); - - b.HasIndex("SessionId"); - - b.HasIndex("SubjectId"); - - b.ToTable("ServerSideSessions", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/20240325172049_net8upgrade.cs b/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/20240325172049_net8upgrade.cs deleted file mode 100644 index 4d8bb137..00000000 --- a/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/20240325172049_net8upgrade.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace SecurityService.SqlServerMigrations.PersistedGrantDb -{ - /// - public partial class net8upgrade : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder){ - migrationBuilder.DropPrimaryKey("PK_ServerSideSessions", "ServerSideSessions"); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ServerSideSessions", - type: "bigint", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("SqlServer:Identity", "1, 1") - .OldAnnotation("SqlServer:Identity", "1, 1"); - - migrationBuilder.AddPrimaryKey("PK_ServerSideSessions", "ServerSideSessions","Id"); - - migrationBuilder.CreateTable( - name: "PushedAuthorizationRequests", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ReferenceValueHash = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), - ExpiresAtUtc = table.Column(type: "datetime2", nullable: false), - Parameters = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_PushedAuthorizationRequests", x => x.Id); - }); - - migrationBuilder.CreateIndex( - name: "IX_PushedAuthorizationRequests_ExpiresAtUtc", - table: "PushedAuthorizationRequests", - column: "ExpiresAtUtc"); - - migrationBuilder.CreateIndex( - name: "IX_PushedAuthorizationRequests_ReferenceValueHash", - table: "PushedAuthorizationRequests", - column: "ReferenceValueHash", - unique: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "PushedAuthorizationRequests"); - - migrationBuilder.AlterColumn( - name: "Id", - table: "ServerSideSessions", - type: "int", - nullable: false, - oldClrType: typeof(long), - oldType: "bigint") - .Annotation("SqlServer:Identity", "1, 1") - .OldAnnotation("SqlServer:Identity", "1, 1"); - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/PersistedGrantDbContextModelSnapshot.cs b/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/PersistedGrantDbContextModelSnapshot.cs deleted file mode 100644 index 111ab5ce..00000000 --- a/archive/SecurityService.SqlServerMigrations/PersistedGrantDb/PersistedGrantDbContextModelSnapshot.cs +++ /dev/null @@ -1,268 +0,0 @@ -// -using System; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace SecurityService.SqlServerMigrations.PersistedGrantDb -{ - [DbContext(typeof(PersistedGrantDbContext))] - partial class PersistedGrantDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("DeviceCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("datetime2"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("Algorithm") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("DataProtected") - .HasColumnType("bit"); - - b.Property("IsX509Certificate") - .HasColumnType("bit"); - - b.Property("Use") - .HasColumnType("nvarchar(450)"); - - b.Property("Version") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("Use"); - - b.ToTable("Keys", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("ConsumedTime") - .HasColumnType("datetime2"); - - b.Property("CreationTime") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasMaxLength(50000) - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("Key") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.HasKey("Id"); - - b.HasIndex("ConsumedTime"); - - b.HasIndex("Expiration"); - - b.HasIndex("Key") - .IsUnique() - .HasFilter("[Key] IS NOT NULL"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.HasIndex("SubjectId", "SessionId", "Type"); - - b.ToTable("PersistedGrants", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PushedAuthorizationRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ExpiresAtUtc") - .HasColumnType("datetime2"); - - b.Property("Parameters") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ReferenceValueHash") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.HasKey("Id"); - - b.HasIndex("ExpiresAtUtc"); - - b.HasIndex("ReferenceValueHash") - .IsUnique(); - - b.ToTable("PushedAuthorizationRequests", (string)null); - }); - - modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.ServerSideSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("DisplayName") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Expires") - .HasColumnType("datetime2"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Renewed") - .HasColumnType("datetime2"); - - b.Property("Scheme") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SessionId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("SubjectId") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.HasKey("Id"); - - b.HasIndex("DisplayName"); - - b.HasIndex("Expires"); - - b.HasIndex("Key") - .IsUnique(); - - b.HasIndex("SessionId"); - - b.HasIndex("SubjectId"); - - b.ToTable("ServerSideSessions", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/archive/SecurityService.SqlServerMigrations/SecurityService.SqlServerMigrations.csproj b/archive/SecurityService.SqlServerMigrations/SecurityService.SqlServerMigrations.csproj deleted file mode 100644 index 0902cb19..00000000 --- a/archive/SecurityService.SqlServerMigrations/SecurityService.SqlServerMigrations.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - net10.0 - None - - - - - - - - - - - - - diff --git a/archive/SecurityService.UnitTests/BootstrapperTests.cs b/archive/SecurityService.UnitTests/BootstrapperTests.cs deleted file mode 100644 index 3854dcb8..00000000 --- a/archive/SecurityService.UnitTests/BootstrapperTests.cs +++ /dev/null @@ -1,103 +0,0 @@ -namespace SecurityService.UnitTests -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using Duende.IdentityServer.Services; - using Duende.IdentityServer.Stores; - using Lamar; - using Microsoft.AspNetCore.Authentication; - using Microsoft.AspNetCore.DataProtection; - using Microsoft.AspNetCore.Hosting; - using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Identity; - using Microsoft.AspNetCore.Identity.EntityFrameworkCore; - using Microsoft.AspNetCore.Mvc; - using Microsoft.EntityFrameworkCore; - using Microsoft.Extensions.Configuration; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.Logging; - using Microsoft.Extensions.Options; - using Moq; - using Xunit; - - public class BootstrapperTests - { - [Fact(Skip = ":|")] - public void VerifyBootstrapperIsValid() - { - Mock hostingEnvironment = new Mock(); - hostingEnvironment.Setup(he => he.EnvironmentName).Returns("Development"); - hostingEnvironment.Setup(he => he.ContentRootPath).Returns("/home"); - hostingEnvironment.Setup(he => he.ApplicationName).Returns("Test Application"); - - ServiceRegistry services = new ServiceRegistry(); - Startup s = new Startup(hostingEnvironment.Object); - Startup.Configuration = this.SetupMemoryConfiguration(); - - this.AddTestRegistrations(services, hostingEnvironment.Object); - s.ConfigureContainer(services); - Startup.GetContainer().AssertConfigurationIsValid(); - } - - private IConfigurationRoot SetupMemoryConfiguration() - { - Dictionary configuration = new Dictionary(); - configuration.Add("ConnectionStrings:PersistedGrantDbContext", "server=127.0.0.1;database=PersistedGrantStore;user id=sa;password=Sc0tland"); - configuration.Add("ConnectionStrings:ConfigurationDbContext", "server=127.0.0.1;database=PersistedGrantStore;user id=sa;password=Sc0tland"); - configuration.Add("ConnectionStrings:AuthenticationDbContext", "server=127.0.0.1;database=PersistedGrantStore;user id=sa;password=Sc0tland"); - configuration.Add("AppSettings:MessagingServiceApi", "http://127.0.0.1"); - configuration.Add("AppSettings:DatabaseEngine", "SqlServer"); - configuration.Add("ServiceOptions:UseInMemoryDatabase", "true"); - - IConfigurationBuilder builder = new ConfigurationBuilder(); - builder.AddInMemoryCollection(configuration); - - return builder.Build(); - } - - private void AddTestRegistrations(ServiceRegistry serviceRegistry, - IWebHostEnvironment hostingEnvironment) - { - Mock service = new Mock(); - - serviceRegistry.For().Use(service.Object); - serviceRegistry.For().Use(); - serviceRegistry.For>().Use>(); - serviceRegistry.For().Use(); - serviceRegistry.For().Use(); - serviceRegistry.For().Use(); - serviceRegistry.For().Use(); - serviceRegistry.For().Use>(); - serviceRegistry.For().Use(); - serviceRegistry.For>>().Use>>(); - serviceRegistry.For>().Use>(); - serviceRegistry.For>>().Use>>(); - serviceRegistry.For().Use(); - serviceRegistry.For>>().Use>>(); - serviceRegistry.For>().Use>(); - serviceRegistry.For>().Use>(); - serviceRegistry.For>().Use>(); - serviceRegistry.For>().Use>(); - serviceRegistry.For>().Use>(); - serviceRegistry.For>().Use>(); - serviceRegistry.For>().Use>(); - serviceRegistry.For>().Use>(); - serviceRegistry.For>().Use>(); - serviceRegistry.For>().Use>(); - serviceRegistry.For>().Use>(); - //serviceRegistry.For>().Use>(); - //serviceRegistry.For>().Use>(); - //serviceRegistry.For>().Use>(); - //serviceRegistry.For>().Use>(); - - serviceRegistry.For>().Use>(); - - serviceRegistry.AddLogging(); - DiagnosticListener diagnosticSource = new DiagnosticListener(hostingEnvironment.ApplicationName); - serviceRegistry.AddSingleton(diagnosticSource); - serviceRegistry.AddSingleton(diagnosticSource); - serviceRegistry.AddSingleton(hostingEnvironment); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService.UnitTests/MediatorTests.cs b/archive/SecurityService.UnitTests/MediatorTests.cs deleted file mode 100644 index a4c5636a..00000000 --- a/archive/SecurityService.UnitTests/MediatorTests.cs +++ /dev/null @@ -1,173 +0,0 @@ -using Lamar; -using MediatR; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc.ApiExplorer; -using Microsoft.AspNetCore.Mvc.Infrastructure; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Moq; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using MessagingService.Client; -using MessagingService.DataTransferObjects; -using SimpleResults; -using Xunit; - -namespace SecurityService.UnitTests -{ - using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure; - using System.Diagnostics; - using System.IO; - using BusinessLogic.Requests; - using Duende.IdentityServer.EntityFramework.DbContexts; - using Microsoft.AspNetCore.Identity; - using Microsoft.EntityFrameworkCore; - using Microsoft.Extensions.Logging.Abstractions; - using Microsoft.Identity.Client; - using Swashbuckle.AspNetCore.Filters; - using SecurityService.BusinessLogic; - using SecurityService.Database.DbContexts; - using Duende.IdentityServer; - - public class MediatorTests - { - private List Requests = new List(); - - public MediatorTests(){ - this.Requests.Add(TestData.CreateApiResourceCommand); - this.Requests.Add(TestData.GetApiResourceQuery); - this.Requests.Add(TestData.GetApiResourcesQuery); - this.Requests.Add(TestData.CreateApiScopeCommand); - this.Requests.Add(TestData.GetApiScopeQuery); - this.Requests.Add(TestData.GetApiScopesQuery); - this.Requests.Add(TestData.CreateClientCommand); - this.Requests.Add(TestData.GetClientQuery); - this.Requests.Add(TestData.GetClientsQuery); - this.Requests.Add(TestData.CreateIdentityResourceCommand); - this.Requests.Add(TestData.GetIdentityResourceQuery); - this.Requests.Add(TestData.GetIdentityResourcesQuery); - this.Requests.Add(TestData.CreateUserCommand); - this.Requests.Add(TestData.GetUserQuery); - this.Requests.Add(TestData.GetUsersQuery); - this.Requests.Add(TestData.CreateRoleCommand); - this.Requests.Add(TestData.GetRoleQuery); - this.Requests.Add(TestData.GetRolesQuery); - this.Requests.Add(TestData.ChangeUserPasswordCommand); - this.Requests.Add(TestData.ConfirmUserEmailAddressCommand); - this.Requests.Add(TestData.ProcessPasswordResetConfirmationCommand); - this.Requests.Add(TestData.ProcessPasswordResetRequestCommand); - this.Requests.Add(TestData.SendWelcomeEmailCommand); - - Directory.CreateDirectory("D:\\home\\"); - } - - [Fact] - public async Task Mediator_Send_RequestHandled() - { - Shared.Logger.Logger.Initialise(NullLogger.Instance); - Mock hostingEnvironment = new Mock(); - hostingEnvironment.Setup(he => he.EnvironmentName).Returns("Development"); - hostingEnvironment.Setup(he => he.ContentRootPath).Returns("/home"); - hostingEnvironment.Setup(he => he.ApplicationName).Returns("Test Application"); - - ServiceRegistry services = new ServiceRegistry(); - Startup s = new Startup(hostingEnvironment.Object); - Startup.Configuration = this.SetupMemoryConfiguration(); - - this.AddTestRegistrations(services, hostingEnvironment.Object); - s.ConfigureContainer(services); - Container container = Startup.GetContainer(); - RoleManager authDb = container.GetInstance>(); - - List errors = new List(); - IMediator mediator = container.GetService(); - foreach (IBaseRequest baseRequest in this.Requests) - { - try - { - if (baseRequest is SecurityServiceCommands.CreateUserCommand || - baseRequest is SecurityServiceQueries.GetRoleQuery){ - await authDb.CreateAsync(new IdentityRole(TestData.RoleName)); - } - else{ - if (await authDb.RoleExistsAsync(TestData.RoleName)){ - IdentityRole roleToRemove = await authDb.Roles.SingleOrDefaultAsync(); - await authDb.DeleteAsync(roleToRemove); - } - } - - await mediator.Send(baseRequest); - } - catch (Exception ex) - { - errors.Add($"[{baseRequest.GetType()}] - {ex.Message}"); - } - } - - if (errors.Any() == true) - { - String errorMessage = String.Join(Environment.NewLine, errors); - throw new Exception(errorMessage); - } - } - - private IConfigurationRoot SetupMemoryConfiguration(){ - - Dictionary configuration = new Dictionary(); - - IConfigurationBuilder builder = new ConfigurationBuilder(); - - configuration.Add("AppSettings:DatabaseEngine", "SqlServer"); - configuration.Add("ConnectionStrings:PersistedGrantDbContext", "PersistedGrantDbContext"); - configuration.Add("ConnectionStrings:ConfigurationDbContext", "ConfigurationDbContext"); - configuration.Add("ConnectionStrings:AuthenticationDbContext", "AuthenticationDbContext"); - configuration.Add("AppSettings:MessagingServiceApi", "http://localhost"); - configuration.Add("ServiceOptions:PublicOrigin", "https://127.0.0.1:5001"); - configuration.Add("ServiceOptions:ClientId", "ClientId"); - configuration.Add("ServiceOptions:IssuerUrl", "https://127.0.0.1:5001"); - configuration.Add("ServiceOptions:UseInMemoryDatabase", "true"); - - builder.AddInMemoryCollection(configuration); - - return builder.Build(); - } - - private void AddTestRegistrations(ServiceRegistry services, - IWebHostEnvironment hostingEnvironment){ - - services.AddLogging(); - DiagnosticListener diagnosticSource = new DiagnosticListener(hostingEnvironment.ApplicationName); - services.AddSingleton(diagnosticSource); - services.AddSingleton(diagnosticSource); - services.AddSingleton(Startup.Configuration); - services.AddSingleton(hostingEnvironment); - services.AddSingleton(hostingEnvironment); - - services.OverrideServices(s => { - s.AddDbContext(builder => builder.UseInMemoryDatabase("Configuration"), ServiceLifetime.Singleton); - s.AddDbContext(builder => builder.UseInMemoryDatabase("PersistedGrantDb"), ServiceLifetime.Singleton); - s.AddDbContext(builder => builder.UseInMemoryDatabase("Authentication"), ServiceLifetime.Singleton); - s.AddSingleton(); - }); - } - } - - public class DummyMessagingServiceClient : IMessagingServiceClient { - public async Task SendEmail(String accessToken, - SendEmailRequest request, - CancellationToken cancellationToken) => Result.Success(); - - public async Task ResendEmail(String accessToken, - ResendEmailRequest request, - CancellationToken cancellationToken) => Result.Success(); - - public async Task SendSMS(String accessToken, - SendSMSRequest request, - CancellationToken cancellationToken) => Result.Success(); - } -} diff --git a/archive/SecurityService.UnitTests/ModelFactoryTests.cs b/archive/SecurityService.UnitTests/ModelFactoryTests.cs deleted file mode 100644 index 22ee1447..00000000 --- a/archive/SecurityService.UnitTests/ModelFactoryTests.cs +++ /dev/null @@ -1,491 +0,0 @@ -namespace SecurityService.UnitTests -{ - using System; - using System.Collections.Generic; - using System.Linq; - using DataTransferObjects.Responses; - using Duende.IdentityServer.Models; - using Factories; - using Shouldly; - using Xunit; - using RoleDetails = Models.RoleDetails; - using UserDetails = Models.UserDetails; - - public class ModelFactoryTests - { - #region Methods - - [Fact] - public void ModelFactory_ConvertFrom_ApiResource_ModelConverted() - { - ApiResource apiResourceModel = new ApiResource - { - Scopes = new List - { - TestData.AllowedScopes.First() - }, - Description = TestData.ApiResourceDescription, - Name = TestData.ApiResourceName, - DisplayName = TestData.ApiResourceDisplayName, - UserClaims = TestData.ApiResourceUserClaims, - Enabled = true - }; - - ApiResourceDetails apiResourceDto = ModelFactory.ConvertFrom(apiResourceModel); - - apiResourceDto.Scopes.First().ShouldBe(TestData.AllowedScopes.First()); - apiResourceDto.Description.ShouldBe(TestData.ApiResourceDescription); - apiResourceDto.DisplayName.ShouldBe(TestData.ApiResourceDisplayName); - apiResourceDto.Name.ShouldBe(TestData.ApiResourceName); - apiResourceDto.UserClaims.ShouldBe(TestData.ApiResourceUserClaims); - apiResourceDto.Enabled.ShouldBeTrue(); - } - - [Fact] - public void ModelFactory_ConvertFrom_ApiResource_ModelIsNull_NullReturned() - { - ApiResource apiResourceModel = null; - - ApiResourceDetails apiResourceDto = ModelFactory.ConvertFrom(apiResourceModel); - - apiResourceDto.ShouldBeNull(); - } - - [Fact] - public void ModelFactory_ConvertFrom_ApiScope_ModelConverted() - { - ApiScope apiScopeModel = new ApiScope - { - Description = TestData.ApiScopeDescription, - Name = TestData.ApiScopeName, - DisplayName = TestData.ApiScopeDisplayName, - Enabled = true - }; - - ApiScopeDetails apiScopeDto = ModelFactory.ConvertFrom(apiScopeModel); - - apiScopeDto.Description.ShouldBe(TestData.ApiScopeDescription); - apiScopeDto.DisplayName.ShouldBe(TestData.ApiScopeDisplayName); - apiScopeDto.Name.ShouldBe(TestData.ApiScopeName); - apiScopeDto.Enabled.ShouldBeTrue(); - } - - [Fact] - public void ModelFactory_ConvertFrom_ApiScope_ModelIsNull_NullReturned() - { - ApiScope apiScopeModel = null; - - ApiScopeDetails apiScopeDto = ModelFactory.ConvertFrom(apiScopeModel); - - apiScopeDto.ShouldBeNull(); - } - - [Fact] - public void ModelFactory_ConvertFrom_ApiResourceList_ListIsEmpty_NullReturned() - { - List apiResourceList = new List(); - - List apiResourceDtoList = ModelFactory.ConvertFrom(apiResourceList); - - apiResourceDtoList.ShouldBeEmpty(); - } - - [Fact] - public void ModelFactory_ConvertFrom_ApiResourceList_ListIsNull_NullReturned() - { - List apiResourceList = null; - - List apiResourceDtoList = ModelFactory.ConvertFrom(apiResourceList); - - apiResourceDtoList.ShouldBeEmpty(); - } - - [Fact] - public void ModelFactory_ConvertFrom_ApiResourceList_ModelsConverted() - { - ApiResource apiResourceModel = new ApiResource - { - Scopes = new List - { - TestData.AllowedScopes.First() - }, - Description = TestData.ApiResourceDescription, - Name = TestData.ApiResourceName, - DisplayName = TestData.ApiResourceDisplayName, - UserClaims = TestData.ApiResourceUserClaims, - Enabled = true - }; - - List apiResourceModelList = [ - apiResourceModel - ]; - - List apiResourceDtoList = ModelFactory.ConvertFrom(apiResourceModelList); - - apiResourceDtoList.ShouldNotBeNull(); - apiResourceDtoList.ShouldNotBeEmpty(); - apiResourceDtoList.Count.ShouldBe(apiResourceModelList.Count); - apiResourceDtoList.First().Scopes.First().ShouldBe(TestData.AllowedScopes.First()); - apiResourceDtoList.First().Description.ShouldBe(TestData.ApiResourceDescription); - apiResourceDtoList.First().DisplayName.ShouldBe(TestData.ApiResourceDisplayName); - apiResourceDtoList.First().Name.ShouldBe(TestData.ApiResourceName); - apiResourceDtoList.First().UserClaims.ShouldBe(TestData.ApiResourceUserClaims); - apiResourceDtoList.First().Enabled.ShouldBeTrue(); - } - - [Fact] - public void ModelFactory_ConvertFrom_ApiScopeList_ListIsEmpty_NullReturned() - { - List apiScopeList = new(); - - List apiScopeDtoList = ModelFactory.ConvertFrom(apiScopeList); - - apiScopeDtoList.ShouldBeEmpty(); - } - - [Fact] - public void ModelFactory_ConvertFrom_ApiScopeList_ListIsNull_NullReturned() - { - List apiScopeList = null; - - List apiScopeDtoList = ModelFactory.ConvertFrom(apiScopeList); - - apiScopeDtoList.ShouldBeEmpty(); - } - - [Fact] - public void ModelFactory_ConvertFrom_ApiScopeList_ModelsConverted() - { - ApiScope apiScopeModel = new ApiScope - { - Description = TestData.ApiScopeDescription, - Name = TestData.ApiScopeName, - DisplayName = TestData.ApiResourceDisplayName, - Enabled = true - }; - - List apiScopeModelList = [ - apiScopeModel - ]; - - List apiScopeDtoList = ModelFactory.ConvertFrom(apiScopeModelList); - - apiScopeDtoList.ShouldNotBeNull(); - apiScopeDtoList.ShouldNotBeEmpty(); - apiScopeDtoList.Count.ShouldBe(apiScopeModelList.Count); - apiScopeDtoList.First().Description.ShouldBe(TestData.ApiScopeDescription); - apiScopeDtoList.First().DisplayName.ShouldBe(TestData.ApiResourceDisplayName); - apiScopeDtoList.First().Name.ShouldBe(TestData.ApiScopeName); - apiScopeDtoList.First().Enabled.ShouldBeTrue(); - } - - [Fact] - public void ModelFactory_ConvertFrom_Client_ModelConverted() - { - Client clientModel = new Client - { - ClientId = TestData.ClientId, - ClientName = TestData.ClientName, - Description = TestData.ClientDescription, - AllowedGrantTypes = TestData.AllowedGrantTypes, - AllowedScopes = TestData.AllowedScopes, - Enabled = true - }; - - ClientDetails clientDto = ModelFactory.ConvertFrom(clientModel); - - clientDto.AllowedGrantTypes.ShouldBe(TestData.AllowedGrantTypes); - clientDto.AllowedScopes.ShouldBe(TestData.AllowedScopes); - clientDto.ClientDescription.ShouldBe(TestData.ClientDescription); - clientDto.ClientId.ShouldBe(TestData.ClientId); - clientDto.ClientName.ShouldBe(TestData.ClientName); - clientDto.Enabled.ShouldBeTrue(); - } - - [Fact] - public void ModelFactory_ConvertFrom_Client_ModelIsNull_NullReturned() - { - Client clientModel = null; - - ClientDetails clientDto = ModelFactory.ConvertFrom(clientModel); - - clientDto.ShouldBeNull(); - } - - [Fact] - public void ModelFactory_ConvertFrom_ClientList_ListIsEmpty_NullReturned() - { - List clientModelList = new(); - - List clientDtoList = ModelFactory.ConvertFrom(clientModelList); - - clientDtoList.ShouldBeEmpty(); - } - - [Fact] - public void ModelFactory_ConvertFrom_ClientList_ListIsNull_NullReturned() - { - List clientModelList = null; - - List clientDtoList = ModelFactory.ConvertFrom(clientModelList); - - clientDtoList.ShouldBeEmpty(); - } - - [Fact] - public void ModelFactory_ConvertFrom_ClientList_ModelsConverted() - { - Client clientModel = new Client - { - ClientId = TestData.ClientId, - ClientName = TestData.ClientName, - Description = TestData.ClientDescription, - AllowedGrantTypes = TestData.AllowedGrantTypes, - AllowedScopes = TestData.AllowedScopes, - Enabled = true - }; - List clientModelList = [ - clientModel - ]; - - List clientDtoList = ModelFactory.ConvertFrom(clientModelList); - - clientDtoList.ShouldNotBeNull(); - clientDtoList.ShouldNotBeEmpty(); - clientDtoList.Count.ShouldBe(clientModelList.Count); - clientDtoList.First().AllowedGrantTypes.ShouldBe(TestData.AllowedGrantTypes); - clientDtoList.First().AllowedScopes.ShouldBe(TestData.AllowedScopes); - clientDtoList.First().ClientDescription.ShouldBe(TestData.ClientDescription); - clientDtoList.First().ClientId.ShouldBe(TestData.ClientId); - clientDtoList.First().ClientName.ShouldBe(TestData.ClientName); - clientDtoList.First().Enabled.ShouldBeTrue(); - } - - [Fact] - public void ModelFactory_ConvertFrom_IdentityResource_ModelConverted() - { - IdentityResource identityResourceModel = new IdentityResource - { - Description = TestData.IdentityResourceDescription, - DisplayName = TestData.IdentityResourceDisplayName, - UserClaims = TestData.IdentityResourceUserClaims, - Emphasize = true, - ShowInDiscoveryDocument = true, - Required = true - }; - - IdentityResourceDetails identityResourceDto = ModelFactory.ConvertFrom(identityResourceModel); - - identityResourceDto.Description.ShouldBe(TestData.IdentityResourceDescription); - identityResourceDto.DisplayName.ShouldBe(TestData.IdentityResourceDisplayName); - identityResourceDto.Claims.ShouldBe(TestData.IdentityResourceUserClaims); - identityResourceDto.Emphasize.ShouldBeTrue(); - identityResourceDto.ShowInDiscoveryDocument.ShouldBeTrue(); - identityResourceDto.Required.ShouldBeTrue(); - } - - [Fact] - public void ModelFactory_ConvertFrom_IdentityResource_ModelIsNull_NullReturned() - { - IdentityResource identityResourceModel = null; - - IdentityResourceDetails identityResourceDto = ModelFactory.ConvertFrom(identityResourceModel); - - identityResourceDto.ShouldBeNull(); - } - - [Fact] - public void ModelFactory_ConvertFrom_IdentityResourceList_ListIsNull_NullReturned() - { - List identityResourceList = null; - - List identityResourceDtoList = ModelFactory.ConvertFrom(identityResourceList); - - identityResourceDtoList.ShouldBeEmpty(); - } - - [Fact] - public void ModelFactory_ConvertFrom_IdentityResourceList_ModelConverted() - { - IdentityResource identityResourceModel = new IdentityResource - { - Description = TestData.IdentityResourceDescription, - DisplayName = TestData.IdentityResourceDisplayName, - UserClaims = TestData.IdentityResourceUserClaims, - Emphasize = true, - ShowInDiscoveryDocument = true, - Required = true - }; - - List identityResourceModelList = [ - identityResourceModel - ]; - - List identityResourceDtoList = ModelFactory.ConvertFrom(identityResourceModelList); - - identityResourceDtoList.ShouldNotBeNull(); - identityResourceDtoList.ShouldNotBeEmpty(); - identityResourceDtoList.Count.ShouldBe(identityResourceModelList.Count); - identityResourceDtoList.First().Description.ShouldBe(TestData.IdentityResourceDescription); - identityResourceDtoList.First().DisplayName.ShouldBe(TestData.IdentityResourceDisplayName); - identityResourceDtoList.First().Claims.ShouldBe(TestData.IdentityResourceUserClaims); - identityResourceDtoList.First().Emphasize.ShouldBeTrue(); - identityResourceDtoList.First().ShowInDiscoveryDocument.ShouldBeTrue(); - identityResourceDtoList.First().Required.ShouldBeTrue(); - } - - [Fact] - public void ModelFactory_ConvertFrom_ListRoleDetails_ListIsEmpty_NullReturned() - { - List roleDetailsModelList = new(); - - List roleDetailsDtoList = ModelFactory.ConvertFrom(roleDetailsModelList); - - roleDetailsDtoList.ShouldBeEmpty(); - } - - [Fact] - public void ModelFactory_ConvertFrom_ListRoleDetails_ListIsNull_NullReturned() - { - List roleDetailsModelList = null; - - List roleDetailsDtoList = ModelFactory.ConvertFrom(roleDetailsModelList); - - roleDetailsDtoList.ShouldBeEmpty(); - } - - [Fact] - public void ModelFactory_ConvertFrom_ListRoleDetails_ModelsConverted() - { - RoleDetails roleDetailsModel = new RoleDetails - { - RoleId = Guid.Parse(TestData.Role1Id), - RoleName = TestData.RoleName - }; - List roleDetailsModelList = [ - roleDetailsModel - ]; - - List rolesDetailsDtoList = ModelFactory.ConvertFrom(roleDetailsModelList); - - rolesDetailsDtoList.ShouldNotBeNull(); - rolesDetailsDtoList.ShouldNotBeEmpty(); - rolesDetailsDtoList.Count.ShouldBe(roleDetailsModelList.Count); - rolesDetailsDtoList.First().RoleId.ShouldBe(Guid.Parse(TestData.Role1Id)); - rolesDetailsDtoList.First().RoleName.ShouldBe(TestData.RoleName); - } - - [Fact] - public void ModelFactory_ConvertFrom_ListUserDetails_ListIsEmpty_NullReturned() - { - List userDetailsModelList = new(); - - List userDetailsDtoList = ModelFactory.ConvertFrom(userDetailsModelList); - - userDetailsDtoList.ShouldNotBeNull(); - userDetailsDtoList.ShouldBeEmpty(); - } - - [Fact] - public void ModelFactory_ConvertFrom_ListUserDetails_ListIsNull_NullReturned() - { - List userDetailsModelList = null; - - List userDetailsDtoList = ModelFactory.ConvertFrom(userDetailsModelList); - - userDetailsDtoList.ShouldNotBeNull(); - userDetailsDtoList.ShouldBeEmpty(); - } - - [Fact] - public void ModelFactory_ConvertFrom_ListUserDetails_ModelsConverted() - { - UserDetails userDetailsModel = new UserDetails - { - PhoneNumber = TestData.PhoneNumber, - Username = TestData.UserName, - Roles = TestData.Roles, - UserId = Guid.Parse(TestData.User1Id), - Email = TestData.EmailAddress, - Claims = TestData.Claims, - RegistrationDateTime = new DateTime(2025,2,1) - }; - List userDetailsModelList = [ - userDetailsModel - ]; - - List userDetailsDtoList = ModelFactory.ConvertFrom(userDetailsModelList); - - userDetailsDtoList.ShouldNotBeNull(); - userDetailsDtoList.ShouldNotBeEmpty(); - userDetailsDtoList.Count.ShouldBe(userDetailsModelList.Count); - userDetailsDtoList.First().UserName.ShouldBe(TestData.UserName); - userDetailsDtoList.First().EmailAddress.ShouldBe(TestData.EmailAddress); - userDetailsDtoList.First().PhoneNumber.ShouldBe(TestData.PhoneNumber); - userDetailsDtoList.First().UserId.ShouldBe(Guid.Parse(TestData.User1Id)); - userDetailsDtoList.First().Claims.ShouldBe(TestData.Claims); - userDetailsDtoList.First().Roles.ShouldBe(TestData.Roles); - userDetailsDtoList.First().RegistrationDateTime.ShouldBe(new DateTime(2025, 2, 1)); - } - - [Fact] - public void ModelFactory_ConvertFrom_RoleDetails_ModelConverted() - { - RoleDetails roleDetailsModel = new RoleDetails - { - RoleId = Guid.Parse(TestData.Role1Id), - RoleName = TestData.RoleName - }; - - DataTransferObjects.Responses.RoleDetails roleDetailsDto = ModelFactory.ConvertFrom(roleDetailsModel); - - roleDetailsDto.RoleId.ShouldBe(Guid.Parse(TestData.Role1Id)); - roleDetailsDto.RoleName.ShouldBe(TestData.RoleName); - } - - [Fact] - public void ModelFactory_ConvertFrom_RoleDetails_ModelIsNull_NullReturned() - { - RoleDetails roleDetailsModel = null; - - DataTransferObjects.Responses.RoleDetails roleDetailsDto = ModelFactory.ConvertFrom(roleDetailsModel); - - roleDetailsDto.ShouldBeNull(); - } - - [Fact] - public void ModelFactory_ConvertFrom_UserDetails_ModelConverted() - { - UserDetails userDetailsModel = new UserDetails - { - PhoneNumber = TestData.PhoneNumber, - Username = TestData.UserName, - Roles = TestData.Roles, - UserId = Guid.Parse(TestData.User1Id), - Email = TestData.EmailAddress, - Claims = TestData.Claims - }; - - DataTransferObjects.Responses.UserDetails userDetailsDto = ModelFactory.ConvertFrom(userDetailsModel); - - userDetailsDto.UserName.ShouldBe(TestData.UserName); - userDetailsDto.EmailAddress.ShouldBe(TestData.EmailAddress); - userDetailsDto.PhoneNumber.ShouldBe(TestData.PhoneNumber); - userDetailsDto.UserId.ShouldBe(Guid.Parse(TestData.User1Id)); - userDetailsDto.Claims.ShouldBe(TestData.Claims); - userDetailsDto.Roles.ShouldBe(TestData.Roles); - } - - [Fact] - public void ModelFactory_ConvertFrom_UserDetails_ModelIsNull_NullReturned() - { - UserDetails userDetailsModel = null; - - DataTransferObjects.Responses.UserDetails userDetailsDto = ModelFactory.ConvertFrom(userDetailsModel); - - userDetailsDto.ShouldBeNull(); - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService.UnitTests/RequestHandler/ApiResourceRequestHandlerTests.cs b/archive/SecurityService.UnitTests/RequestHandler/ApiResourceRequestHandlerTests.cs deleted file mode 100644 index 139c40f6..00000000 --- a/archive/SecurityService.UnitTests/RequestHandler/ApiResourceRequestHandlerTests.cs +++ /dev/null @@ -1,122 +0,0 @@ -using SimpleResults; - -namespace SecurityService.UnitTests.RequestHandler; - -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using BusinessLogic.RequestHandlers; -using BusinessLogic.Requests; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Duende.IdentityServer.EntityFramework.Entities; -using Duende.IdentityServer.EntityFramework.Options; -using Microsoft.EntityFrameworkCore; -using Shared.Exceptions; -using Shouldly; -using Xunit; - -public class ApiResourceRequestHandlerTests{ - - private readonly ApiResourceRequestHandler RequestHandler; - - private readonly ConfigurationDbContext Context; - - public ApiResourceRequestHandlerTests(){ - SetupRequestHandlers setupRequestHandlers = new SetupRequestHandlers(); - this.Context = SetupRequestHandlers.GetConfigurationDbContext(); - this.RequestHandler = setupRequestHandlers.SetupApiResourceRequestHandler(this.Context); - } - - [Fact] - public async Task ApiResourceRequestHandler_CreateApiResourceRequest_RequestIsHandled(){ - SecurityServiceCommands.CreateApiResourceCommand command = TestData.CreateApiResourceCommand; - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - - Int32 resourceCount = await this.Context.ApiResources.CountAsync(); - resourceCount.ShouldBe(1); - } - - [Fact] - public async Task ApiResourceRequestHandler_CreateApiResourceRequest_NoScopes_RequestIsHandled() - { - SecurityServiceCommands.CreateApiResourceCommand command = TestData.CreateApiResourceCommand; - command = command with { Scopes = new List() }; - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - - Int32 resourceCount = await this.Context.ApiResources.CountAsync(); - resourceCount.ShouldBe(1); - } - - [Fact] - public async Task ApiResourceRequestHandler_CreateApiResourceRequest_NullScopes_RequestIsHandled(){ - SecurityServiceCommands.CreateApiResourceCommand command = TestData.CreateApiResourceCommand; - command = command with { Scopes = null }; - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - - Int32 resourceCount = await this.Context.ApiResources.CountAsync(); - resourceCount.ShouldBe(1); - } - - [Fact] - public async Task ApiResourceRequestHandler_GetApiResourceRequest_RequestIsHandled() - { - SecurityServiceQueries.GetApiResourceQuery query = TestData.GetApiResourceQuery; - - await this.Context.ApiResources.AddAsync(new ApiResource{ - Id = 1, - Name = TestData.GetApiResourceQuery.Name - }); - await this.Context.SaveChangesAsync(CancellationToken.None); - - var result = await this.RequestHandler.Handle(query, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - result.Data.ShouldNotBeNull(); - result.Data.Name.ShouldBe(query.Name); - } - - [Fact] - public async Task ApiResourceRequestHandler_GetApiResourceRequest_RecordNotFound_RequestIsHandled() - { - SecurityServiceQueries.GetApiResourceQuery query = TestData.GetApiResourceQuery; - - var result = await this.RequestHandler.Handle(query, CancellationToken.None); - result.IsFailed.ShouldBeTrue(); - result.Status.ShouldBe(ResultStatus.NotFound); - } - - [Fact] - public async Task ApiResourceRequestHandler_GetApiResourcesRequest_RequestIsHandled() - { - SecurityServiceQueries.GetApiResourcesQuery query = TestData.GetApiResourcesQuery; - - await this.Context.ApiResources.AddAsync(new ApiResource - { - Id = 1, - Name = TestData.GetApiResourceQuery.Name - }); - await this.Context.SaveChangesAsync(CancellationToken.None); - - var result = await this.RequestHandler.Handle(query, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - result.Data.ShouldNotBeNull(); - result.Data.ShouldHaveSingleItem(); - } - - [Fact] - public async Task ApiResourceRequestHandler_GetApiResourcesRequest_NoRecordsFound_RequestIsHandled() - { - SecurityServiceQueries.GetApiResourcesQuery query = TestData.GetApiResourcesQuery; - - var result = await this.RequestHandler.Handle(query, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - result.Data.ShouldNotBeNull(); - result.Data.ShouldBeEmpty(); - } -} \ No newline at end of file diff --git a/archive/SecurityService.UnitTests/RequestHandler/ApiScopeRequestHandlerTests.cs b/archive/SecurityService.UnitTests/RequestHandler/ApiScopeRequestHandlerTests.cs deleted file mode 100644 index 0a057c92..00000000 --- a/archive/SecurityService.UnitTests/RequestHandler/ApiScopeRequestHandlerTests.cs +++ /dev/null @@ -1,103 +0,0 @@ -using SimpleResults; - -namespace SecurityService.UnitTests.RequestHandler; - -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using BusinessLogic.RequestHandlers; -using BusinessLogic.Requests; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Duende.IdentityServer.EntityFramework.Entities; -using Duende.IdentityServer.EntityFramework.Options; -using Microsoft.EntityFrameworkCore; -using Shared.Exceptions; -using Shouldly; -using Xunit; -using static Microsoft.EntityFrameworkCore.DbLoggerCategory; - -public class ApiScopeRequestHandlerTests -{ - - private readonly ApiScopeRequestHandler RequestHandler; - - private readonly ConfigurationDbContext Context; - - public ApiScopeRequestHandlerTests(){ - SetupRequestHandlers setupRequestHandlers = new SetupRequestHandlers(); - this.Context = SetupRequestHandlers.GetConfigurationDbContext(); - this.RequestHandler = setupRequestHandlers.SetupApiScopeRequestHandler(this.Context); - } - - [Fact] - public async Task ApiScopeRequestHandler_CreateApiScopeRequest_RequestIsHandled() - { - SecurityServiceCommands.CreateApiScopeCommand command = TestData.CreateApiScopeCommand; - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - - Int32 scopeCount = await this.Context.ApiScopes.CountAsync(); - scopeCount.ShouldBe(1); - } - - [Fact] - public async Task ApiScopeRequestHandler_GetApiScopeRequest_RequestIsHandled() - { - SecurityServiceQueries.GetApiScopeQuery query = TestData.GetApiScopeQuery; - - await this.Context.ApiScopes.AddAsync(new ApiScope() - { - Id = 1, - Name = TestData.GetApiScopeQuery.Name - }); - await this.Context.SaveChangesAsync(CancellationToken.None); - - var result = await this.RequestHandler.Handle(query, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - result.Data.ShouldNotBeNull(); - result.Data.Name.ShouldBe(query.Name); - } - - [Fact] - public async Task ApiScopeRequestHandler_GetApiScopeRequest_RecordNotFound_RequestIsHandled() - { - SecurityServiceQueries.GetApiScopeQuery query = TestData.GetApiScopeQuery; - - var result = await this.RequestHandler.Handle(query, CancellationToken.None); - result.IsFailed.ShouldBeTrue(); - result.Status.ShouldBe(ResultStatus.NotFound); - } - - [Fact] - public async Task ApiScopeRequestHandler_GetApiScopesRequest_RequestIsHandled() - { - SecurityServiceQueries.GetApiScopesQuery query = TestData.GetApiScopesQuery; - - await this.Context.ApiScopes.AddAsync(new ApiScope() - { - Id = 1, - Name = TestData.GetApiResourceQuery.Name - }); - await this.Context.SaveChangesAsync(CancellationToken.None); - - var result = await this.RequestHandler.Handle(query, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - result.Data.ShouldNotBeNull(); - result.Data.ShouldHaveSingleItem(); - } - - [Fact] - public async Task ApiScopeRequestHandler_GetApiScopesRequest_NoRecordsFound_RequestIsHandled() - { - SecurityServiceQueries.GetApiScopesQuery query = TestData.GetApiScopesQuery; - - await this.Context.SaveChangesAsync(CancellationToken.None); - - var result = await this.RequestHandler.Handle(query, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - result.Data.ShouldNotBeNull(); - result.Data.ShouldBeEmpty(); - } -} \ No newline at end of file diff --git a/archive/SecurityService.UnitTests/RequestHandler/ClientRequestHandlerTests.cs b/archive/SecurityService.UnitTests/RequestHandler/ClientRequestHandlerTests.cs deleted file mode 100644 index 413431e0..00000000 --- a/archive/SecurityService.UnitTests/RequestHandler/ClientRequestHandlerTests.cs +++ /dev/null @@ -1,180 +0,0 @@ -using SimpleResults; - -namespace SecurityService.UnitTests.RequestHandler; - -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using BusinessLogic.RequestHandlers; -using BusinessLogic.Requests; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Duende.IdentityServer.EntityFramework.Options; -using Duende.IdentityServer.Models; -using Microsoft.EntityFrameworkCore; -using Shared.Exceptions; -using Shouldly; -using Xunit; - -public class ClientRequestHandlerTests -{ - private readonly ClientRequestHandler RequestHandler; - - private readonly ConfigurationDbContext Context; - - public ClientRequestHandlerTests(){ - SetupRequestHandlers setupRequestHandlers = new SetupRequestHandlers(); - this.Context = SetupRequestHandlers.GetConfigurationDbContext(); - this.RequestHandler = setupRequestHandlers.SetupClientRequestHandler(this.Context); - } - - [Fact] - public async Task ClientRequestHandler_CreateClientCommand_RequestIsHandled() - { - SecurityServiceCommands.CreateClientCommand command = TestData.CreateClientCommand; - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - - Int32 clientCount = await this.Context.Clients.CountAsync(); - clientCount.ShouldBe(1); - } - - [Fact] - public async Task ClientRequestHandler_CreateClientCommand_NullClientRedirectUris_RequestIsHandled() - { - SecurityServiceCommands.CreateClientCommand command = TestData.CreateClientCommand; - - command = command with { ClientRedirectUris = null }; - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - - Int32 clientCount = await this.Context.Clients.CountAsync(); - clientCount.ShouldBe(1); - } - - [Fact] - public async Task ClientRequestHandler_CreateClientCommand_EmptyClientRedirectUris_RequestIsHandled() - { - SecurityServiceCommands.CreateClientCommand command = TestData.CreateClientCommand; - - command = command with { ClientRedirectUris = new List() }; - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - - Int32 clientCount = await this.Context.Clients.CountAsync(); - clientCount.ShouldBe(1); - } - - [Fact] - public async Task ClientRequestHandler_CreateClientRequest_EmptyClientPostLogoutRedirectUris_RequestIsHandled() - { - SecurityServiceCommands.CreateClientCommand command = TestData.CreateClientCommand; - - command = command with { ClientPostLogoutRedirectUris = new List() }; - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - - Int32 clientCount = await this.Context.Clients.CountAsync(); - clientCount.ShouldBe(1); - } - - - [Fact] - public async Task ClientRequestHandler_CreateClientRequest_InvalidGrant_RequestIsHandled(){ - SecurityServiceCommands.CreateClientCommand command = TestData.CreateClientCommand; - - command = command with { AllowedGrantTypes = new List() { - "invalid" - } }; - - Result result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsFailed.ShouldBeTrue(); - result.Status.ShouldBe(ResultStatus.Invalid); - } - - [Fact] - public async Task ClientRequestHandler_CreateClientRequest_NullClientPostLogoutRedirectUris_RequestIsHandled() - { - SecurityServiceCommands.CreateClientCommand command = TestData.CreateClientCommand; - - command = command with { ClientPostLogoutRedirectUris = null }; - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - Int32 clientCount = await this.Context.Clients.CountAsync(); - clientCount.ShouldBe(1); - } - - [Fact] - public async Task ClientRequestHandler_CreateClientRequest_HybridClient_RequestIsHandled() - { - SecurityServiceCommands.CreateClientCommand command = TestData.CreateHybridClientCommand; - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - - Int32 clientCount = await this.Context.Clients.CountAsync(); - clientCount.ShouldBe(1); - } - [Fact] - public async Task ClientRequestHandler_GetClientRequest_RequestIsHandled() - { - SecurityServiceQueries.GetClientQuery query = TestData.GetClientQuery; - - await this.Context.Clients.AddAsync(new Duende.IdentityServer.EntityFramework.Entities.Client() - { - ClientId = query.ClientId, - }); - await this.Context.SaveChangesAsync(CancellationToken.None); - - var result = await this.RequestHandler.Handle(query, CancellationToken.None); - - result.IsSuccess.ShouldBeTrue(); - result.Data.ShouldNotBeNull(); - result.Data.ClientId.ShouldBe(query.ClientId); - } - - [Fact] - public async Task ClientRequestHandler_GetClientRequest_RecordNotFound_RequestIsHandled() - { - SecurityServiceQueries.GetClientQuery query = TestData.GetClientQuery; - - var result = await this.RequestHandler.Handle(query, CancellationToken.None); - - result.IsFailed.ShouldBeTrue(); - result.Status.ShouldBe(ResultStatus.NotFound); - } - - [Fact] - public async Task ClientRequestHandler_GetClientsRequest_RequestIsHandled() - { - SecurityServiceQueries.GetClientsQuery query = TestData.GetClientsQuery; - - await this.Context.Clients.AddAsync(new Duende.IdentityServer.EntityFramework.Entities.Client(){ - ClientId = TestData.GetClientQuery.ClientId, - }); - await this.Context.SaveChangesAsync(CancellationToken.None); - - var result = await this.RequestHandler.Handle(query, CancellationToken.None); - - result.IsSuccess.ShouldBeTrue(); - result.Data.ShouldNotBeNull(); - result.Data.ShouldHaveSingleItem(); - } - - [Fact] - public async Task ClientRequestHandler_GetClientsRequest_NoRecordsFound_RequestIsHandled() - { - SecurityServiceQueries.GetClientsQuery query = TestData.GetClientsQuery; - - var result = await this.RequestHandler.Handle(query, CancellationToken.None); - - result.IsSuccess.ShouldBeTrue(); - result.Data.ShouldNotBeNull(); - result.Data.ShouldBeEmpty(); - } -} \ No newline at end of file diff --git a/archive/SecurityService.UnitTests/RequestHandler/IdentityResourceRequestHandlerTests.cs b/archive/SecurityService.UnitTests/RequestHandler/IdentityResourceRequestHandlerTests.cs deleted file mode 100644 index 64c98e99..00000000 --- a/archive/SecurityService.UnitTests/RequestHandler/IdentityResourceRequestHandlerTests.cs +++ /dev/null @@ -1,102 +0,0 @@ -using SimpleResults; - -namespace SecurityService.UnitTests.RequestHandler; - -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using BusinessLogic.RequestHandlers; -using BusinessLogic.Requests; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Duende.IdentityServer.EntityFramework.Entities; -using Duende.IdentityServer.EntityFramework.Options; -using Microsoft.EntityFrameworkCore; -using Shared.Exceptions; -using Shouldly; -using Xunit; - -public class IdentityResourceRequestHandlerTests -{ - private readonly IdentityResourceRequestHandler RequestHandler; - - private readonly ConfigurationDbContext Context; - - public IdentityResourceRequestHandlerTests(){ - SetupRequestHandlers setupRequestHandlers = new SetupRequestHandlers(); - this.Context = SetupRequestHandlers.GetConfigurationDbContext(); - this.RequestHandler = setupRequestHandlers.SetupIdentityResourceRequestHandler(this.Context); - } - - [Fact] - public async Task IdentityResourceRequestHandler_CreateIdentityResourceRequest_RequestIsHandled() - { - SecurityServiceCommands.CreateIdentityResourceCommand command = TestData.CreateIdentityResourceCommand; - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - - Int32 clientCount = await this.Context.IdentityResources.CountAsync(); - clientCount.ShouldBe(1); - } - - [Fact] - public async Task IdentityResourceRequestHandler_GetIdentityResourceRequest_RequestIsHandled() - { - SecurityServiceQueries.GetIdentityResourceQuery query = TestData.GetIdentityResourceQuery; - - await this.Context.IdentityResources.AddAsync(new IdentityResource() - { - Id = 1, - Name = query.IdentityResourceName - }); - await this.Context.SaveChangesAsync(CancellationToken.None); - - var result= await this.RequestHandler.Handle(query, CancellationToken.None); - - result.IsSuccess.ShouldBeTrue(); - result.Data.ShouldNotBeNull(); - result.Data.Name.ShouldBe(query.IdentityResourceName); - } - - [Fact] - public async Task IdentityResourceRequestHandler_GetIdentityResourceRequest_RecordNotFound_RequestIsHandled() - { - SecurityServiceQueries.GetIdentityResourceQuery query = TestData.GetIdentityResourceQuery; - - var result = await this.RequestHandler.Handle(query, CancellationToken.None); - result.IsFailed.ShouldBeTrue(); - result.Status.ShouldBe(ResultStatus.NotFound); - } - - [Fact] - public async Task IdentityResourceRequestHandler_GetIdentityResourcesRequest_RequestIsHandled() - { - SecurityServiceQueries.GetIdentityResourcesQuery query = TestData.GetIdentityResourcesQuery; - - await this.Context.IdentityResources.AddAsync(new IdentityResource() - { - Id = 1, - Name = TestData.GetIdentityResourceQuery.IdentityResourceName - }); - await this.Context.SaveChangesAsync(CancellationToken.None); - - var result = await this.RequestHandler.Handle(query, CancellationToken.None); - - result.IsSuccess.ShouldBeTrue(); - result.Data.ShouldNotBeNull(); - result.Data.ShouldHaveSingleItem(); - } - - [Fact] - public async Task IdentityResourceRequestHandler_GetIdentityResourcesRequest_NoRecordsFound_RequestIsHandled() - { - SecurityServiceQueries.GetIdentityResourcesQuery query = TestData.GetIdentityResourcesQuery; - - var result = await this.RequestHandler.Handle(query, CancellationToken.None); - - result.IsSuccess.ShouldBeTrue(); - result.Data.ShouldNotBeNull(); - result.Data.ShouldBeEmpty(); - } -} \ No newline at end of file diff --git a/archive/SecurityService.UnitTests/RequestHandler/RoleRequestHandlerTests.cs b/archive/SecurityService.UnitTests/RequestHandler/RoleRequestHandlerTests.cs deleted file mode 100644 index f0d23815..00000000 --- a/archive/SecurityService.UnitTests/RequestHandler/RoleRequestHandlerTests.cs +++ /dev/null @@ -1,143 +0,0 @@ -using SimpleResults; - -namespace SecurityService.UnitTests.RequestHandler; - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using BusinessLogic.Exceptions; -using BusinessLogic.RequestHandlers; -using BusinessLogic.Requests; -using Database.DbContexts; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Identity.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Models; -using Moq; -using Shared.Exceptions; -using Shouldly; -using Xunit; -using static Microsoft.EntityFrameworkCore.DbLoggerCategory; - -public class RoleRequestHandlerTests -{ - private readonly RoleRequestHandler RequestHandler; - private readonly ConfigurationDbContext ConfigurationDbContext; - private readonly AuthenticationDbContext AuthenticationDbContext; - - private readonly SetupRequestHandlers SetupRequestHandlers; - - public RoleRequestHandlerTests(){ - this.SetupRequestHandlers = new SetupRequestHandlers(); - this.ConfigurationDbContext = SetupRequestHandlers.GetConfigurationDbContext(); - this.AuthenticationDbContext = SetupRequestHandlers.GetAuthenticationDbContext(); - this.RequestHandler = this.SetupRequestHandlers.SetupRoleRequestHandler(this.ConfigurationDbContext, this.AuthenticationDbContext); - } - - [Fact] - public async Task RoleRequestHandler_CreateRoleCommand_RequestIsHandled() - { - SecurityServiceCommands.CreateRoleCommand command = TestData.CreateRoleCommand; - - this.SetupRequestHandlers.RoleValidator.Setup(r => r.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - - Int32 roleCount = await this.AuthenticationDbContext.Roles.CountAsync(); - roleCount.ShouldBe(1); - } - - [Fact] - public async Task RoleRequestHandler_CreateRoleCommand_RoleAlreadyExists_RequestIsHandled() - { - SecurityServiceCommands.CreateRoleCommand command = TestData.CreateRoleCommand; - - await this.AuthenticationDbContext.Roles.AddAsync(new IdentityRole() - { - Id = TestData.CreateRoleCommand.RoleId.ToString(), - Name = TestData.CreateRoleCommand.Name, - NormalizedName = TestData.CreateRoleCommand.Name.ToUpper() - }); - await this.AuthenticationDbContext.SaveChangesAsync(CancellationToken.None); - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsFailed.ShouldBeTrue(); - } - - [Fact] - public async Task RoleRequestHandler_CreateRoleCommand_RoleCreateFailed_RequestIsHandled() - { - SecurityServiceCommands.CreateRoleCommand command = TestData.CreateRoleCommand; - - List errors = new List(); - errors.Add(new IdentityError()); - this.SetupRequestHandlers.RoleValidator.Setup(r => r.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Failed(errors.ToArray())); - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsFailed.ShouldBeTrue(); - } - - [Fact] - public async Task RoleRequestHandler_GetRoleRequest_RequestIsHandled() - { - SecurityServiceQueries.GetRoleQuery query = TestData.GetRoleQuery; - - await this.AuthenticationDbContext.Roles.AddAsync(new IdentityRole() - { - Id = TestData.GetRoleQuery.RoleId.ToString() - }); - await this.AuthenticationDbContext.SaveChangesAsync(CancellationToken.None); - - var result = await this.RequestHandler.Handle(query, CancellationToken.None); - - result.IsSuccess.ShouldBeTrue(); - result.Data.ShouldNotBeNull(); - - result.Data.RoleId.ShouldBe(query.RoleId); - } - - [Fact] - public async Task RoleRequestHandler_GetRoleRequest_RecordNotFound_RequestIsHandled() - { - SecurityServiceQueries.GetRoleQuery query = TestData.GetRoleQuery; - - var result = await this.RequestHandler.Handle(query, CancellationToken.None); - result.IsFailed.ShouldBeTrue(); - result.Status.ShouldBe(ResultStatus.NotFound); - } - - [Fact] - public async Task RoleRequestHandler_GetRolesRequest_RequestIsHandled() - { - SecurityServiceQueries.GetRolesQuery query = TestData.GetRolesQuery; - - await this.AuthenticationDbContext.Roles.AddAsync(new IdentityRole() - { - Id = TestData.GetRoleQuery.RoleId.ToString() - }); - await this.AuthenticationDbContext.SaveChangesAsync(CancellationToken.None); - - var result = await this.RequestHandler.Handle(query, CancellationToken.None); - - result.IsSuccess.ShouldBeTrue(); - result.Data.ShouldNotBeNull(); - result.Data.ShouldHaveSingleItem(); - } - - [Fact] - public async Task RoleRequestHandler_GetRolesRequest_NoRecordsFound_RequestIsHandled(){ - SecurityServiceQueries.GetRolesQuery query = TestData.GetRolesQuery; - - var result = await this.RequestHandler.Handle(query, CancellationToken.None); - - result.IsSuccess.ShouldBeTrue(); - result.Data.ShouldNotBeNull(); - result.Data.ShouldBeEmpty(); - } -} \ No newline at end of file diff --git a/archive/SecurityService.UnitTests/RequestHandler/UserRequestHandlerTests.cs b/archive/SecurityService.UnitTests/RequestHandler/UserRequestHandlerTests.cs deleted file mode 100644 index db44a7c9..00000000 --- a/archive/SecurityService.UnitTests/RequestHandler/UserRequestHandlerTests.cs +++ /dev/null @@ -1,690 +0,0 @@ -using SimpleResults; - -namespace SecurityService.UnitTests.RequestHandler; - -using BusinessLogic.RequestHandlers; -using BusinessLogic.Requests; -using Castle.Components.DictionaryAdapter; -using Database.DbContexts; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Duende.IdentityServer.EntityFramework.Entities; -using MessagingService.DataTransferObjects; -using Microsoft.AspNetCore.Identity; -using Microsoft.EntityFrameworkCore; -using Models; -using Moq; -using SecurityService.BusinessLogic; -using SecurityService.BusinessLogic.Exceptions; -using Shared.Exceptions; -using Shared.Logger; -using Shouldly; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Xunit; -using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database; -using static SecurityService.BusinessLogic.Requests.SecurityServiceCommands; - -public class UserRequestHandlerTests{ - private readonly ConfigurationDbContext ConfigurationDbContext; - private readonly AuthenticationDbContext AuthenticationDbContext; - public UserRequestHandler RequestHandler; - - private SetupRequestHandlers SetupRequestHandlers; - - public UserRequestHandlerTests(){ - Logger.Initialise(NullLogger.Instance); - - this.SetupRequestHandlers = new SetupRequestHandlers(); - this.ConfigurationDbContext = SetupRequestHandlers.GetConfigurationDbContext(); - this.AuthenticationDbContext = SetupRequestHandlers.GetAuthenticationDbContext(); - this.RequestHandler = this.SetupRequestHandlers.SetUserRequestHandler(this.ConfigurationDbContext,this.AuthenticationDbContext); - } - - [Theory] - [InlineData("password")] - [InlineData(null)] - [InlineData("")] - public async Task UserRequestHandler_CreateUserCommand_RequestIsHandled(String password) - { - SecurityServiceCommands.CreateUserCommand command = new(Guid.Parse(TestData.UserId), - TestData.GivenName, - TestData.MiddleName, - TestData.FamilyName, - TestData.UserName, - password, - TestData.EmailAddress, - TestData.PhoneNumber, - TestData.Claims, - TestData.Roles); - - - await this.AuthenticationDbContext.Roles.AddAsync(new IdentityRole{ - Id = Guid.NewGuid().ToString(), - Name = "TESTROLE1", - NormalizedName = "TESTROLE1"}); - await this.AuthenticationDbContext.SaveChangesAsync(); - - this.SetupRequestHandlers.UserValidator.Setup(s => s.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - this.SetupRequestHandlers.MessagingServiceClient.Setup(m => m.SendEmail(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success); - - Result result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - - Int32 userCount = await this.AuthenticationDbContext.Users.CountAsync(); - userCount.ShouldBe(1); - } - - [Fact] - public async Task UserRequestHandler_CreateUserCommand_EmailSendFailed_RequestIsHandled() - { - SecurityServiceCommands.CreateUserCommand command = new(Guid.Parse(TestData.UserId), - TestData.GivenName, - TestData.MiddleName, - TestData.FamilyName, - TestData.UserName, - "password", - TestData.EmailAddress, - TestData.PhoneNumber, - TestData.Claims, - TestData.Roles); - - - await this.AuthenticationDbContext.Roles.AddAsync(new IdentityRole - { - Id = Guid.NewGuid().ToString(), - Name = "TESTROLE1", - NormalizedName = "TESTROLE1" - }); - await this.AuthenticationDbContext.SaveChangesAsync(); - - this.SetupRequestHandlers.UserValidator.Setup(s => s.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - this.SetupRequestHandlers.MessagingServiceClient.Setup(m => m.SendEmail(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Failure); - - Result result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - - Int32 userCount = await this.AuthenticationDbContext.Users.CountAsync(); - userCount.ShouldBe(1); - } - - [Fact] - public async Task UserRequestHandler_CreateUserCommand_NewPasswordHashEmpty_RequestIsHandled() { - SecurityServiceCommands.CreateUserCommand command = TestData.CreateUserCommand; - - await this.AuthenticationDbContext.Roles.AddAsync(new IdentityRole{ - Id = Guid.NewGuid().ToString(), - Name = "TESTROLE1", - NormalizedName = "TESTROLE1" - }); - await this.AuthenticationDbContext.SaveChangesAsync(); - - this.SetupRequestHandlers.PasswordHasher.Setup(s => s.HashPassword(It.IsAny(), It.IsAny())).Returns(String.Empty); - - this.SetupRequestHandlers.UserValidator.Setup(s => s.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsFailed.ShouldBeTrue(); - } - - [Fact] - public async Task UserRequestHandler_CreateUserCommand_CreateFailed_RequestIsHandled(){ - SecurityServiceCommands.CreateUserCommand command = TestData.CreateUserCommand; - - await this.AuthenticationDbContext.Roles.AddAsync(new IdentityRole - { - Id = Guid.NewGuid().ToString(), - Name = "TESTROLE1", - NormalizedName = "TESTROLE1" - }); - await this.AuthenticationDbContext.SaveChangesAsync(); - - List errors = new List(); - errors.Add(new IdentityError()); - this.SetupRequestHandlers.UserValidator.Setup(s => s.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Failed(errors.ToArray())); - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsFailed.ShouldBeTrue(); - } - - [Fact] - public async Task UserRequestHandler_CreateUserCommand_AddClaimsFailed_RequestIsHandled() - { - SecurityServiceCommands.CreateUserCommand command = TestData.CreateUserCommand; - - await this.AuthenticationDbContext.Roles.AddAsync(new IdentityRole - { - Id = Guid.NewGuid().ToString(), - Name = "TESTROLE1", - NormalizedName = "TESTROLE1" - }); - await this.AuthenticationDbContext.SaveChangesAsync(); - - List errors = new List(); - errors.Add(new IdentityError()); - - this.SetupRequestHandlers.UserValidator - .SetupSequence(s => - s.ValidateAsync(It.IsAny>(), It.IsAny())) - .ReturnsAsync(IdentityResult.Success) - .ReturnsAsync(IdentityResult.Success) - .ReturnsAsync(IdentityResult.Failed(errors.ToArray())); - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsFailed.ShouldBeTrue(); - } - - [Fact] - public async Task UserRequestHandler_CreateUserCommand_SendMailThrowsError_RequestIsHandled() - { - SecurityServiceCommands.CreateUserCommand command = TestData.CreateUserCommand; - - await this.AuthenticationDbContext.Roles.AddAsync(new IdentityRole - { - Id = Guid.NewGuid().ToString(), - Name = "TESTROLE1", - NormalizedName = "TESTROLE1" - }); - await this.AuthenticationDbContext.SaveChangesAsync(); - - this.SetupRequestHandlers.UserValidator.Setup(s => s.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - - this.SetupRequestHandlers.MessagingServiceClient.Setup(m => m.SendEmail(It.IsAny(), - It.IsAny(), - It.IsAny())).ReturnsAsync(Result.Failure); - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - } - - [Fact] - public async Task UserRequestHandler_CreateUserCommand_AddToRoleFailed_RequestIsHandled() - { - SecurityServiceCommands.CreateUserCommand command = TestData.CreateUserCommand; - - await this.AuthenticationDbContext.Roles.AddAsync(new IdentityRole - { - Id = "RoleId1", - Name = "TESTROLE1", - NormalizedName = "TESTROLE1" - }); - await this.AuthenticationDbContext.UserRoles.AddAsync(new IdentityUserRole{ - RoleId = "RoleId1", - UserId = command.UserId.ToString(), - }); - - await this.AuthenticationDbContext.SaveChangesAsync(); - - this.SetupRequestHandlers.UserValidator.Setup(s => s.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsFailed.ShouldBeTrue(); - } - - [Fact] - public async Task UserRequestHandler_CreateUserCommand_CreateFailedAndCleanUpFailed_RequestIsHandled() - { - SecurityServiceCommands.CreateUserCommand command = TestData.CreateUserCommand; - - await this.AuthenticationDbContext.Roles.AddAsync(new IdentityRole - { - Id = "RoleId1", - Name = "TESTROLE1", - NormalizedName = "TESTROLE1" - }); - await this.AuthenticationDbContext.UserRoles.AddAsync(new IdentityUserRole - { - RoleId = "RoleId1", - UserId = command.UserId.ToString(), - }); - - await this.AuthenticationDbContext.SaveChangesAsync(); - - List errors = new List(); - errors.Add(new IdentityError()); - - this.SetupRequestHandlers.UserValidator - .SetupSequence(s => - s.ValidateAsync(It.IsAny>(), It.IsAny())) - .ReturnsAsync(IdentityResult.Success) - .ReturnsAsync(IdentityResult.Success) - .ReturnsAsync(IdentityResult.Failed(errors.ToArray())) - .ReturnsAsync(IdentityResult.Failed(errors.ToArray())); - - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsFailed.ShouldBeTrue(); - } - - - [Fact] - public async Task UserRequestHandler_CreateUserCommand_NullRoles_RequestIsHandled() - { - SecurityServiceCommands.CreateUserCommand command = TestData.CreateUserCommand; - command = command with { Roles = null }; - - this.SetupRequestHandlers.UserValidator.Setup(s => s.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - this.SetupRequestHandlers.MessagingServiceClient.Setup(m => m.SendEmail(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success); - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - Int32 userCount = await this.AuthenticationDbContext.Users.CountAsync(); - userCount.ShouldBe(1); - } - - [Fact] - public async Task UserRequestHandler_CreateUserCommand_EmptyRoles_RequestIsHandled() - { - SecurityServiceCommands.CreateUserCommand command = TestData.CreateUserCommand; - command = command with { Roles = new List() }; - this.SetupRequestHandlers.UserValidator.Setup(s => s.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - this.SetupRequestHandlers.MessagingServiceClient.Setup(m => m.SendEmail(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success); - - Result result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - - Int32 userCount = await this.AuthenticationDbContext.Users.CountAsync(); - userCount.ShouldBe(1); - } - /* - [Fact] - public async Task UserRequestHandler_GetUserRequest_RequestIsHandled() - { - GetUserRequest request = TestData.GetUserRequest; - - await this.AuthenticationDbContext.Users.AddAsync(new IdentityUser - { - Id = request.UserId.ToString() - }); - await this.AuthenticationDbContext.SaveChangesAsync(); - - UserDetails model = await this.RequestHandler.Handle(request, CancellationToken.None); - - model.ShouldNotBeNull(); - } - - [Fact] - public async Task UserRequestHandler_GetUserRequest_UserNotFound_RequestIsHandled() - { - GetUserRequest request = TestData.GetUserRequest; - - Should.Throw(async () => { - await this.RequestHandler.Handle(request, CancellationToken.None); - }); - } - - [Theory] - [InlineData("00000001")] - [InlineData(null)] - [InlineData("")] - public async Task UserRequestHandler_GetUsersRequest_RequestIsHandled(String userName) - { - GetUsersRequest request = GetUsersRequest.Create(userName); - - await this.AuthenticationDbContext.Users.AddAsync(new IdentityUser - { - Id = TestData.CreateUserRequest.UserId.ToString(), - UserName = TestData.CreateUserRequest.UserName, - NormalizedUserName = TestData.CreateUserRequest.UserName.ToUpper() - }); - await this.AuthenticationDbContext.SaveChangesAsync(); - - List models = await this.RequestHandler.Handle(request, CancellationToken.None); - - models.ShouldHaveSingleItem(); - } - */ - - [Fact] - public async Task UserRequestHandler_ConfirmUserEmailAddressCommand_RequestIsHandled() - { - SecurityServiceCommands.ConfirmUserEmailAddressCommand command = TestData.ConfirmUserEmailAddressCommand; - - await this.AuthenticationDbContext.Users.AddAsync(new ApplicationUser - { - Id = TestData.CreateUserCommand.UserId.ToString(), - UserName = TestData.CreateUserCommand.UserName, - NormalizedUserName = TestData.CreateUserCommand.UserName.ToUpper() - }); - await this.AuthenticationDbContext.SaveChangesAsync(); - - this.SetupRequestHandlers.UserValidator.Setup(s => s.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - - Result result = await this.RequestHandler.Handle(command, CancellationToken.None); - - result.IsSuccess.ShouldBeTrue(); - } - - [Fact] - public async Task UserRequestHandler_ConfirmUserEmailAddressCommand_UserNotFound_RequestIsHandled() - { - SecurityServiceCommands.ConfirmUserEmailAddressCommand command = TestData.ConfirmUserEmailAddressCommand; - - this.SetupRequestHandlers.UserValidator.Setup(s => s.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - - Result result = await this.RequestHandler.Handle(command, CancellationToken.None); - - result.IsFailed.ShouldBeTrue(); - result.Status.ShouldBe(ResultStatus.NotFound); - } - - [Fact] - public async Task UserRequestHandler_ConfirmUserEmailAddressCommand_ConfirmFailed_RequestIsHandled() - { - SecurityServiceCommands.ConfirmUserEmailAddressCommand command = TestData.ConfirmUserEmailAddressCommand; - - await this.AuthenticationDbContext.Users.AddAsync(new ApplicationUser - { - Id = TestData.CreateUserCommand.UserId.ToString(), - UserName = TestData.CreateUserCommand.UserName, - NormalizedUserName = TestData.CreateUserCommand.UserName.ToUpper() - }); - await this.AuthenticationDbContext.SaveChangesAsync(); - - List errors = new List(); - errors.Add(new IdentityError()); - this.SetupRequestHandlers.UserValidator.Setup(s => s.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Failed(errors.ToArray())); - - Result result = await this.RequestHandler.Handle(command, CancellationToken.None); - - result.IsFailed.ShouldBeTrue(); - result.Status.ShouldBe(ResultStatus.Failure); - } - - [Fact] - public async Task UserRequestHandler_ChangeUserPasswordCommand_RequestIsHandled() - { - SecurityServiceCommands.ChangeUserPasswordCommand command = TestData.ChangeUserPasswordCommand; - - await this.AuthenticationDbContext.Users.AddAsync(new ApplicationUser - { - Id = Guid.NewGuid().ToString(), - UserName = TestData.ChangeUserPasswordCommand.UserName, - NormalizedUserName = TestData.ChangeUserPasswordCommand.UserName.ToUpper(), - PasswordHash = TestData.ChangeUserPasswordCommand.CurrentPassword - }); - await this.AuthenticationDbContext.SaveChangesAsync(); - - await this.ConfigurationDbContext.Clients.AddAsync(new Client{ - ClientId = TestData.ChangeUserPasswordCommand.ClientId, - ClientUri = "http://localhost" - }); - - - await this.ConfigurationDbContext.SaveChangesAsync(); - - this.SetupRequestHandlers.UserValidator.Setup(s => s.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - this.SetupRequestHandlers.PasswordValidator.Setup(p => p.ValidateAsync(It.IsAny>(), It.IsAny(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - - result.IsSuccess.ShouldBeTrue(); - result.Data.IsSuccessful.ShouldBeTrue(); - result.Data.RedirectUri.ShouldNotBeNullOrEmpty(); - } - - [Fact] - public async Task UserRequestHandler_ChangeUserPasswordCommand_UserNotFound_RequestIsHandled() - { - ChangeUserPasswordCommand command = TestData.ChangeUserPasswordCommand; - - Result result = await this.RequestHandler.Handle(command, CancellationToken.None); - - result.IsFailed.ShouldBeTrue(); - result.Status.ShouldBe(ResultStatus.NotFound); - } - - [Fact] - public async Task UserRequestHandler_ChangeUserPasswordCommand_ClientNotFound_RequestIsHandled() - { - ChangeUserPasswordCommand command = TestData.ChangeUserPasswordCommand; - - await this.AuthenticationDbContext.Users.AddAsync(new ApplicationUser - { - Id = Guid.NewGuid().ToString(), - UserName = TestData.ChangeUserPasswordCommand.UserName, - NormalizedUserName = TestData.ChangeUserPasswordCommand.UserName.ToUpper(), - PasswordHash = TestData.ChangeUserPasswordCommand.CurrentPassword - }); - await this.AuthenticationDbContext.SaveChangesAsync(); - - this.SetupRequestHandlers.UserValidator.Setup(s => s.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - this.SetupRequestHandlers.PasswordValidator.Setup(p => p.ValidateAsync(It.IsAny>(), It.IsAny(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - Result result = await this.RequestHandler.Handle(command, CancellationToken.None); - - result.IsFailed.ShouldBeTrue(); - result.Status.ShouldBe(ResultStatus.Invalid); - } - - [Fact] - public async Task UserRequestHandler_ChangeUserPasswordCommand_PasswordChangeFailed_RequestIsHandled() - { - ChangeUserPasswordCommand command = TestData.ChangeUserPasswordCommand; - - await this.AuthenticationDbContext.Users.AddAsync(new ApplicationUser - { - Id = Guid.NewGuid().ToString(), - UserName = TestData.ChangeUserPasswordCommand.UserName, - NormalizedUserName = TestData.ChangeUserPasswordCommand.UserName.ToUpper(), - PasswordHash = TestData.ChangeUserPasswordCommand.CurrentPassword - }); - await this.AuthenticationDbContext.SaveChangesAsync(); - - await this.ConfigurationDbContext.Clients.AddAsync(new Client - { - ClientId = TestData.ChangeUserPasswordCommand.ClientId, - ClientUri = "http://localhost" - }); - - - await this.ConfigurationDbContext.SaveChangesAsync(); - List errors = new List(); - errors.Add(new IdentityError()); - - this.SetupRequestHandlers.UserValidator.Setup(s => s.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - this.SetupRequestHandlers.PasswordValidator.Setup(p => p.ValidateAsync(It.IsAny>(), It.IsAny(), - It.IsAny())).ReturnsAsync(IdentityResult.Failed(errors.ToArray())); - Result result = await this.RequestHandler.Handle(command, CancellationToken.None); - - result.IsFailed.ShouldBeTrue(); - result.Status.ShouldBe(ResultStatus.Failure); - } - - [Fact] - public async Task UserRequestHandler_ProcessPasswordResetConfirmationCommand_RequestIsHandled() - { - ProcessPasswordResetConfirmationCommand command = TestData.ProcessPasswordResetConfirmationCommand; - - await this.AuthenticationDbContext.Users.AddAsync(new ApplicationUser - { - Id = TestData.CreateUserCommand.UserId.ToString(), - UserName = TestData.CreateUserCommand.UserName, - NormalizedUserName = TestData.CreateUserCommand.UserName.ToUpper() - }); - await this.AuthenticationDbContext.SaveChangesAsync(); - - await this.ConfigurationDbContext.Clients.AddAsync(new Client - { - ClientId = TestData.ChangeUserPasswordCommand.ClientId, - ClientUri = "http://localhost" - }); - - - await this.ConfigurationDbContext.SaveChangesAsync(); - - this.SetupRequestHandlers.UserValidator.Setup(s => s.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - this.SetupRequestHandlers.PasswordValidator.Setup(p => p.ValidateAsync(It.IsAny>(), It.IsAny(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - - Result result = await this.RequestHandler.Handle(command, CancellationToken.None); - - result.IsSuccess.ShouldBeTrue(); - result.Data.ShouldNotBeNullOrEmpty(); - } - - [Fact] - public async Task UserRequestHandler_ProcessPasswordResetConfirmationCommand_UserNotFound_RequestIsHandled() - { - ProcessPasswordResetConfirmationCommand command = TestData.ProcessPasswordResetConfirmationCommand; - - Result result = await this.RequestHandler.Handle(command, CancellationToken.None); - - result.IsFailed.ShouldBeTrue(); - } - - [Fact] - public async Task UserRequestHandler_ProcessPasswordResetConfirmationCommand_ResetPasswordFailed_RequestIsHandled() - { - ProcessPasswordResetConfirmationCommand command = TestData.ProcessPasswordResetConfirmationCommand; - - await this.AuthenticationDbContext.Users.AddAsync(new ApplicationUser - { - Id = TestData.CreateUserCommand.UserId.ToString(), - UserName = TestData.CreateUserCommand.UserName, - NormalizedUserName = TestData.CreateUserCommand.UserName.ToUpper() - }); - await this.AuthenticationDbContext.SaveChangesAsync(); - - await this.ConfigurationDbContext.Clients.AddAsync(new Client - { - ClientId = TestData.ChangeUserPasswordCommand.ClientId, - ClientUri = "http://localhost" - }); - - - await this.ConfigurationDbContext.SaveChangesAsync(); - - List errors = new List(); - errors.Add(new IdentityError()); - - this.SetupRequestHandlers.UserValidator.Setup(s => s.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - this.SetupRequestHandlers.PasswordValidator.Setup(p => p.ValidateAsync(It.IsAny>(), It.IsAny(), - It.IsAny())).ReturnsAsync(IdentityResult.Failed(errors.ToArray())); - - Result result = await this.RequestHandler.Handle(command, CancellationToken.None); - - result.IsFailed.ShouldBeTrue(); - } - - [Fact] - public async Task UserRequestHandler_ProcessPasswordResetConfirmationCommand_ClientNotFound_RequestIsHandled() - { - ProcessPasswordResetConfirmationCommand command = TestData.ProcessPasswordResetConfirmationCommand; - - await this.AuthenticationDbContext.Users.AddAsync(new ApplicationUser - { - Id = TestData.CreateUserCommand.UserId.ToString(), - UserName = TestData.CreateUserCommand.UserName, - NormalizedUserName = TestData.CreateUserCommand.UserName.ToUpper() - }); - await this.AuthenticationDbContext.SaveChangesAsync(); - - this.SetupRequestHandlers.UserValidator.Setup(s => s.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - this.SetupRequestHandlers.PasswordValidator.Setup(p => p.ValidateAsync(It.IsAny>(), It.IsAny(), - It.IsAny())).ReturnsAsync(IdentityResult.Success); - - Result result = await this.RequestHandler.Handle(command, CancellationToken.None); - - result.IsFailed.ShouldBeTrue(); - } - - [Fact] - public async Task UserRequestHandler_ProcessPasswordResetRequestCommand_RequestIsHandled() - { - ProcessPasswordResetRequestCommand command = TestData.ProcessPasswordResetRequestCommand; - - await this.AuthenticationDbContext.Users.AddAsync(new ApplicationUser - { - Id = TestData.CreateUserCommand.UserId.ToString(), - UserName = TestData.CreateUserCommand.UserName, - NormalizedUserName = TestData.CreateUserCommand.UserName.ToUpper() - }); - await this.AuthenticationDbContext.SaveChangesAsync(); - - - this.SetupRequestHandlers.MessagingServiceClient.Setup(m => m.SendEmail(It.IsAny(), - It.IsAny(), - It.IsAny())).ReturnsAsync(Result.Success); - - Result result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - } - - [Fact] - public async Task UserRequestHandler_ProcessPasswordResetRequestCommand_UserNotFound_RequestIsHandled() - { - ProcessPasswordResetRequestCommand command = TestData.ProcessPasswordResetRequestCommand; - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsFailed.ShouldBeTrue(); - } - - [Fact] - public async Task UserRequestHandler_ProcessPasswordResetRequestCommand_MessagingServiceThrowsException_RequestIsHandled() - { - ProcessPasswordResetRequestCommand command = TestData.ProcessPasswordResetRequestCommand; - - await this.AuthenticationDbContext.Users.AddAsync(new ApplicationUser - { - Id = TestData.CreateUserCommand.UserId.ToString(), - UserName = TestData.CreateUserCommand.UserName, - NormalizedUserName = TestData.CreateUserCommand.UserName.ToUpper() - }); - await this.AuthenticationDbContext.SaveChangesAsync(); - - this.SetupRequestHandlers.MessagingServiceClient.Setup(m => m.SendEmail(It.IsAny(), - It.IsAny(), - It.IsAny())).ReturnsAsync(Result.Failure); - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsFailed.ShouldBeTrue(); - } - - [Fact] - public async Task UserRequestHandler_SendWelcomeEmailRequest_RequestIsHandled() - { - SecurityServiceCommands.SendWelcomeEmailCommand command = TestData.SendWelcomeEmailCommand; - - await this.AuthenticationDbContext.Users.AddAsync(new ApplicationUser - { - Id = TestData.CreateUserCommand.UserId.ToString(), - UserName = TestData.CreateUserCommand.UserName, - NormalizedUserName = TestData.CreateUserCommand.UserName.ToUpper() - }); - await this.AuthenticationDbContext.SaveChangesAsync(); - - this.SetupRequestHandlers.UserValidator.Setup(s => s.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - this.SetupRequestHandlers.PasswordValidator.Setup(p => p.ValidateAsync(It.IsAny>(), It.IsAny(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - - this.SetupRequestHandlers.MessagingServiceClient.Setup(m => m.SendEmail(It.IsAny(), - It.IsAny(), - It.IsAny())).ReturnsAsync(Result.Success); - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - } - - [Fact] - public async Task UserRequestHandler_SendWelcomeEmailRequest_MessagingServiceThrowsException_RequestIsHandled() - { - SecurityServiceCommands.SendWelcomeEmailCommand command = TestData.SendWelcomeEmailCommand; - - await this.AuthenticationDbContext.Users.AddAsync(new ApplicationUser - { - Id = TestData.CreateUserCommand.UserId.ToString(), - UserName = TestData.CreateUserCommand.UserName, - NormalizedUserName = TestData.CreateUserCommand.UserName.ToUpper() - }); - await this.AuthenticationDbContext.SaveChangesAsync(); - - this.SetupRequestHandlers.UserValidator.Setup(s => s.ValidateAsync(It.IsAny>(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - this.SetupRequestHandlers.PasswordValidator.Setup(p => p.ValidateAsync(It.IsAny>(), It.IsAny(), It.IsAny())).ReturnsAsync(IdentityResult.Success); - - this.SetupRequestHandlers.MessagingServiceClient.Setup(m => m.SendEmail(It.IsAny(), - It.IsAny(), - It.IsAny())).ReturnsAsync(Result.Failure); - - var result = await this.RequestHandler.Handle(command, CancellationToken.None); - result.IsFailed.ShouldBeTrue(); - } -} diff --git a/archive/SecurityService.UnitTests/RequestHandlerTests.cs b/archive/SecurityService.UnitTests/RequestHandlerTests.cs deleted file mode 100644 index 221f24c2..00000000 --- a/archive/SecurityService.UnitTests/RequestHandlerTests.cs +++ /dev/null @@ -1,224 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace SecurityService.UnitTests { - using BusinessLogic; - using BusinessLogic.RequestHandlers; - using Duende.IdentityServer; - using Duende.IdentityServer.Configuration; - using Duende.IdentityServer.EntityFramework.DbContexts; - using Duende.IdentityServer.EntityFramework.Options; - using Duende.IdentityServer.Services; - using MessagingService.Client; - using Microsoft.AspNetCore.Identity; - using Microsoft.AspNetCore.Identity.EntityFrameworkCore; - using Microsoft.EntityFrameworkCore; - using Microsoft.EntityFrameworkCore.Diagnostics; - using Microsoft.Extensions.Logging.Abstractions; - using Microsoft.Extensions.Options; - using Moq; - using SecurityService.Database.DbContexts; - - //public class TestRoleValidator : IRoleValidator{ - // public async Task ValidateAsync(RoleManager manager, IdentityRole role){ - // if (role.Name == "CreateFailed"){ - // List errors = new List(); - // errors.Add(new IdentityError{ - // Description = "Error", - // Code = "1" - // }); - // return IdentityResult.Failed(errors.ToArray()); - // } - // return IdentityResult.Success; - // } - //} - - //public class CreateUserValidator : IUserValidator - //{ - // public async Task ValidateAsync(UserManager manager, IdentityUser user){ - // if (user.UserName == "CreateFailed") - // { - // List errors = new List(); - // errors.Add(new IdentityError - // { - // Description = "Error", - // Code = "1" - // }); - // return IdentityResult.Failed(errors.ToArray()); - // } - // return IdentityResult.Success; - // } - //} - - //public class AddClaimsToUserUserValidator : IUserValidator - //{ - // public async Task ValidateAsync(UserManager manager, IdentityUser user) - // { - // if (user.UserName == "ClaimsAddFailed") - // { - // List errors = new List(); - // errors.Add(new IdentityError - // { - // Description = "Error", - // Code = "1" - // }); - // return IdentityResult.Failed(errors.ToArray()); - // } - // return IdentityResult.Success; - // } - //} - - public class SetupRequestHandlers{ - - public Mock> PasswordHasher; - public IUserStore UserStore; - public IRoleStore RoleStore; - public List> UserValidators; - public List> RoleValidators; - public List> PasswordValidators; - IdentityErrorDescriber ErrorDescriber = new IdentityErrorDescriber(); - public Mock ServiceProvider; - public Mock MessagingServiceClient; - public ServiceOptions ServiceOptions; - public UserManager UserManager; - public IdentityServerTools IdentityServerTools; - public Mock> Options; - - public Mock> RoleValidator; - public Mock> UserValidator; - public Mock> PasswordValidator; - - - ILookupNormalizer KeyNormalizer = new UpperInvariantLookupNormalizer(); - public SetupRequestHandlers(){ - IdentityOptions identityOptions = new IdentityOptions(); - identityOptions.Tokens.ProviderMap.Add("Default", new TokenProviderDescriptor(typeof(IUserTwoFactorTokenProvider))); - - this.Options = new Mock>(); - this.Options.Setup(o => o.Value).Returns(identityOptions); - - this.PasswordHasher = new Mock>(); - this.RoleValidator = new Mock>(); - this.UserValidator = new Mock>(); - this.UserValidators = new List>(); - this.UserValidators.Add(this.UserValidator.Object); - this.RoleValidators = new List>(); - this.RoleValidators.Add(this.RoleValidator.Object); - this.PasswordValidator = new Mock>(); - this.PasswordValidators = new List>(); - this.PasswordValidators.Add(this.PasswordValidator.Object); - - this.ServiceProvider = new Mock(); - this.ServiceOptions = new ServiceOptions(); - this.IdentityServerTools = this.SetupIdentityServerTools(); - this.MessagingServiceClient = new Mock(); - - this.SetupServiceProvider(); - - } - - private void SetupServiceProvider() - { - Mock> tokenProvider = - new Mock>(); - tokenProvider.Setup(tp => tp.GenerateAsync(It.IsAny(), It.IsAny>(), - It.IsAny())).ReturnsAsync("token"); - - tokenProvider.Setup(tp => tp.ValidateAsync(It.IsAny(), It.IsAny(), - It.IsAny>(), - It.IsAny())).ReturnsAsync(true); - this.ServiceProvider.Setup(sp => sp.GetService(typeof(IUserTwoFactorTokenProvider))).Returns(tokenProvider.Object); - } - - private IdentityServerTools SetupIdentityServerTools() - { - Mock serviceProvider = new Mock(); - Mock issuerNameService = new Mock(); - Mock tokenCreationService = new Mock(); - Mock systemClock = new Mock(); - systemClock.Setup(c => c.UtcNow).Returns(DateTimeOffset.UtcNow); - - serviceProvider.Setup(m => m.GetService(typeof(IdentityServerOptions))).Returns(new IdentityServerOptions()); - - issuerNameService.Setup(i => i.GetCurrentAsync()).ReturnsAsync("Test Issuer"); - - IdentityServerTools identityServerTools = new IdentityServerTools(issuerNameService.Object, tokenCreationService.Object, - systemClock.Object, new IdentityServerOptions()); - - return identityServerTools; - } - - public static ConfigurationDbContext GetConfigurationDbContext(){ - String databaseName = Guid.NewGuid().ToString(); - DbContextOptionsBuilder builder = new DbContextOptionsBuilder().UseInMemoryDatabase(databaseName) - .ConfigureWarnings(w => w.Ignore(InMemoryEventId.TransactionIgnoredWarning)); - ConfigurationDbContext context = new ConfigurationDbContext(builder.Options); - context.StoreOptions = new ConfigurationStoreOptions(); - - return context; - } - - public static AuthenticationDbContext GetAuthenticationDbContext() - { - String databaseName = Guid.NewGuid().ToString(); - DbContextOptionsBuilder builder = new DbContextOptionsBuilder().UseInMemoryDatabase(databaseName) - .ConfigureWarnings(w => w.Ignore(InMemoryEventId.TransactionIgnoredWarning)); - AuthenticationDbContext context = new AuthenticationDbContext(builder.Options); - - return context; - } - - public UserRequestHandler SetUserRequestHandler(ConfigurationDbContext configurationDbContext, AuthenticationDbContext authenticationDbContext) - { - this.UserStore = new UserStore(authenticationDbContext,this.ErrorDescriber); - this.RoleStore = new RoleStore(authenticationDbContext, this.ErrorDescriber); - this.UserManager = - new UserManager(this.UserStore, this.Options.Object, this.PasswordHasher.Object, - this.UserValidators, this.PasswordValidators, - this.KeyNormalizer, this.ErrorDescriber, this.ServiceProvider.Object, - new NullLogger>()); - - this.PasswordHasher.Setup(p => p.HashPassword(It.IsAny(), It.IsAny())).Returns("passwordhash"); - this.PasswordHasher.Setup(p => p.VerifyHashedPassword(It.IsAny(), It.IsAny(), It.IsAny())).Returns(PasswordVerificationResult.Success); - - this.ServiceOptions.ClientId = "clientId"; - - return new UserRequestHandler(this.PasswordHasher.Object, - this.UserManager, - this.ServiceOptions, - this.MessagingServiceClient.Object, - this.IdentityServerTools, - configurationDbContext); - } - - public ApiResourceRequestHandler SetupApiResourceRequestHandler(ConfigurationDbContext configurationDbContext) - { - return new ApiResourceRequestHandler(configurationDbContext); - } - - public ApiScopeRequestHandler SetupApiScopeRequestHandler(ConfigurationDbContext configurationDbContext) - { - return new ApiScopeRequestHandler(configurationDbContext); - } - - public ClientRequestHandler SetupClientRequestHandler(ConfigurationDbContext configurationDbContext) - { - return new ClientRequestHandler(configurationDbContext); - } - - public IdentityResourceRequestHandler SetupIdentityResourceRequestHandler(ConfigurationDbContext configurationDbContext) - { - return new IdentityResourceRequestHandler(configurationDbContext); - } - - public RoleRequestHandler SetupRoleRequestHandler(ConfigurationDbContext configurationDbContext, AuthenticationDbContext authenticationDbContext){ - this.RoleStore = new RoleStore(authenticationDbContext, this.ErrorDescriber); - RoleManager roleManager = new RoleManager(this.RoleStore, - this.RoleValidators, - this.KeyNormalizer, - this.ErrorDescriber, - new NullLogger>()); - return new RoleRequestHandler(roleManager); - } - } -} diff --git a/archive/SecurityService.UnitTests/SecurityService.UnitTests.csproj b/archive/SecurityService.UnitTests/SecurityService.UnitTests.csproj deleted file mode 100644 index 00f13170..00000000 --- a/archive/SecurityService.UnitTests/SecurityService.UnitTests.csproj +++ /dev/null @@ -1,43 +0,0 @@ - - - - net10.0 - Full - false - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers - - - - - - - - - - - - - - - diff --git a/archive/SecurityService.UnitTests/SecurityServiceManagerTestData.cs b/archive/SecurityService.UnitTests/SecurityServiceManagerTestData.cs deleted file mode 100644 index c596a213..00000000 --- a/archive/SecurityService.UnitTests/SecurityServiceManagerTestData.cs +++ /dev/null @@ -1,353 +0,0 @@ -namespace SecurityService.UnitTests -{ - using BusinessLogic.Requests; - using DataTransferObjects; - using Microsoft.AspNetCore.Identity; - using SecurityService.BusinessLogic; - using System; - using System.Collections.Generic; - using System.Linq; - using System.Security.Claims; - using System.Threading.Tasks; - - public class TestData{ - public static String UserName = "00000001"; - - public static String UserName1 = "testaemail1@testing.co.uk"; - - public static String UserName2 = "testaemail2@testing.co.uk"; - - public static String UserName3 = "testbemail3@testing.co.uk"; - - public static String EmailAddress = "testemail1@testing.co.uk"; - - public static String EmailAddress1 = "testemail1@testing.co.uk"; - - public static String EmailAddress2 = "testemail2@testing.co.uk"; - - public static String EmailAddress3 = "testemail3@testing.co.uk"; - - public static String Password = "123456"; - - public static String NewPassword = "654321"; - - public static String PhoneNumber = "07777777777"; - - public static List NullRoles = null; - - public static List EmptyRoles = new List(); - - public static List Roles => new List{ - TestData.RoleName, - }; - - public static Dictionary NullClaims = new Dictionary(); - - public static Dictionary EmptyClaims = new Dictionary(); - - public static Dictionary Claims = new Dictionary(){ - { "Claim1", "Claim1Value" }, - { "Claim2", "Claim2Value" } - }; - - public static String UserId = "92BEFFCD-CA30-4E71-B8EC-F38E7DD63A25"; - - public static String User1Id = "04911949-321d-4a9b-af31-b259160ba94f"; - - public static String User2Id = "b8937737-ec2c-488f-bd95-7d053cb1d36e"; - - public static String User3Id = "da6ce793-1ed5-4116-af89-2878b075ec5a"; - - public static List UserList = new List{ - new ApplicationUser{ - UserName = "00000001", - NormalizedUserName = "00000001", - Email = "00000001@testemail.com", - NormalizedEmail = "00000001@testemail.com", - Id = TestData.User1Id - }, - new ApplicationUser{ - UserName = "00000002", - NormalizedUserName = "00000002", - Email = "00000002@testemail.com", - NormalizedEmail = "00000002@testemail.com", - Id = TestData.User2Id - }, - new ApplicationUser{ - UserName = "00000003", - NormalizedUserName = "00000003", - Email = "00000003@testemail.com", - NormalizedEmail = "00000003@testemail.com", - Id = TestData.User3Id - } - }; - - public static Dictionary> UserRoles = new Dictionary>{ - { - TestData.User1Id, new List(){ - "Role1", - "Role2" - } - },{ - TestData.User2Id, new List(){ - "Role3" - } - },{ - TestData.User3Id, new List(){ - "Role4" - } - }, - }; - - public static Dictionary> UserClaims = new Dictionary>{ - { - TestData.User1Id, new List(){ - new Claim("ClaimType1", "Value1") - } - },{ - TestData.User2Id, new List(){ - new Claim("ClaimType1", "Value2") - } - },{ - TestData.User3Id, new List(){ - new Claim("ClaimType1", "Value3") - } - }, - }; - - public static String GivenName = "GivenName"; - - public static String MiddleName = "MiddleName"; - - public static String FamilyName = "FamilyName"; - - public static IdentityUser IdentityUser = new IdentityUser{ - Id = TestData.UserId, - UserName = TestData.UserName, - Email = TestData.EmailAddress, - PhoneNumber = TestData.PhoneNumber, - }; - - public static String ClientId = "testclient"; - - public static String ClientSecret = "secretvalue"; - - public static String ClientName = "Test Client"; - - public static String ClientDescription = "This is a test client"; - - public static List AllowedScopes = new List{ - "Scope1", - "Scope2" - }; - - public static List AllowedGrantTypes = new List{ - "client_credentials" - }; - public static List AllowedGrantTypesWithHybrid = new List{ - "client_credentials", - "hybrid" - }; - - public static Boolean RequireConsentTrue = true; - - public static Boolean RequireConsentFalse = false; - - public static Boolean AllowOfflineAccessTrue = true; - - public static Boolean AllowOfflineAccessFalse = false; - - public static List EmptyClientRedirectUris = new List(); - - public static String ClientUri = "http://localhost"; - - public static List ClientRedirectUris = new List{ - "http://localhost/signin-oidc" - }; - - public static List EmptyClientPostLogoutRedirectUris = new List(); - - public static List ClientPostLogoutRedirectUris = new List{ - "http://localhost/signout-oidc" - }; - - public static String ApiResourceName = "Test Resource Name"; - - public static String IdentityResourceName = "Identity Resource Name"; - - public static String IdentityResourceDisplayName = "Identity Display Name"; - - public static String ApiResourceDisplayName = "Test Resource Display Name"; - - public static String ApiResourceDescription = "Api Resource Description"; - - public static String IdentityResourceDescription = "Identity Resource Description"; - - public static String ApiResourceSecret = "ApiResourceSecret"; - - public static List EmptyApiResourceScopes = new List(); - - public static List ApiResourceScopes = new List{ - "ApiResourceScope1", - "ApiResourceScope2" - }; - - public static List ApiResourceUserClaims = new List{ - "ApiResourceClaim1", - "ApiResourceClaim2" - }; - - public static List IdentityResourceUserClaims = new List{ - "IdentityResourceClaim1", - "IdentityResourceClaim2" - }; - - public static String RoleName = "TestRole1"; - - public static String Role1Id = "12225B6E-36E9-41E0-B786-A1FBFC86C932"; - - public async static Task> IdentityUsers(){ - - IQueryable result = new List{ - new IdentityUser{ - Id = TestData.User1Id, - UserName = TestData.UserName1, - Email = TestData.EmailAddress1, - PhoneNumber = TestData.PhoneNumber, - }, - new IdentityUser{ - Id = TestData.User2Id, - UserName = TestData.UserName2, - Email = TestData.EmailAddress2, - PhoneNumber = TestData.PhoneNumber, - }, - new IdentityUser{ - Id = TestData.User3Id, - UserName = TestData.UserName3, - Email = TestData.EmailAddress3, - PhoneNumber = TestData.PhoneNumber, - } - }.AsQueryable(); - - return await Task.FromResult(result); - } - - public static IdentityRole IdentityRole = new IdentityRole{ - Id = TestData.Role1Id, - Name = TestData.RoleName - }; - - public static String ApiScopeName = "Test Api Scope"; - - public static String ApiScopeDisplayName = "Test Api Scope Display Name"; - - public static String ApiScopeDescription = "Test Api Scope Description"; - - public static SecurityServiceCommands.CreateUserCommand CreateUserCommand => - new(Guid.Parse(TestData.UserId), - TestData.GivenName, - TestData.MiddleName, - TestData.FamilyName, - TestData.UserName, - TestData.Password, - TestData.EmailAddress, - TestData.PhoneNumber, - TestData.Claims, - TestData.Roles); - - public static SecurityServiceQueries.GetUserQuery GetUserQuery => new(Guid.Parse(TestData.UserId)); - public static SecurityServiceQueries.GetUsersQuery GetUsersQuery => new(null); - - public static SecurityServiceCommands.CreateApiResourceCommand CreateApiResourceCommand => - new(TestData.ApiResourceName, - TestData.ApiResourceDisplayName, - TestData.ApiResourceDescription, - TestData.ApiResourceSecret, - TestData.ApiResourceScopes, - TestData.ApiResourceUserClaims); - - public static SecurityServiceQueries.GetApiResourceQuery GetApiResourceQuery => new(TestData.ApiResourceName); - public static SecurityServiceQueries.GetApiResourcesQuery GetApiResourcesQuery => new(); - - public static SecurityServiceCommands.CreateClientCommand CreateClientCommand => new(TestData.ClientId, - TestData.ClientSecret, - TestData.ClientName, - TestData.ClientDescription, - TestData.AllowedScopes, - TestData.AllowedGrantTypes, - TestData.ClientUri, - TestData.ClientRedirectUris, - TestData.ClientPostLogoutRedirectUris, - TestData.RequireConsentTrue, - TestData.AllowOfflineAccessTrue); - - public static SecurityServiceCommands.CreateClientCommand CreateHybridClientCommand => - new(TestData.ClientId, - TestData.ClientSecret, - TestData.ClientName, - TestData.ClientDescription, - TestData.AllowedScopes, - TestData.AllowedGrantTypesWithHybrid, - TestData.ClientUri, - TestData.ClientRedirectUris, - TestData.ClientPostLogoutRedirectUris, - TestData.RequireConsentTrue, - TestData.AllowOfflineAccessTrue); - - public static SecurityServiceQueries.GetClientQuery GetClientQuery => new(TestData.ClientId); - - public static SecurityServiceQueries.GetClientsQuery GetClientsQuery => new(); - - public static SecurityServiceCommands.CreateApiScopeCommand CreateApiScopeCommand => new(TestData.ApiScopeName, - TestData.ApiScopeDisplayName, - TestData.ApiScopeDescription); - - public static SecurityServiceCommands.CreateIdentityResourceCommand CreateIdentityResourceCommand => new(TestData.IdentityResourceName, - TestData.IdentityResourceDisplayName, - TestData.IdentityResourceDescription, - TestData.IdentityResourceRequired, - TestData.IdentityResourceEmphasize, - TestData.IdentityResourceShowInDiscoveryDocument, - TestData.IdentityResourceUserClaims); - - public static SecurityServiceCommands.CreateRoleCommand CreateRoleCommand => new(Guid.Parse(TestData.Role1Id), TestData.RoleName); - - public static SecurityServiceQueries.GetApiScopeQuery GetApiScopeQuery => new(TestData.ApiScopeName); - public static SecurityServiceQueries.GetApiScopesQuery GetApiScopesQuery => new(); - - public static SecurityServiceQueries.GetIdentityResourceQuery GetIdentityResourceQuery => new(TestData.IdentityResourceName); - - public static SecurityServiceQueries.GetIdentityResourcesQuery GetIdentityResourcesQuery => new(); - - public static SecurityServiceQueries.GetRoleQuery GetRoleQuery => new(Guid.Parse(TestData.Role1Id)); - public static SecurityServiceQueries.GetRolesQuery GetRolesQuery => new(); - - public static Boolean IdentityResourceRequired = true; - - public static Boolean IdentityResourceEmphasize = true; - - public static Boolean IdentityResourceShowInDiscoveryDocument = true; - - public static String ConfirmEmailToken = "Token"; - - public static String PasswordResetToken = "Token"; - - public static SecurityServiceCommands.ChangeUserPasswordCommand ChangeUserPasswordCommand => - new(TestData.UserName, - TestData.Password, - TestData.Password, - TestData.ClientId); - public static SecurityServiceCommands.ConfirmUserEmailAddressCommand ConfirmUserEmailAddressCommand => new(TestData.UserName, - TestData.ConfirmEmailToken); - public static SecurityServiceCommands.ProcessPasswordResetConfirmationCommand ProcessPasswordResetConfirmationCommand =>new (TestData.UserName, - TestData.PasswordResetToken, - TestData.Password, - TestData.ClientId); - - public static SecurityServiceCommands.ProcessPasswordResetRequestCommand ProcessPasswordResetRequestCommand => new(TestData.UserName, TestData.EmailAddress, TestData.ClientId); - - public static SecurityServiceCommands.SendWelcomeEmailCommand SendWelcomeEmailCommand => new(TestData.UserName); - } -} - - diff --git a/archive/SecurityService.UnitTests/UserRequestHandlerTests.cs b/archive/SecurityService.UnitTests/UserRequestHandlerTests.cs deleted file mode 100644 index a9907ded..00000000 --- a/archive/SecurityService.UnitTests/UserRequestHandlerTests.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System; -using System.Linq; -using Microsoft.AspNetCore.Identity; -using SecurityService.BusinessLogic.RequestHandlers; -using Shouldly; -using SimpleResults; -using Xunit; - -namespace SecurityService.UnitTests; - -public class PasswordGeneratorTests -{ - [Fact] - public void GenerateRandomPassword_WithDefaultOptions_ReturnsValidPassword() - { - // Act - Result result = PasswordGenerator.GenerateRandomPassword(); - - // Assert - result.IsSuccess.ShouldBeTrue(); - String password = result.Data; - password.ShouldNotBeNull(); - password.Length.ShouldBeGreaterThanOrEqualTo(8); - password.Count(char.IsUpper).ShouldBeGreaterThan(0); - password.Count(char.IsLower).ShouldBeGreaterThan(0); - password.Count(char.IsDigit).ShouldBeGreaterThan(0); - password.Count(c => "!@$?_-".Contains(c)).ShouldBeGreaterThan(0); - password.Distinct().Count().ShouldBeGreaterThanOrEqualTo(4); - } - - [Fact] - public void GenerateRandomPassword_WithCustomOptions_ReturnsValidPassword() - { - PasswordOptions options = new PasswordOptions - { - RequiredLength = 12, - RequiredUniqueChars = 6, - RequireDigit = true, - RequireLowercase = true, - RequireNonAlphanumeric = true, - RequireUppercase = true - }; - - Result result = PasswordGenerator.GenerateRandomPassword(options); - - result.IsSuccess.ShouldBeTrue(); - String password = result.Data; - password.ShouldNotBeNull(); - password.Length.ShouldBeGreaterThanOrEqualTo(12); - password.Distinct().Count().ShouldBeGreaterThanOrEqualTo(6); - password.Count(char.IsUpper).ShouldBeGreaterThan(0); - password.Count(char.IsLower).ShouldBeGreaterThan(0); - password.Count(char.IsDigit).ShouldBeGreaterThan(0); - password.Count(c => "!@$?_-".Contains(c)).ShouldBeGreaterThan(0); - } - - [Fact] - public void GenerateRandomPassword_TooManyUniqueChars_ReturnsFailure() - { - PasswordOptions options = new PasswordOptions - { - RequiredLength = 10, - RequiredUniqueChars = 100, // Exceeds available unique chars - RequireDigit = true, - RequireLowercase = true, - RequireNonAlphanumeric = true, - RequireUppercase = true - }; - - Result result = PasswordGenerator.GenerateRandomPassword(options); - - result.IsFailed.ShouldBeTrue(); - result.Data.ShouldBeNull(); - result.Message.ShouldNotBeEmpty(); - result.Message.ShouldContain("exceeds available unique characters"); - } - - [Fact] - public void GenerateRandomPassword_NoCategories_FallbackToLowerAndDigits() - { - PasswordOptions options = new PasswordOptions - { - RequiredLength = 8, - RequiredUniqueChars = 4, - RequireDigit = false, - RequireLowercase = false, - RequireNonAlphanumeric = false, - RequireUppercase = false - }; - - Result result = PasswordGenerator.GenerateRandomPassword(options); - - result.IsSuccess.ShouldBeTrue(); - String password = result.Data; - password.ShouldNotBeNull(); - password.Length.ShouldBeGreaterThanOrEqualTo(8); - password.All(c => "abcdefghijkmnopqrstuvwxyz0123456789".Contains(c)).ShouldBeTrue(); - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Common/ClaimExtensions.cs b/archive/SecurityService.UserInterface/Common/ClaimExtensions.cs deleted file mode 100644 index 0adbe7ab..00000000 --- a/archive/SecurityService.UserInterface/Common/ClaimExtensions.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Duende.IdentityModel; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; -using System.Text; -using System.Threading.Tasks; - -namespace SecurityService.UserInterface.Common -{ - public static class ClaimExtensions - { - public static string? GetClaimValue(this IEnumerable claims, params string[] types) - { - return types - .Select(t => claims.FirstOrDefault(c => c.Type == t)?.Value) - .FirstOrDefault(v => v != null); - } - - public static List BuildDisplayNameClaims(this IEnumerable claims) - { - // 1. Name - var name = claims.GetClaimValue(JwtClaimTypes.Name, ClaimTypes.Name); - if (name != null) - { - return new List { new Claim(JwtClaimTypes.Name, name) }; - } - - // 2. Given/Family name fallback - var first = claims.GetClaimValue(JwtClaimTypes.GivenName, ClaimTypes.GivenName); - var last = claims.GetClaimValue(JwtClaimTypes.FamilyName, ClaimTypes.Surname); - - var full = (first, last) switch - { - (not null, not null) => $"{first} {last}", - (not null, null) => first, - (null, not null) => last, - _ => null - }; - - return full != null - ? new List { new Claim(JwtClaimTypes.Name, full) } - : new List(); - } - } -} diff --git a/archive/SecurityService.UserInterface/Pages/Account/AccessDenied.cshtml b/archive/SecurityService.UserInterface/Pages/Account/AccessDenied.cshtml deleted file mode 100644 index fe8647f7..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/AccessDenied.cshtml +++ /dev/null @@ -1,11 +0,0 @@ -@page -@model IdentityServerHost.Pages.Account.AccessDeniedModel -@{ -} - -
-
-

Access Denied

-

You do not have permission to access that resource.

-
-
\ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/AccessDenied.cshtml.cs b/archive/SecurityService.UserInterface/Pages/Account/AccessDenied.cshtml.cs deleted file mode 100644 index 4f97ddda..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/AccessDenied.cshtml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace IdentityServerHost.Pages.Account; - -public class AccessDeniedModel : PageModel -{ - public void OnGet() - { - // No special processing required - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/ChangePassword/Index.cshtml b/archive/SecurityService.UserInterface/Pages/Account/ChangePassword/Index.cshtml deleted file mode 100644 index 9b05d104..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/ChangePassword/Index.cshtml +++ /dev/null @@ -1,48 +0,0 @@ -@page -@using Microsoft.AspNetCore.Mvc.TagHelpers -@model IdentityServerHost.Pages.ChangePassword.Index - -
-

Change Password

-
- - - -
-
-
-

Change Password

-
- -
-
- - - -
- - -
-
- - -
- -
- - -
- -
- - -
- -
- - -
-
-
-
-
\ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/ChangePassword/Index.cshtml.cs b/archive/SecurityService.UserInterface/Pages/Account/ChangePassword/Index.cshtml.cs deleted file mode 100644 index ab445e76..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/ChangePassword/Index.cshtml.cs +++ /dev/null @@ -1,95 +0,0 @@ -using Duende.IdentityServer.Events; -using - Duende.IdentityServer.Models; -using Duende.IdentityServer.Services; -using Duende.IdentityServer.Stores; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; -using SecurityService.Models; -using SimpleResults; - -namespace IdentityServerHost.Pages.ChangePassword; - -using System; -using System.Collections.Specialized; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using System.Web; -using Duende.IdentityServer.EntityFramework.Entities; -using MediatR; -using SecurityService.BusinessLogic; -using SecurityService.BusinessLogic.Requests; -using Shared.Logger; - -[SecurityHeaders] -[AllowAnonymous] -public class Index : PageModel -{ - private readonly IMediator Mediator; - - public ViewModel View { get; set; } - - [BindProperty] - public IndexInputModel Input { get; set; } - - public Index(IMediator mediator) { - this.Mediator = mediator; - } - - public async Task OnGet(String returnUrl) - { - await BuildModelAsync(returnUrl); - - return Page(); - } - - private const String DontMatchMessage = "New Password does not match Confirm Password"; - - private const String ErrorChangingMessage = "An error occurred changing password"; - - public async Task OnPost(CancellationToken cancellationToken) { - await BuildModelAsync(Input.ReturnUrl); - //// the user clicked the "cancel" button - //if (Input.Button == "cancel") { - // return Redirect("Login/Index"); - //} - - if (String.CompareOrdinal(Input.NewPassword, Input.ConfirmPassword) != 0) { - await BuildModelAsync(Input.ReturnUrl); - ModelState.AddModelError(String.Empty, DontMatchMessage); - return this.Page(); - } - - SecurityServiceCommands.ChangeUserPasswordCommand command = new(Input.Username, Input.CurrentPassword, Input.NewPassword, Input.ClientId); - Result? result = await this.Mediator.Send(command, cancellationToken); - - if (result.IsFailed) { - ModelState.AddModelError(String.Empty, ErrorChangingMessage); - return this.Page(); - } - - return this.Redirect(result.Data.RedirectUri); - } - - private async Task BuildModelAsync(String returnUrl) - { - //Logger.LogWarning($"return url is {returnUrl}"); - NameValueCollection queryString = HttpUtility.ParseQueryString(Request.QueryString.ToString()); - - View = new ViewModel(); - - Input = new IndexInputModel - { - ReturnUrl = returnUrl, - ClientId = queryString["clientId"] != null ? queryString["clientId"] : Input.ClientId, - Username = this.User.Identity?.Name, - ConfirmPassword = this.Input?.ConfirmPassword, - CurrentPassword = this.Input?.CurrentPassword, - NewPassword = this.Input?.NewPassword - }; - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/ChangePassword/InputModel.cs b/archive/SecurityService.UserInterface/Pages/Account/ChangePassword/InputModel.cs deleted file mode 100644 index 427d830d..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/ChangePassword/InputModel.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -using System.ComponentModel.DataAnnotations; - -namespace IdentityServerHost.Pages.ChangePassword; - -public class IndexInputModel -{ - public string Username { get; set; } - - public string ReturnUrl { get; set; } - - [Required] - public string CurrentPassword { get; set; } - [Required] - public string NewPassword { get; set; } - - [Required] - public string ConfirmPassword { get; set; } - - public string Button { get; set; } - public string ClientId { get; set; } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/ChangePassword/ViewModel.cs b/archive/SecurityService.UserInterface/Pages/Account/ChangePassword/ViewModel.cs deleted file mode 100644 index d1cb30a0..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/ChangePassword/ViewModel.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -namespace IdentityServerHost.Pages.ChangePassword; - -using System; -using System.Collections.Generic; -using System.Linq; - -public class ViewModel -{ - public string Username { get; set; } - - public string Token { get; set; } - - public string ClientId { get; set; } - - public String UserMessage { get; set; } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/EmailConfirmation/Confirm.cshtml b/archive/SecurityService.UserInterface/Pages/Account/EmailConfirmation/Confirm.cshtml deleted file mode 100644 index 1dad3ced..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/EmailConfirmation/Confirm.cshtml +++ /dev/null @@ -1,21 +0,0 @@ -@page -@using Microsoft.AspNetCore.Mvc.TagHelpers -@model IdentityServerHost.Pages.EmailConfirmation.Confirm - -
-

Email Confirmation

-
- - - -
-
-
-

Confirm Email Address

-
- -
-

@Model.View.UserMessage

-
-
-
\ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/EmailConfirmation/Confirm.cshtml.cs b/archive/SecurityService.UserInterface/Pages/Account/EmailConfirmation/Confirm.cshtml.cs deleted file mode 100644 index a6a1a0a6..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/EmailConfirmation/Confirm.cshtml.cs +++ /dev/null @@ -1,74 +0,0 @@ -using Duende.IdentityServer.Events; -using Duende.IdentityServer.Models; -using Duende.IdentityServer.Services; -using Duende.IdentityServer.Stores; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; -using Shared.Logger; -using SimpleResults; - -namespace IdentityServerHost.Pages.EmailConfirmation; - -using System; -using System.Collections.Specialized; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using System.Web; -using MediatR; -using Microsoft.AspNetCore.Http; -using SecurityService.BusinessLogic; -using SecurityService.BusinessLogic.Requests; - -[SecurityHeaders] -[AllowAnonymous] -public class Confirm : PageModel -{ - private readonly IMediator Mediator; - - public ViewModel View { get; set; } - - [BindProperty] - public ConfirmInputModel Input { get; set; } - - public Confirm(IMediator mediator){ - this.Mediator = mediator; - } - - public async Task OnGet(CancellationToken cancellationToken) { - // Process the query string and populate the view model with username (read only) - await BuildModelAsync(); - - // mark the email address as confirmed - SecurityServiceCommands.ConfirmUserEmailAddressCommand confirmUserEmailAddressCommand= new(Input.Username, Input.Token); - Result? confirmUserEmailAddressResult = await this.Mediator.Send(confirmUserEmailAddressCommand, cancellationToken); - - if (confirmUserEmailAddressResult.IsFailed) { - this.View.UserMessage = $"Failed confirming user email address for username {Input.Username}"; - } - else { - this.View.UserMessage = $"Thanks for confirming your email address, you should receive a welcome email soon."; - // Send the welcome email - SecurityServiceCommands.SendWelcomeEmailCommand command = new(Input.Username); - Result? sendWelcomeEmailResult = await this.Mediator.Send(command, cancellationToken); - if (sendWelcomeEmailResult.IsFailed) - Logger.LogWarning($"Error sending welcome email to {this.Input.Username} [{sendWelcomeEmailResult.Message}]"); - - } - return Page(); - } - - private async Task BuildModelAsync() { - NameValueCollection parsedQueryString = HttpUtility.ParseQueryString(Request.QueryString.ToString()); - String userName = parsedQueryString["userName"]; - String token = parsedQueryString["confirmationToken"]; - this.View = new ViewModel(); - Input = new ConfirmInputModel { - Username = userName, - Token = token, - }; - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/EmailConfirmation/ConfirmInputModel.cs b/archive/SecurityService.UserInterface/Pages/Account/EmailConfirmation/ConfirmInputModel.cs deleted file mode 100644 index 016075c9..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/EmailConfirmation/ConfirmInputModel.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace IdentityServerHost.Pages.EmailConfirmation; - -using System.ComponentModel.DataAnnotations; - -public class ConfirmInputModel -{ - public string Username { get; set; } - public string Token { get; set; } - - [Required] - public string Password { get; set; } - -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/EmailConfirmation/ViewModel.cs b/archive/SecurityService.UserInterface/Pages/Account/EmailConfirmation/ViewModel.cs deleted file mode 100644 index 592160bf..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/EmailConfirmation/ViewModel.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -namespace IdentityServerHost.Pages.EmailConfirmation; - -using System; -using System.Collections.Generic; -using System.Linq; - -public class ViewModel -{ - public string Username { get; set; } - - public string Token { get; set; } - - public String UserMessage { get; set; } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/Confirm.cshtml b/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/Confirm.cshtml deleted file mode 100644 index 94432ce3..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/Confirm.cshtml +++ /dev/null @@ -1,45 +0,0 @@ -@page -@using Microsoft.AspNetCore.Mvc.TagHelpers -@model IdentityServerHost.Pages.ForgotPassword.Confirm - -
- -
-

Reset Password

-
- - - -
-
-

Reset Password

-
- -
-
- - - -
- -
- -
- - -
- -
- - -
- -
- - -
-
-
-
- -
\ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/Confirm.cshtml.cs b/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/Confirm.cshtml.cs deleted file mode 100644 index c764d0ed..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/Confirm.cshtml.cs +++ /dev/null @@ -1,97 +0,0 @@ -using Duende.IdentityServer.Events; -using Duende.IdentityServer.Models; -using Duende.IdentityServer.Services; -using Duende.IdentityServer.Stores; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; -using SimpleResults; - -namespace IdentityServerHost.Pages.ForgotPassword; - -using System; -using System.Collections.Specialized; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using System.Web; -using MediatR; -using Microsoft.AspNetCore.Http; -using SecurityService.BusinessLogic; -using SecurityService.BusinessLogic.Requests; - -[SecurityHeaders] -[AllowAnonymous] -public class Confirm : PageModel -{ - private readonly IMediator Mediator; - - public ViewModel View { get; set; } - - [BindProperty] - public ConfirmInputModel Input { get; set; } - - public Confirm(IMediator mediator){ - this.Mediator = mediator; - } - - public async Task OnGet() { - // Process the query string and populate the view model with username (read only) - await BuildModelAsync(Request.QueryString); - - return Page(); - } - - - public async Task OnPost(CancellationToken cancellationToken) - { - // the user clicked the "cancel" button - if (Input.Button == "cancel") - { - return Redirect("Login/Index"); - } - - if (ModelState.IsValid) { - // process the password change - SecurityServiceCommands.ProcessPasswordResetConfirmationCommand command = new(Input.Username, Input.Token, Input.Password, Input.ClientId); - Result? result= await this.Mediator.Send(command, cancellationToken); - - if (result.IsFailed) { - this.View = new ViewModel - { - Username = Input.Username, - Token = Input.Token, - UserMessage = $"Failed processing password reset for username {Input.Username}: {result.Message}" - }; - return Page(); - } - - return this.Redirect(result.Data); - } - - return Page(); - } - - private async Task BuildModelAsync(QueryString queryString) - { - NameValueCollection parsedQueryString = HttpUtility.ParseQueryString(Request.QueryString.ToString()); - String userName = parsedQueryString["userName"]; - String token = parsedQueryString["resetToken"]; - String clientId = parsedQueryString["clientId"]; - - View = new ViewModel - { - Username = userName, - Token = token - }; - - Input = new ConfirmInputModel - { - Username = userName, - Token = token, - ClientId = clientId - }; - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/ConfirmInputModel.cs b/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/ConfirmInputModel.cs deleted file mode 100644 index f9d6f832..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/ConfirmInputModel.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace IdentityServerHost.Pages.ForgotPassword; - -using System.ComponentModel.DataAnnotations; - -public class ConfirmInputModel -{ - public string Username { get; set; } - public string Token { get; set; } - - [Required] - public string Password { get; set; } - - [Required] - public string ConfirmPassword { get; set; } - - public string Button { get; set; } - public string ClientId { get; set; } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/Index.cshtml b/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/Index.cshtml deleted file mode 100644 index 768beb59..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/Index.cshtml +++ /dev/null @@ -1,47 +0,0 @@ -@page -@using Microsoft.AspNetCore.Mvc.TagHelpers -@model IdentityServerHost.Pages.ForgotPassword.Index - -
- -
-

Forgot Password

-
- - - -
-
-

Forgot Password

-
- - @if (String.IsNullOrEmpty(Model.View.UserMessage)) { -
-
- - - -
- - -
-
- - -
- -
- - -
-
-
- } - else { -
-

@Model.View.UserMessage

-
- } -
- -
\ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/Index.cshtml.cs b/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/Index.cshtml.cs deleted file mode 100644 index 33f2cbd7..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/Index.cshtml.cs +++ /dev/null @@ -1,72 +0,0 @@ -using Duende.IdentityServer.Events; -using Duende.IdentityServer.Models; -using Duende.IdentityServer.Services; -using Duende.IdentityServer.Stores; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace IdentityServerHost.Pages.ForgotPassword; - -using System; -using System.Collections.Specialized; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using System.Web; -using MediatR; -using SecurityService.BusinessLogic; -using SecurityService.BusinessLogic.Requests; - -[SecurityHeaders] -[AllowAnonymous] -public class Index : PageModel{ - private readonly IMediator Mediator; - - public ViewModel View { get; set; } - - [BindProperty] - public IndexInputModel Input { get; set; } - - public Index(IMediator mediator) { - this.Mediator = mediator; - } - - public async Task OnGet(string returnUrl) - { - await BuildModelAsync(returnUrl); - - return Page(); - } - - public async Task OnPost(CancellationToken cancellationToken) - { - // the user clicked the "cancel" button - if (Input.Button == "cancel") { - return Redirect("Login/Index"); - } - SecurityServiceCommands.ProcessPasswordResetRequestCommand command = new(Input.Username, Input.EmailAddress, Input.ClientId); - - await this.Mediator.Send(command, cancellationToken); - - View = new ViewModel() { - UserMessage = "Password Reset sent, please check your registered email for further instructions." - }; - return Page(); - } - - private async Task BuildModelAsync(string returnUrl) - { - NameValueCollection queryString = HttpUtility.ParseQueryString(Request.QueryString.ToString()); - - View = new ViewModel(); - - Input = new IndexInputModel - { - ReturnUrl = returnUrl, - ClientId = queryString["clientId"] - }; - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/InputModel.cs b/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/InputModel.cs deleted file mode 100644 index 76ee5fba..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/InputModel.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -using System.ComponentModel.DataAnnotations; - -namespace IdentityServerHost.Pages.ForgotPassword; - -public class IndexInputModel -{ - [Required] - public string Username { get; set; } - - public string ReturnUrl { get; set; } - - [Required] - public string EmailAddress { get; set; } - - public string Button { get; set; } - public string ClientId { get; set; } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/ViewModel.cs b/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/ViewModel.cs deleted file mode 100644 index 4cf89645..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/ForgotPassword/ViewModel.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -namespace IdentityServerHost.Pages.ForgotPassword; - -using System; -using System.Collections.Generic; -using System.Linq; - -public class ViewModel -{ - public string Username { get; set; } - - public string Token { get; set; } - - public String UserMessage { get; set; } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/Login/Index.cshtml b/archive/SecurityService.UserInterface/Pages/Account/Login/Index.cshtml deleted file mode 100644 index c462e980..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/Login/Index.cshtml +++ /dev/null @@ -1,92 +0,0 @@ -@page -@using Microsoft.AspNetCore.Mvc.TagHelpers -@model IdentityServerHost.Pages.Login.Index - -
- -
-

Login

-

Choose how to login

-
- - - -
- - @if (Model.View.EnableLocalLogin) - { -
-
-
-

Local Account

-
- -
-
- - - -
- - -
-
- - -
- - @if (Model.View.AllowRememberLogin) - { -
-
- - -
-
- } - -
- - - -
-
-
-
-
- } - - @if (Model.View.VisibleExternalProviders.Any()) - { -
-
-
-

External Account

-
-
-
- @foreach (var provider in Model.View.VisibleExternalProviders) - { - - @provider.DisplayName - - } -
-
-
-
- } - - @if (!Model.View.EnableLocalLogin && !Model.View.VisibleExternalProviders.Any()) - { -
- Invalid login request -

There are no login schemes configured for this request.

-
- } -
\ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/Login/Index.cshtml.cs b/archive/SecurityService.UserInterface/Pages/Account/Login/Index.cshtml.cs deleted file mode 100644 index 3e972b0e..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/Login/Index.cshtml.cs +++ /dev/null @@ -1,263 +0,0 @@ -using Duende.IdentityServer.Events; -using Duende.IdentityServer.Models; -using Duende.IdentityServer.Services; -using Duende.IdentityServer.Stores; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; -using SecurityService.BusinessLogic; - -namespace IdentityServerHost.Pages.Login; - -using Polly; -using System; -using System.Linq; -using System.Threading.Tasks; - -[SecurityHeaders] -[AllowAnonymous] -public class Index : PageModel -{ - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; - private readonly IIdentityServerInteractionService _interaction; - private readonly IEventService _events; - private readonly IAuthenticationSchemeProvider _schemeProvider; - private readonly IIdentityProviderStore _identityProviderStore; - - public ViewModel View { get; set; } - - [BindProperty] - public InputModel Input { get; set; } - - public Index( - IIdentityServerInteractionService interaction, - IAuthenticationSchemeProvider schemeProvider, - IIdentityProviderStore identityProviderStore, - IEventService events, - UserManager userManager, - SignInManager signInManager) - { - _userManager = userManager; - _signInManager = signInManager; - _interaction = interaction; - _schemeProvider = schemeProvider; - _identityProviderStore = identityProviderStore; - _events = events; - } - - public async Task OnGet(string returnUrl) - { - await BuildModelAsync(returnUrl); - - if (View.IsExternalLoginOnly) - { - // we only have one option for logging in and it's an external provider - return RedirectToPage("/ExternalLogin/Challenge", new { scheme = View.ExternalLoginScheme, returnUrl }); - } - - return Page(); - } - - public async Task OnPost() - { - // check if we are in the context of an authorization request - AuthorizationRequest? context = await _interaction.GetAuthorizationContextAsync(Input.ReturnUrl); - - // the user clicked the "cancel" button - if (Input.Button == "forgotpassword") { - return Redirect($"ForgotPassword/Index?clientId={Input.ClientId}"); - } - - // the user clicked the "cancel" button - if (Input.Button != "login") { - return await HandleCancelButton(context); - } - - if (ModelState.IsValid) { - return await HandleLoginButton(context); - } - - // something went wrong, show form with error - await BuildModelAsync(Input.ReturnUrl); - return Page(); - } - - private async Task HandleCancelButton(AuthorizationRequest? context) { - if (context != null) - { - // if the user cancels, send a result back into IdentityServer as if they - // denied the consent (even if this client does not require consent). - // this will send back an access denied OIDC error response to the client. - await _interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied); - - // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null - if (context.IsNativeClient()) - { - // The client is native, so this change in how to - // return the response is for better UX for the end user. - return this.LoadingPage(Input.ReturnUrl); - } - - return Redirect(Input.ReturnUrl); - } - - // since we don't have a valid context, then we just go back to the home page - return Redirect("~/"); - } - - private async Task HandleLoginButton(AuthorizationRequest? context) { - var result = await _signInManager.PasswordSignInAsync(Input.Username, Input.Password, Input.RememberLogin, lockoutOnFailure: true); - if (result.Succeeded) { - var user = await _userManager.FindByNameAsync(Input.Username); - await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id, user.UserName, clientId: context?.Client.ClientId)); - - if (context != null) { - if (context.IsNativeClient()) { - // The client is native, so this change in how to - // return the response is for better UX for the end user. - return this.LoadingPage(Input.ReturnUrl); - } - - // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null - return Redirect(Input.ReturnUrl); - } - - // request for a local page - if (Url.IsLocalUrl(Input.ReturnUrl)) { - return Redirect(Input.ReturnUrl); - } - - if (string.IsNullOrEmpty(Input.ReturnUrl)) { - return Redirect("~/"); - } - - // user might have clicked on a malicious link - should be logged - throw new ArgumentException("invalid return URL"); - } - - await _events.RaiseAsync(new UserLoginFailureEvent(Input.Username, "invalid credentials", clientId: context?.Client.ClientId)); - ModelState.AddModelError(string.Empty, LoginOptions.InvalidCredentialsErrorMessage); - - return this.Page(); - } - - private async Task BuildModelAsync(string returnUrl) - { - Input = CreateInputModel(returnUrl); - - var context = await _interaction.GetAuthorizationContextAsync(returnUrl); - - if (await TryBuildSingleIdpViewAsync(context)) - return; - - var providers = await GetExternalProvidersAsync(context?.Client); - - View = CreateViewModel(context?.Client, providers); - } - - private InputModel CreateInputModel(string returnUrl) => - new() - { - ReturnUrl = returnUrl - }; - - private async Task TryBuildSingleIdpViewAsync(AuthorizationRequest? context) - { - if (context?.IdP == null) - return false; - - if (await _schemeProvider.GetSchemeAsync(context.IdP) == null) - return false; - - var isLocal = context.IdP == Duende.IdentityServer.IdentityServerConstants.LocalIdentityProvider; - - View = new ViewModel - { - EnableLocalLogin = isLocal, - ExternalProviders = isLocal - ? Array.Empty() - : new[] - { - new ViewModel.ExternalProvider - { - AuthenticationScheme = context.IdP - } - } - }; - - Input.Username = context.LoginHint; - - return true; - } - private async Task> GetExternalProvidersAsync(Client? client) - { - var providers = await GetStaticProvidersAsync(); - providers.AddRange(await GetDynamicProvidersAsync()); - - return ApplyClientRestrictions(providers, client); - } - - private async Task> GetStaticProvidersAsync() - { - var schemes = await _schemeProvider.GetAllSchemesAsync(); - - return schemes - .Where(s => s.DisplayName != null) - .Select(s => new ViewModel.ExternalProvider - { - AuthenticationScheme = s.Name, - DisplayName = s.DisplayName! - }) - .ToList(); - } - - private async Task> GetDynamicProvidersAsync() - { - var schemes = await _identityProviderStore.GetAllSchemeNamesAsync(); - - return schemes - .Where(s => s.Enabled) - .Select(s => new ViewModel.ExternalProvider - { - AuthenticationScheme = s.Scheme, - DisplayName = s.DisplayName - }); - } - - private List ApplyClientRestrictions( - List providers, - Client? client) - { - if (client == null) - return providers; - - Input.ClientId = client.ClientId; - - if (client.IdentityProviderRestrictions?.Any() == true) - { - providers = providers - .Where(p => client.IdentityProviderRestrictions.Contains(p.AuthenticationScheme)) - .ToList(); - } - - return providers; - } - - private ViewModel CreateViewModel( - Client? client, - IEnumerable providers) - { - var allowLocal = client?.EnableLocalLogin ?? true; - - return new ViewModel - { - AllowRememberLogin = LoginOptions.AllowRememberLogin, - EnableLocalLogin = allowLocal && LoginOptions.AllowLocalLogin, - ExternalProviders = providers.ToArray() - }; - } - -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/Login/InputModel.cs b/archive/SecurityService.UserInterface/Pages/Account/Login/InputModel.cs deleted file mode 100644 index 9f984e04..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/Login/InputModel.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - - -using System.ComponentModel.DataAnnotations; - -namespace IdentityServerHost.Pages.Login; - -public class InputModel -{ - [Required] - public string Username { get; set; } - - [Required] - public string Password { get; set; } - - public bool RememberLogin { get; set; } - - public string ReturnUrl { get; set; } - public string ClientId { get; set; } - - public string Button { get; set; } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/Login/LoginOptions.cs b/archive/SecurityService.UserInterface/Pages/Account/Login/LoginOptions.cs deleted file mode 100644 index 1f994515..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/Login/LoginOptions.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace IdentityServerHost.Pages.Login; - -using System; - -public static class LoginOptions -{ - public static readonly bool AllowLocalLogin = true; - public static readonly bool AllowRememberLogin = true; - public static readonly TimeSpan RememberMeLoginDuration = TimeSpan.FromDays(30); - public static readonly string InvalidCredentialsErrorMessage = "Invalid username or password"; -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/Login/ViewModel.cs b/archive/SecurityService.UserInterface/Pages/Account/Login/ViewModel.cs deleted file mode 100644 index 98f064cc..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/Login/ViewModel.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -namespace IdentityServerHost.Pages.Login; - -using System; -using System.Collections.Generic; -using System.Linq; - -public class ViewModel -{ - public bool AllowRememberLogin { get; set; } = true; - public bool EnableLocalLogin { get; set; } = true; - - public String Client { get; set; } - - public IEnumerable ExternalProviders { get; set; } = Enumerable.Empty(); - public IEnumerable VisibleExternalProviders => ExternalProviders.Where(x => !String.IsNullOrWhiteSpace(x.DisplayName)); - - public bool IsExternalLoginOnly => EnableLocalLogin == false && ExternalProviders?.Count() == 1; - public string ExternalLoginScheme => IsExternalLoginOnly ? ExternalProviders?.SingleOrDefault()?.AuthenticationScheme : null; - - public class ExternalProvider - { - public string DisplayName { get; set; } - public string AuthenticationScheme { get; set; } - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/Logout/Index.cshtml b/archive/SecurityService.UserInterface/Pages/Account/Logout/Index.cshtml deleted file mode 100644 index 77daba8c..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/Logout/Index.cshtml +++ /dev/null @@ -1,13 +0,0 @@ -@page -@using Microsoft.AspNetCore.Mvc.TagHelpers -@model IdentityServerHost.Pages.Logout.Index - -
-

Logout

-

Would you like to logout of IdentityServer?

-
- -
- - -
\ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/Logout/Index.cshtml.cs b/archive/SecurityService.UserInterface/Pages/Account/Logout/Index.cshtml.cs deleted file mode 100644 index c9662bc4..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/Logout/Index.cshtml.cs +++ /dev/null @@ -1,102 +0,0 @@ -using Duende.IdentityModel; -using Duende.IdentityServer.Events; -using Duende.IdentityServer.Extensions; -using Duende.IdentityServer.Services; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace IdentityServerHost.Pages.Logout; - -using SecurityService.BusinessLogic; -using System.Threading.Tasks; - -[SecurityHeaders] -[AllowAnonymous] -public class Index : PageModel -{ - private readonly SignInManager _signInManager; - private readonly IIdentityServerInteractionService _interaction; - private readonly IEventService _events; - - [BindProperty] - public string LogoutId { get; set; } - - public Index(SignInManager signInManager, IIdentityServerInteractionService interaction, IEventService events) - { - _signInManager = signInManager; - _interaction = interaction; - _events = events; - } - - public async Task OnGet(string logoutId) - { - LogoutId = logoutId; - - var showLogoutPrompt = LogoutOptions.ShowLogoutPrompt; - - if (User?.Identity.IsAuthenticated != true) - { - // if the user is not authenticated, then just show logged out page - showLogoutPrompt = false; - } - else - { - var context = await _interaction.GetLogoutContextAsync(LogoutId); - if (context?.ShowSignoutPrompt == false) - { - // it's safe to automatically sign-out - showLogoutPrompt = false; - } - } - - if (showLogoutPrompt == false) - { - // if the request for logout was properly authenticated from IdentityServer, then - // we don't need to show the prompt and can just log the user out directly. - return await OnPost(); - } - - return Page(); - } - - public async Task OnPost() - { - if (User?.Identity.IsAuthenticated == true) - { - // if there's no current logout context, we need to create one - // this captures necessary info from the current logged in user - // this can still return null if there is no context needed - LogoutId ??= await _interaction.CreateLogoutContextAsync(); - - // delete local authentication cookie - await _signInManager.SignOutAsync(); - - // raise the logout event - await _events.RaiseAsync(new UserLogoutSuccessEvent(User.GetSubjectId(), User.GetDisplayName())); - - // see if we need to trigger federated logout - var idp = User.FindFirst(JwtClaimTypes.IdentityProvider)?.Value; - - // if it's a local login we can ignore this workflow - if (idp != null && idp != Duende.IdentityServer.IdentityServerConstants.LocalIdentityProvider) - { - // we need to see if the provider supports external logout - if (await HttpContext.GetSchemeSupportsSignOutAsync(idp)) - { - // build a return URL so the upstream provider will redirect back - // to us after the user has logged out. this allows us to then - // complete our single sign-out processing. - string url = Url.Page("/Account/Logout/Loggedout", new { logoutId = LogoutId }); - - // this triggers a redirect to the external provider for sign-out - return SignOut(new AuthenticationProperties { RedirectUri = url }, idp); - } - } - } - - return RedirectToPage("/Account/Logout/LoggedOut", new { logoutId = LogoutId }); - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/Logout/LoggedOut.cshtml b/archive/SecurityService.UserInterface/Pages/Account/Logout/LoggedOut.cshtml deleted file mode 100644 index 39830321..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/Logout/LoggedOut.cshtml +++ /dev/null @@ -1,37 +0,0 @@ -@page -@model IdentityServerHost.Pages.Logout.LoggedOut - -
-
-
-
- - - -
-

Logged Out

-

You are now logged out

- - @if (Model.View.PostLogoutRedirectUri != null) - { -

- Click here to return to the - @Model.View.ClientName application. -

- } -
-
-
- -@if (Model.View.SignOutIframeUrl != null) -{ - -} - -@section scripts -{ - @if (Model.View.AutomaticRedirectAfterSignOut) - { - - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/Logout/LoggedOut.cshtml.cs b/archive/SecurityService.UserInterface/Pages/Account/Logout/LoggedOut.cshtml.cs deleted file mode 100644 index c0f01628..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/Logout/LoggedOut.cshtml.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Duende.IdentityServer.Services; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace IdentityServerHost.Pages.Logout; - -using System; -using System.Threading.Tasks; - -[SecurityHeaders] -[AllowAnonymous] -public class LoggedOut : PageModel -{ - private readonly IIdentityServerInteractionService _interactionService; - - public LoggedOutViewModel View { get; set; } - - public LoggedOut(IIdentityServerInteractionService interactionService) - { - _interactionService = interactionService; - } - - public async Task OnGet(string logoutId) - { - // get context information (client name, post logout redirect URI and iframe for federated signout) - var logout = await _interactionService.GetLogoutContextAsync(logoutId); - - View = new LoggedOutViewModel - { - AutomaticRedirectAfterSignOut = LogoutOptions.AutomaticRedirectAfterSignOut, - PostLogoutRedirectUri = logout?.PostLogoutRedirectUri, - ClientName = String.IsNullOrEmpty(logout?.ClientName) ? logout?.ClientId : logout?.ClientName, - SignOutIframeUrl = logout?.SignOutIFrameUrl - }; - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/Logout/LoggedOutViewModel.cs b/archive/SecurityService.UserInterface/Pages/Account/Logout/LoggedOutViewModel.cs deleted file mode 100644 index 77b1ef09..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/Logout/LoggedOutViewModel.cs +++ /dev/null @@ -1,14 +0,0 @@ - -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - - -namespace IdentityServerHost.Pages.Logout; - -public class LoggedOutViewModel -{ - public string PostLogoutRedirectUri { get; set; } - public string ClientName { get; set; } - public string SignOutIframeUrl { get; set; } - public bool AutomaticRedirectAfterSignOut { get; set; } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Account/Logout/LogoutOptions.cs b/archive/SecurityService.UserInterface/Pages/Account/Logout/LogoutOptions.cs deleted file mode 100644 index e395c303..00000000 --- a/archive/SecurityService.UserInterface/Pages/Account/Logout/LogoutOptions.cs +++ /dev/null @@ -1,8 +0,0 @@ - -namespace IdentityServerHost.Pages.Logout; - -public static class LogoutOptions -{ - public static readonly bool ShowLogoutPrompt = true; - public static readonly bool AutomaticRedirectAfterSignOut = false; -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Ciba/All.cshtml b/archive/SecurityService.UserInterface/Pages/Ciba/All.cshtml deleted file mode 100644 index d5fad0ae..00000000 --- a/archive/SecurityService.UserInterface/Pages/Ciba/All.cshtml +++ /dev/null @@ -1,49 +0,0 @@ -@page -@using Microsoft.AspNetCore.Mvc.TagHelpers -@model IdentityServerHost.Pages.Ciba.AllModel -@{ -} - -
-
-
-
-
-

Pending Backchannel Login Requests

-
-
- @if (Model.Logins?.Any() == true) - { - - - - - - - - - - - @foreach (var login in Model.Logins) - { - - - - - - - } - -
IdClient IdBinding Message
@login.InternalId@login.Client.ClientId@login.BindingMessage - Process -
- } - else - { -
No Pending Login Requests
- } -
-
-
-
-
\ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Ciba/All.cshtml.cs b/archive/SecurityService.UserInterface/Pages/Ciba/All.cshtml.cs deleted file mode 100644 index d7e4aabc..00000000 --- a/archive/SecurityService.UserInterface/Pages/Ciba/All.cshtml.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -using System.ComponentModel.DataAnnotations; -using Duende.IdentityServer.Models; -using Duende.IdentityServer.Services; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace IdentityServerHost.Pages.Ciba; - -using System.Collections.Generic; -using System.Threading.Tasks; - -[SecurityHeaders] -[Authorize] -public class AllModel : PageModel -{ - public IEnumerable Logins { get; set; } - - [BindProperty, Required] - public string Id { get; set; } - [BindProperty, Required] - public string Button { get; set; } - - private readonly IBackchannelAuthenticationInteractionService _backchannelAuthenticationInteraction; - - public AllModel(IBackchannelAuthenticationInteractionService backchannelAuthenticationInteractionService) - { - _backchannelAuthenticationInteraction = backchannelAuthenticationInteractionService; - } - - public async Task OnGet() - { - Logins = await _backchannelAuthenticationInteraction.GetPendingLoginRequestsForCurrentUserAsync(); - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Ciba/Consent.cshtml b/archive/SecurityService.UserInterface/Pages/Ciba/Consent.cshtml deleted file mode 100644 index df1e63b1..00000000 --- a/archive/SecurityService.UserInterface/Pages/Ciba/Consent.cshtml +++ /dev/null @@ -1,99 +0,0 @@ -@page -@using Microsoft.AspNetCore.Mvc.TagHelpers -@model IdentityServerHost.Pages.Ciba.Consent -@{ -} - - diff --git a/archive/SecurityService.UserInterface/Pages/Ciba/Consent.cshtml.cs b/archive/SecurityService.UserInterface/Pages/Ciba/Consent.cshtml.cs deleted file mode 100644 index 01587e4f..00000000 --- a/archive/SecurityService.UserInterface/Pages/Ciba/Consent.cshtml.cs +++ /dev/null @@ -1,287 +0,0 @@ -using Duende.IdentityServer.Events; -using Duende.IdentityServer.Extensions; -using Duende.IdentityServer.Models; -using Duende.IdentityServer.Services; -using Duende.IdentityServer.Validation; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace IdentityServerHost.Pages.Ciba; - -using Azure.Core; -using MediatR; -using Microsoft.Extensions.Logging; -using SimpleResults; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -[Authorize] -[SecurityHeadersAttribute] -public class Consent : PageModel -{ - private readonly IBackchannelAuthenticationInteractionService _interaction; - private readonly IEventService _events; - private readonly ILogger _logger; - - public Consent( - IBackchannelAuthenticationInteractionService interaction, - IEventService events, - ILogger logger) - { - _interaction = interaction; - _events = events; - _logger = logger; - } - - public ViewModel View { get; set; } - - [BindProperty] - public InputModel Input { get; set; } - - public async Task OnGet(string id) - { - View = await BuildViewModelAsync(id); - if (View == null) - { - return RedirectToPage("/Home/Error/Index"); - } - - Input = new InputModel - { - Id = id - }; - - return Page(); - } - - private async Task HandleNoButtonClicked(BackchannelUserLoginRequest request) { - CompleteBackchannelLoginRequest result = new(Input.Id); - - // emit event - await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues)); - - return result; - } - - private async Task HandleYesButtonClicked(BackchannelUserLoginRequest request) { - // if the user consented to some scope, build the response model - if (Input.ScopesConsented != null && Input.ScopesConsented.Any()) - { - var scopes = Input.ScopesConsented; - if (ConsentOptions.EnableOfflineAccess == false) - { - scopes = scopes.Where(x => x != Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess); - } - - CompleteBackchannelLoginRequest result = new CompleteBackchannelLoginRequest(Input.Id) - { - ScopesValuesConsented = scopes.ToArray(), - Description = Input.Description - }; - - // emit event - await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, result.ScopesValuesConsented, false)); - return result; - } - - this.ModelState.AddModelError("", ConsentOptions.MustChooseOneErrorMessage); - return null; - } - - public async Task OnPost() - { - // validate return url is still valid - BackchannelUserLoginRequest? request = await _interaction.GetLoginRequestByInternalIdAsync(Input.Id); - if (request == null || request.Subject.GetSubjectId() != User.GetSubjectId()) { - _logger.LogError("Invalid id {id}", Input.Id); - return RedirectToPage("/Home/Error/Index"); - } - - CompleteBackchannelLoginRequest result = await HandleButtonClickAsync(request); - - if (result != null) { - // communicate outcome of consent back to identityserver - await _interaction.CompleteLoginRequestAsync(result); - return RedirectToPage("/Ciba/All"); - } - - // we need to redisplay the consent UI - View = await BuildViewModelAsync(Input.Id, Input); - return Page(); - } - - private async Task HandleButtonClickAsync(BackchannelUserLoginRequest request) - { - switch (Input?.Button) - { - case "no": - return await HandleNoButtonClicked(request); - case "yes": - return await HandleYesButtonClicked(request); - default: - ModelState.AddModelError("", ConsentOptions.InvalidSelectionErrorMessage); - return null; - } - } - - private async Task BuildViewModelAsync(string id, InputModel model = null) - { - var request = await _interaction.GetLoginRequestByInternalIdAsync(id); - if (request != null && request.Subject.GetSubjectId() == User.GetSubjectId()) - { - return CreateConsentViewModel(model, request); - } - else - { - _logger.LogError("No backchannel login request matching id: {id}", id); - } - return null; - } - - private ViewModel CreateConsentViewModel( - InputModel model, - BackchannelUserLoginRequest request) - { - var vm = CreateBaseViewModel(request); - - vm.IdentityScopes = CreateIdentityScopes(model, request); - vm.ApiScopes = CreateApiScopes(model, request); - - return vm; - } - - private ViewModel CreateBaseViewModel(BackchannelUserLoginRequest request) => - new() - { - ClientName = request.Client.ClientName ?? request.Client.ClientId, - ClientUrl = request.Client.ClientUri, - ClientLogoUrl = request.Client.LogoUri, - BindingMessage = request.BindingMessage - }; - - private ScopeViewModel[] CreateIdentityScopes(InputModel model, - BackchannelUserLoginRequest request) - { - return request.ValidatedResources.Resources.IdentityResources - .Select(resource => - CreateScopeViewModel( - resource, - IsConsented(model, resource.Name))) - .ToArray(); - } - - private List CreateApiScopes(InputModel model, - BackchannelUserLoginRequest request) - { - var apiScopes = request.ValidatedResources.ParsedScopes - .Select(parsed => CreateApiScope(parsed, model, request)) - .Where(scope => scope != null) - .ToList()!; - - AddOfflineAccessIfNeeded(apiScopes, model, request); - - return apiScopes; - } - - private ScopeViewModel? CreateApiScope(ParsedScopeValue parsedScope, - InputModel model, - BackchannelUserLoginRequest request) - { - var apiScope = request.ValidatedResources.Resources - .FindApiScope(parsedScope.ParsedName); - - if (apiScope == null) - return null; - - var scopeVm = CreateScopeViewModel( - parsedScope, - apiScope, - IsConsented(model, parsedScope.RawValue)); - - scopeVm.Resources = CreateApiResources(parsedScope, request); - - return scopeVm; - } - - private ResourceViewModel[] CreateApiResources(ParsedScopeValue parsedScope, - BackchannelUserLoginRequest request) - { - var resourceIndicators = request.RequestedResourceIndicators ?? Enumerable.Empty(); - - return request.ValidatedResources.Resources.ApiResources - .Where(r => resourceIndicators.Contains(r.Name)) - .Where(r => r.Scopes.Contains(parsedScope.ParsedName)) - .Select(r => new ResourceViewModel - { - Name = r.Name, - DisplayName = r.DisplayName ?? r.Name - }) - .ToArray(); - } - - private void AddOfflineAccessIfNeeded(List apiScopes, - InputModel model, - BackchannelUserLoginRequest request) - { - if (!ConsentOptions.EnableOfflineAccess || - !request.ValidatedResources.Resources.OfflineAccess) - { - return; - } - - apiScopes.Add(GetOfflineAccessScope(IsConsented(model, Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess))); - } - - private static bool IsConsented(InputModel model, string scopeName) => - model?.ScopesConsented == null || model.ScopesConsented.Contains(scopeName); - - - private ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check) - { - return new ScopeViewModel - { - Name = identity.Name, - Value = identity.Name, - DisplayName = identity.DisplayName ?? identity.Name, - Description = identity.Description, - Emphasize = identity.Emphasize, - Required = identity.Required, - Checked = check || identity.Required - }; - } - - public ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScopeValue, ApiScope apiScope, bool check) - { - var displayName = apiScope.DisplayName ?? apiScope.Name; - if (!String.IsNullOrWhiteSpace(parsedScopeValue.ParsedParameter)) - { - displayName += ":" + parsedScopeValue.ParsedParameter; - } - - return new ScopeViewModel - { - Name = parsedScopeValue.ParsedName, - Value = parsedScopeValue.RawValue, - DisplayName = displayName, - Description = apiScope.Description, - Emphasize = apiScope.Emphasize, - Required = apiScope.Required, - Checked = check || apiScope.Required - }; - } - - private ScopeViewModel GetOfflineAccessScope(bool check) - { - return new ScopeViewModel - { - Value = Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess, - DisplayName = ConsentOptions.OfflineAccessDisplayName, - Description = ConsentOptions.OfflineAccessDescription, - Emphasize = true, - Checked = check - }; - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Ciba/ConsentOptions.cs b/archive/SecurityService.UserInterface/Pages/Ciba/ConsentOptions.cs deleted file mode 100644 index c7545fa9..00000000 --- a/archive/SecurityService.UserInterface/Pages/Ciba/ConsentOptions.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - - -namespace IdentityServerHost.Pages.Ciba; - -public static class ConsentOptions -{ - public static readonly bool EnableOfflineAccess = true; - public static readonly string OfflineAccessDisplayName = "Offline Access"; - public static readonly string OfflineAccessDescription = "Access to your applications and resources, even when you are offline"; - - public static readonly string MustChooseOneErrorMessage = "You must pick at least one permission"; - public static readonly string InvalidSelectionErrorMessage = "Invalid selection"; -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Ciba/Index.cshtml b/archive/SecurityService.UserInterface/Pages/Ciba/Index.cshtml deleted file mode 100644 index 6a81cb52..00000000 --- a/archive/SecurityService.UserInterface/Pages/Ciba/Index.cshtml +++ /dev/null @@ -1,29 +0,0 @@ -@page -@using Microsoft.AspNetCore.Mvc.TagHelpers -@model IdentityServerHost.Pages.Ciba.IndexModel -@{ -} - -
- @if (Model.LoginRequest.Client.LogoUri != null) - { - - } -

- @Model.LoginRequest.Client.ClientName - is requesting your permission -

-
- -
-
-

- Verify that this identifier matches what the client is displaying: - @Model.LoginRequest.BindingMessage -

-

Do you wish to continue?

- -
-
diff --git a/archive/SecurityService.UserInterface/Pages/Ciba/Index.cshtml.cs b/archive/SecurityService.UserInterface/Pages/Ciba/Index.cshtml.cs deleted file mode 100644 index b6b4e053..00000000 --- a/archive/SecurityService.UserInterface/Pages/Ciba/Index.cshtml.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -using Duende.IdentityServer.Models; -using Duende.IdentityServer.Services; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace IdentityServerHost.Pages.Ciba; - -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; - -[AllowAnonymous] -[SecurityHeaders] -public class IndexModel : PageModel -{ - public BackchannelUserLoginRequest LoginRequest { get; set; } - - private readonly IBackchannelAuthenticationInteractionService _backchannelAuthenticationInteraction; - private readonly ILogger _logger; - - public IndexModel(IBackchannelAuthenticationInteractionService backchannelAuthenticationInteractionService, ILogger logger) - { - _backchannelAuthenticationInteraction = backchannelAuthenticationInteractionService; - _logger = logger; - } - - public async Task OnGet(string id) - { - LoginRequest = await _backchannelAuthenticationInteraction.GetLoginRequestByInternalIdAsync(id); - if (LoginRequest == null) - { - _logger.LogWarning("Invalid backchannel login id {id}", id); - return RedirectToPage("/Home/Error/Index"); - } - - return Page(); - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Ciba/InputModel.cs b/archive/SecurityService.UserInterface/Pages/Ciba/InputModel.cs deleted file mode 100644 index 89b1c6ad..00000000 --- a/archive/SecurityService.UserInterface/Pages/Ciba/InputModel.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -namespace IdentityServerHost.Pages.Ciba; - -using System.Collections.Generic; - -public class InputModel -{ - public string Button { get; set; } - public IEnumerable ScopesConsented { get; set; } - public string Id { get; set; } - public string Description { get; set; } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Ciba/ViewModel.cs b/archive/SecurityService.UserInterface/Pages/Ciba/ViewModel.cs deleted file mode 100644 index 1ffb513f..00000000 --- a/archive/SecurityService.UserInterface/Pages/Ciba/ViewModel.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -namespace IdentityServerHost.Pages.Ciba; - -using System.Collections.Generic; - -public class ViewModel -{ - public string ClientName { get; set; } - public string ClientUrl { get; set; } - public string ClientLogoUrl { get; set; } - - public string BindingMessage { get; set; } - - public IEnumerable IdentityScopes { get; set; } - public IEnumerable ApiScopes { get; set; } -} - -public class ScopeViewModel -{ - public string Name { get; set; } - public string Value { get; set; } - public string DisplayName { get; set; } - public string Description { get; set; } - public bool Emphasize { get; set; } - public bool Required { get; set; } - public bool Checked { get; set; } - public IEnumerable Resources { get; set; } -} - -public class ResourceViewModel -{ - public string Name { get; set; } - public string DisplayName { get; set; } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Ciba/_ScopeListItem.cshtml b/archive/SecurityService.UserInterface/Pages/Ciba/_ScopeListItem.cshtml deleted file mode 100644 index 3edbf10a..00000000 --- a/archive/SecurityService.UserInterface/Pages/Ciba/_ScopeListItem.cshtml +++ /dev/null @@ -1,47 +0,0 @@ -@using IdentityServerHost.Pages.Ciba -@model ScopeViewModel - -
  • - - @if (Model.Required) - { - (required) - } - @if (Model.Description != null) - { - - } - @if (Model.Resources?.Any() == true) - { - - } -
  • \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Consent/ConsentOptions.cs b/archive/SecurityService.UserInterface/Pages/Consent/ConsentOptions.cs deleted file mode 100644 index 3d6e4bb8..00000000 --- a/archive/SecurityService.UserInterface/Pages/Consent/ConsentOptions.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - - -namespace IdentityServerHost.Pages.Consent; - -public static class ConsentOptions -{ - public static readonly bool EnableOfflineAccess = true; - public static readonly string OfflineAccessDisplayName = "Offline Access"; - public static readonly string OfflineAccessDescription = "Access to your applications and resources, even when you are offline"; - - public static readonly string MustChooseOneErrorMessage = "You must pick at least one permission"; - public static readonly string InvalidSelectionErrorMessage = "Invalid selection"; -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Consent/Index.cshtml b/archive/SecurityService.UserInterface/Pages/Consent/Index.cshtml deleted file mode 100644 index 2ae550ef..00000000 --- a/archive/SecurityService.UserInterface/Pages/Consent/Index.cshtml +++ /dev/null @@ -1,106 +0,0 @@ -@page -@using Microsoft.AspNetCore.Mvc.TagHelpers -@model IdentityServerHost.Pages.Consent.Index -@{ -} - -
    - @if (Model.View.ClientLogoUrl != null) - { - - } -

    - @Model.View.ClientName - is requesting your permission -

    -

    Uncheck the permissions you do not wish to grant.

    -
    - -
    - -
    - -
    - -
    - @if (Model.View.IdentityScopes.Any()) - { -
    -
    -
    - - - - Personal Information -
    -
      - @foreach (var scope in Model.View.IdentityScopes) - { - - } -
    -
    -
    - } - - @if (Model.View.ApiScopes.Any()) - { -
    -
    -
    - - - - Application Access -
    -
      - @foreach (var scope in Model.View.ApiScopes) - { - - } -
    -
    -
    - } - -
    -
    -
    - - - - Description -
    -
    - -
    -
    -
    - - @if (Model.View.AllowRememberConsent) - { -
    -
    - - -
    -
    - } -
    - -
    - - - @if (Model.View.ClientUrl != null) - { - - - - - @Model.View.ClientName - - } -
    -
    diff --git a/archive/SecurityService.UserInterface/Pages/Consent/Index.cshtml.cs b/archive/SecurityService.UserInterface/Pages/Consent/Index.cshtml.cs deleted file mode 100644 index 70f842ee..00000000 --- a/archive/SecurityService.UserInterface/Pages/Consent/Index.cshtml.cs +++ /dev/null @@ -1,265 +0,0 @@ -using Duende.IdentityModel; -using Duende.IdentityServer.Events; -using Duende.IdentityServer.Extensions; -using Duende.IdentityServer.Models; -using Duende.IdentityServer.Services; -using Duende.IdentityServer.Validation; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace IdentityServerHost.Pages.Consent; - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; - -[Authorize] -[SecurityHeadersAttribute] -public class Index : PageModel -{ - private readonly IIdentityServerInteractionService _interaction; - private readonly IEventService _events; - private readonly ILogger _logger; - - public Index( - IIdentityServerInteractionService interaction, - IEventService events, - ILogger logger) - { - _interaction = interaction; - _events = events; - _logger = logger; - } - - public ViewModel View { get; set; } - - [BindProperty] - public InputModel Input { get; set; } - - public async Task OnGet(string returnUrl) - { - View = await BuildViewModelAsync(returnUrl); - if (View == null) - { - return RedirectToPage("/Home/Error/Index"); - } - - Input = new InputModel - { - ReturnUrl = returnUrl, - }; - - return Page(); - } - - public async Task OnPost() - { - var request = await _interaction.GetAuthorizationContextAsync(Input.ReturnUrl); - if (request == null) - return RedirectToPage("/Home/Error/Index"); - - var consent = await HandleConsentAsync(request); - if (consent == null) - { - View = await BuildViewModelAsync(Input.ReturnUrl, Input); - return Page(); - } - - await _interaction.GrantConsentAsync(request, consent); - - return request.IsNativeClient() - ? this.LoadingPage(Input.ReturnUrl) - : Redirect(Input.ReturnUrl); - } - - private async Task HandleConsentAsync(AuthorizationRequest request) - { - return Input?.Button switch - { - "no" => await DenyConsentAsync(request), - "yes" => await GrantConsentAsync(request), - _ => InvalidSelection() - }; - } - - private async Task DenyConsentAsync(AuthorizationRequest request) - { - await _events.RaiseAsync( - new ConsentDeniedEvent( - User.GetSubjectId(), - request.Client.ClientId, - request.ValidatedResources.RawScopeValues)); - - return new ConsentResponse - { - Error = AuthorizationError.AccessDenied - }; - } - - private async Task GrantConsentAsync(AuthorizationRequest request) - { - if (Input.ScopesConsented == null || !Input.ScopesConsented.Any()) - { - ModelState.AddModelError("", ConsentOptions.MustChooseOneErrorMessage); - return null; - } - - var scopes = FilterScopes(Input.ScopesConsented); - - var consent = new ConsentResponse - { - RememberConsent = Input.RememberConsent, - ScopesValuesConsented = scopes, - Description = Input.Description - }; - - await _events.RaiseAsync( - new ConsentGrantedEvent( - User.GetSubjectId(), - request.Client.ClientId, - request.ValidatedResources.RawScopeValues, - consent.ScopesValuesConsented, - consent.RememberConsent)); - - return consent; - } - - private string[] FilterScopes(IEnumerable scopes) - { - if (!ConsentOptions.EnableOfflineAccess) - { - scopes = scopes.Where(x => - x != Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess); - } - - return scopes.ToArray(); - } - - private ConsentResponse? InvalidSelection() - { - ModelState.AddModelError("", ConsentOptions.InvalidSelectionErrorMessage); - return null; - } - - - private async Task BuildViewModelAsync(string returnUrl, InputModel model = null) - { - var request = await _interaction.GetAuthorizationContextAsync(returnUrl); - if (request != null) - { - return CreateConsentViewModel(model, returnUrl, request); - } - else - { - _logger.LogError("No consent request matching request: {0}", returnUrl); - } - return null; - } - - private ViewModel CreateConsentViewModel( - InputModel model, string returnUrl, - AuthorizationRequest request) - { - var vm = new ViewModel - { - ClientName = request.Client.ClientName ?? request.Client.ClientId, - ClientUrl = request.Client.ClientUri, - ClientLogoUrl = request.Client.LogoUri, - AllowRememberConsent = request.Client.AllowRememberConsent - }; - - vm.IdentityScopes = GetIdentityScopes(request, model); - vm.ApiScopes = GetApiScopes(request, model); - - return vm; - } - - private ScopeViewModel[] GetIdentityScopes(AuthorizationRequest request, InputModel model) - { - return request.ValidatedResources.Resources.IdentityResources - .Select(x => CreateScopeViewModel(x, IsScopeConsented(model, x.Name))) - .ToArray(); - } - - private List GetApiScopes(AuthorizationRequest request, InputModel model) - { - var resourceIndicators = request.Parameters.GetValues(OidcConstants.AuthorizeRequest.Resource) ?? Enumerable.Empty(); - var apiResources = request.ValidatedResources.Resources.ApiResources.Where(x => resourceIndicators.Contains(x.Name)); - - var apiScopes = new List(); - foreach (var parsedScope in request.ValidatedResources.ParsedScopes) - { - var apiScope = request.ValidatedResources.Resources.FindApiScope(parsedScope.ParsedName); - if (apiScope != null) - { - var scopeVm = CreateScopeViewModel(parsedScope, apiScope, IsScopeConsented(model, parsedScope.RawValue)); - scopeVm.Resources = apiResources.Where(x => x.Scopes.Contains(parsedScope.ParsedName)) - .Select(x => new ResourceViewModel - { - Name = x.Name, - DisplayName = x.DisplayName ?? x.Name, - }).ToArray(); - apiScopes.Add(scopeVm); - } - } - if (ConsentOptions.EnableOfflineAccess && request.ValidatedResources.Resources.OfflineAccess) - { - apiScopes.Add(GetOfflineAccessScope(IsScopeConsented(model, Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess))); - } - return apiScopes; - } - - private bool IsScopeConsented(InputModel model, string scopeName) - { - return model?.ScopesConsented?.Contains(scopeName) != false; - } - - private ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check) - { - return new ScopeViewModel - { - Name = identity.Name, - Value = identity.Name, - DisplayName = identity.DisplayName ?? identity.Name, - Description = identity.Description, - Emphasize = identity.Emphasize, - Required = identity.Required, - Checked = check || identity.Required - }; - } - - public ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScopeValue, ApiScope apiScope, bool check) - { - var displayName = apiScope.DisplayName ?? apiScope.Name; - if (!String.IsNullOrWhiteSpace(parsedScopeValue.ParsedParameter)) - { - displayName += ":" + parsedScopeValue.ParsedParameter; - } - - return new ScopeViewModel - { - Name = parsedScopeValue.ParsedName, - Value = parsedScopeValue.RawValue, - DisplayName = displayName, - Description = apiScope.Description, - Emphasize = apiScope.Emphasize, - Required = apiScope.Required, - Checked = check || apiScope.Required - }; - } - - private ScopeViewModel GetOfflineAccessScope(bool check) - { - return new ScopeViewModel - { - Value = Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess, - DisplayName = ConsentOptions.OfflineAccessDisplayName, - Description = ConsentOptions.OfflineAccessDescription, - Emphasize = true, - Checked = check - }; - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Consent/InputModel.cs b/archive/SecurityService.UserInterface/Pages/Consent/InputModel.cs deleted file mode 100644 index 2741fb32..00000000 --- a/archive/SecurityService.UserInterface/Pages/Consent/InputModel.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -namespace IdentityServerHost.Pages.Consent; - -using System.Collections.Generic; - -public class InputModel -{ - public string Button { get; set; } - public IEnumerable ScopesConsented { get; set; } - public bool RememberConsent { get; set; } = true; - public string ReturnUrl { get; set; } - public string Description { get; set; } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Consent/ViewModel.cs b/archive/SecurityService.UserInterface/Pages/Consent/ViewModel.cs deleted file mode 100644 index 697f850b..00000000 --- a/archive/SecurityService.UserInterface/Pages/Consent/ViewModel.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -namespace IdentityServerHost.Pages.Consent; - -using System.Collections.Generic; - -public class ViewModel -{ - public string ClientName { get; set; } - public string ClientUrl { get; set; } - public string ClientLogoUrl { get; set; } - public bool AllowRememberConsent { get; set; } - - public IEnumerable IdentityScopes { get; set; } - public IEnumerable ApiScopes { get; set; } -} - -public class ScopeViewModel -{ - public string Name { get; set; } - public string Value { get; set; } - public string DisplayName { get; set; } - public string Description { get; set; } - public bool Emphasize { get; set; } - public bool Required { get; set; } - public bool Checked { get; set; } - public IEnumerable Resources { get; set; } -} - -public class ResourceViewModel -{ - public string Name { get; set; } - public string DisplayName { get; set; } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Consent/_ScopeListItem.cshtml b/archive/SecurityService.UserInterface/Pages/Consent/_ScopeListItem.cshtml deleted file mode 100644 index 66e33281..00000000 --- a/archive/SecurityService.UserInterface/Pages/Consent/_ScopeListItem.cshtml +++ /dev/null @@ -1,51 +0,0 @@ -@using IdentityServerHost.Pages.Consent -@model ScopeViewModel - -
  • - - @if (Model.Required) - { - (required) - } - @if (Model.Description != null) - { - - } - @if (Model.Resources?.Any() == true) - { - - } -
  • \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Device/DeviceOptions.cs b/archive/SecurityService.UserInterface/Pages/Device/DeviceOptions.cs deleted file mode 100644 index ab022d5a..00000000 --- a/archive/SecurityService.UserInterface/Pages/Device/DeviceOptions.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - - -namespace IdentityServerHost.Pages.Device; - -public static class DeviceOptions -{ - public static readonly bool EnableOfflineAccess = true; - public static readonly string OfflineAccessDisplayName = "Offline Access"; - public static readonly string OfflineAccessDescription = "Access to your applications and resources, even when you are offline"; - - public static readonly string InvalidUserCode = "Invalid user code"; - public static readonly string MustChooseOneErrorMessage = "You must pick at least one permission"; - public static readonly string InvalidSelectionErrorMessage = "Invalid selection"; -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Device/Index.cshtml b/archive/SecurityService.UserInterface/Pages/Device/Index.cshtml deleted file mode 100644 index 1bdbbe90..00000000 --- a/archive/SecurityService.UserInterface/Pages/Device/Index.cshtml +++ /dev/null @@ -1,131 +0,0 @@ -@page -@using Microsoft.AspNetCore.Mvc.TagHelpers -@model IdentityServerHost.Pages.Device.Index -@{ -} - -@if (Model.Input.UserCode == null) -{ -
    -

    User Code

    -

    Please enter the code displayed on your device.

    -
    - -
    - -
    - -
    -
    -
    - - -
    - -
    -
    -} -else -{ -
    - @if (Model.View.ClientLogoUrl != null) - { - - } -

    - @Model.View.ClientName - is requesting your permission -

    -

    Please confirm that the authorization request matches the code: @Model.Input.UserCode.

    -

    Uncheck the permissions you do not wish to grant.

    -
    - -
    - -
    - -
    - -
    - @if (Model.View.IdentityScopes.Any()) - { -
    -
    -
    - - - - Personal Information -
    -
      - @foreach (var scope in Model.View.IdentityScopes) - { - - } -
    -
    -
    - } - - @if (Model.View.ApiScopes.Any()) - { -
    -
    -
    - - - - Application Access -
    -
      - @foreach (var scope in Model.View.ApiScopes) - { - - } -
    -
    -
    - } - -
    -
    -
    - - - - Description -
    -
    - -
    -
    -
    - - @if (Model.View.AllowRememberConsent) - { -
    -
    - - -
    -
    - } -
    - -
    - - - @if (Model.View.ClientUrl != null) - { - - - - - @Model.View.ClientName - - } -
    -
    -} diff --git a/archive/SecurityService.UserInterface/Pages/Device/Index.cshtml.cs b/archive/SecurityService.UserInterface/Pages/Device/Index.cshtml.cs deleted file mode 100644 index fa4f64ee..00000000 --- a/archive/SecurityService.UserInterface/Pages/Device/Index.cshtml.cs +++ /dev/null @@ -1,250 +0,0 @@ -using Duende.IdentityServer.Configuration; -using Duende.IdentityServer.Events; -using Duende.IdentityServer.Extensions; -using Duende.IdentityServer.Models; -using Duende.IdentityServer.Services; -using Duende.IdentityServer.Validation; -using IdentityServerHost.Pages.Consent; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; -using Microsoft.Extensions.Options; - -namespace IdentityServerHost.Pages.Device; - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; - -[SecurityHeaders] -[Authorize] -public class Index : PageModel -{ - private readonly IDeviceFlowInteractionService _interaction; - private readonly IEventService _events; - private readonly IOptions _options; - private readonly ILogger _logger; - - public Index( - IDeviceFlowInteractionService interaction, - IEventService eventService, - IOptions options, - ILogger logger) - { - _interaction = interaction; - _events = eventService; - _options = options; - _logger = logger; - } - - public ViewModel View { get; set; } - - [BindProperty] - public InputModel Input { get; set; } - - public async Task OnGet(string userCode) - { - if (String.IsNullOrWhiteSpace(userCode)) - { - View = new ViewModel(); - Input = new InputModel(); - return Page(); - } - - View = await BuildViewModelAsync(userCode); - if (View == null) - { - ModelState.AddModelError("", DeviceOptions.InvalidUserCode); - View = new ViewModel(); - Input = new InputModel(); - return Page(); - } - - Input = new InputModel { - UserCode = userCode, - }; - - return Page(); - } - - public async Task OnPost() - { - var request = await _interaction.GetAuthorizationContextAsync(Input.UserCode); - if (request == null) return RedirectToPage("/Home/Error/Index"); - - ConsentResponse grantedConsent = null; - - // user clicked 'no' - send back the standard 'access_denied' response - if (Input.Button == "no") - { - grantedConsent = new ConsentResponse - { - Error = AuthorizationError.AccessDenied - }; - - // emit event - await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues)); - } - // user clicked 'yes' - validate the data - else if (Input.Button == "yes") - { - // if the user consented to some scope, build the response model - if (Input.ScopesConsented != null && Input.ScopesConsented.Any()) - { - var scopes = Input.ScopesConsented; - if (ConsentOptions.EnableOfflineAccess == false) - { - scopes = scopes.Where(x => x != Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess); - } - - grantedConsent = new ConsentResponse - { - RememberConsent = Input.RememberConsent, - ScopesValuesConsented = scopes.ToArray(), - Description = Input.Description - }; - - // emit event - await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent)); - } - else - { - ModelState.AddModelError("", ConsentOptions.MustChooseOneErrorMessage); - } - } - else - { - ModelState.AddModelError("", ConsentOptions.InvalidSelectionErrorMessage); - } - - if (grantedConsent != null) - { - // communicate outcome of consent back to identityserver - await _interaction.HandleRequestAsync(Input.UserCode, grantedConsent); - - // indicate that's it ok to redirect back to authorization endpoint - return RedirectToPage("/Device/Success"); - } - - // we need to redisplay the consent UI - View = await BuildViewModelAsync(Input.UserCode, Input); - return Page(); - } - - - private async Task BuildViewModelAsync(string userCode, InputModel model = null) - { - var request = await _interaction.GetAuthorizationContextAsync(userCode); - if (request != null) - { - return CreateConsentViewModel(model, request); - } - - return null; - } - - private ViewModel CreateConsentViewModel(InputModel model, DeviceFlowAuthorizationRequest request) - { - return new ViewModel - { - ClientName = GetClientName(request), - ClientUrl = request.Client.ClientUri, - ClientLogoUrl = request.Client.LogoUri, - AllowRememberConsent = request.Client.AllowRememberConsent, - IdentityScopes = CreateIdentityScopes(model, request), - ApiScopes = CreateApiScopes(model, request) - }; - } - - private string GetClientName(DeviceFlowAuthorizationRequest request) => - request.Client.ClientName ?? request.Client.ClientId; - - private bool IsConsented(InputModel model, string scope) => - model == null || model.ScopesConsented?.Contains(scope) == true; - - private ScopeViewModel[] CreateIdentityScopes(InputModel model, DeviceFlowAuthorizationRequest request) - { - return request.ValidatedResources.Resources.IdentityResources - .Select(x => CreateScopeViewModel(x, IsConsented(model, x.Name))) - .ToArray(); - } - - private List CreateApiScopes(InputModel model, DeviceFlowAuthorizationRequest request) - { - var apiScopes = request.ValidatedResources.ParsedScopes - .Select(parsed => BuildApiScopeViewModel(model, request, parsed)) - .Where(vm => vm != null) - .ToList(); - - if (ShouldIncludeOfflineAccess(request)) - { - apiScopes.Add(GetOfflineAccessScope( - IsConsented(model, Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess) - )); - } - - return apiScopes; - } - - private ScopeViewModel? BuildApiScopeViewModel( - InputModel model, - DeviceFlowAuthorizationRequest request, - ParsedScopeValue parsedScope) - { - var apiScope = request.ValidatedResources.Resources.FindApiScope(parsedScope.ParsedName); - if (apiScope == null) return null; - - return CreateScopeViewModel( - parsedScope, - apiScope, - IsConsented(model, parsedScope.RawValue) - ); - } - - private bool ShouldIncludeOfflineAccess(DeviceFlowAuthorizationRequest request) - { - return DeviceOptions.EnableOfflineAccess && - request.ValidatedResources.Resources.OfflineAccess; - } - - - private ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check) - { - return new ScopeViewModel - { - Value = identity.Name, - DisplayName = identity.DisplayName ?? identity.Name, - Description = identity.Description, - Emphasize = identity.Emphasize, - Required = identity.Required, - Checked = check || identity.Required - }; - } - - public ScopeViewModel CreateScopeViewModel(ParsedScopeValue parsedScopeValue, ApiScope apiScope, bool check) - { - return new ScopeViewModel - { - Value = parsedScopeValue.RawValue, - DisplayName = apiScope.DisplayName ?? apiScope.Name, - Description = apiScope.Description, - Emphasize = apiScope.Emphasize, - Required = apiScope.Required, - Checked = check || apiScope.Required - }; - } - - private ScopeViewModel GetOfflineAccessScope(bool check) - { - return new ScopeViewModel - { - Value = Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess, - DisplayName = DeviceOptions.OfflineAccessDisplayName, - Description = DeviceOptions.OfflineAccessDescription, - Emphasize = true, - Checked = check - }; - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Device/InputModel.cs b/archive/SecurityService.UserInterface/Pages/Device/InputModel.cs deleted file mode 100644 index 0d6d7a0d..00000000 --- a/archive/SecurityService.UserInterface/Pages/Device/InputModel.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace IdentityServerHost.Pages.Device; - -using System.Collections.Generic; - -public class InputModel -{ - public string Button { get; set; } - public IEnumerable ScopesConsented { get; set; } - public bool RememberConsent { get; set; } = true; - public string ReturnUrl { get; set; } - public string Description { get; set; } - public string UserCode { get; set; } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Device/Success.cshtml b/archive/SecurityService.UserInterface/Pages/Device/Success.cshtml deleted file mode 100644 index d2f90aab..00000000 --- a/archive/SecurityService.UserInterface/Pages/Device/Success.cshtml +++ /dev/null @@ -1,18 +0,0 @@ -@page -@model IdentityServerHost.Pages.Device.SuccessModel -@{ -} - -
    -
    -
    -
    - - - -
    -

    Success

    -

    You have successfully authorized the device

    -
    -
    -
    diff --git a/archive/SecurityService.UserInterface/Pages/Device/Success.cshtml.cs b/archive/SecurityService.UserInterface/Pages/Device/Success.cshtml.cs deleted file mode 100644 index 2db979ec..00000000 --- a/archive/SecurityService.UserInterface/Pages/Device/Success.cshtml.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace IdentityServerHost.Pages.Device; - -[SecurityHeaders] -[Authorize] -public class SuccessModel : PageModel -{ -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Device/ViewModel.cs b/archive/SecurityService.UserInterface/Pages/Device/ViewModel.cs deleted file mode 100644 index a70a5c07..00000000 --- a/archive/SecurityService.UserInterface/Pages/Device/ViewModel.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace IdentityServerHost.Pages.Device; - -using System.Collections.Generic; - -public class ViewModel -{ - public string ClientName { get; set; } - public string ClientUrl { get; set; } - public string ClientLogoUrl { get; set; } - public bool AllowRememberConsent { get; set; } - - public IEnumerable IdentityScopes { get; set; } - public IEnumerable ApiScopes { get; set; } -} - -public class ScopeViewModel -{ - public string Value { get; set; } - public string DisplayName { get; set; } - public string Description { get; set; } - public bool Emphasize { get; set; } - public bool Required { get; set; } - public bool Checked { get; set; } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Device/_ScopeListItem.cshtml b/archive/SecurityService.UserInterface/Pages/Device/_ScopeListItem.cshtml deleted file mode 100644 index 8ab6b0df..00000000 --- a/archive/SecurityService.UserInterface/Pages/Device/_ScopeListItem.cshtml +++ /dev/null @@ -1,39 +0,0 @@ -@using IdentityServerHost.Pages.Device -@model ScopeViewModel - -
  • - - @if (Model.Required) - { - (required) - } - @if (Model.Description != null) - { - - } -
  • \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Diagnostics/Index.cshtml b/archive/SecurityService.UserInterface/Pages/Diagnostics/Index.cshtml deleted file mode 100644 index c93825d9..00000000 --- a/archive/SecurityService.UserInterface/Pages/Diagnostics/Index.cshtml +++ /dev/null @@ -1,61 +0,0 @@ -@page -@model IdentityServerHost.Pages.Diagnostics.Index - -
    -
    -

    Authentication Cookie

    -
    - -
    -
    -
    -
    -

    Claims

    -
    -
    -
    - @foreach (var claim in Model.View.AuthenticateResult.Principal.Claims) - { -
    @claim.Type
    -
    @claim.Value
    - } -
    -
    -
    -
    - -
    -
    -
    -

    Properties

    -
    -
    -
    - @foreach (var prop in Model.View.AuthenticateResult.Properties.Items) - { -
    @prop.Key
    -
    @prop.Value
    - } - @if (Model.View.Clients.Any()) - { -
    Clients
    -
    - @{ - var clients = Model.View.Clients.ToArray(); - for(var i = 0; i < clients.Length; i++) - { - @clients[i] - if (i < clients.Length - 1) - { - , - } - } - } -
    - } -
    -
    -
    -
    -
    -
    \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Diagnostics/Index.cshtml.cs b/archive/SecurityService.UserInterface/Pages/Diagnostics/Index.cshtml.cs deleted file mode 100644 index 6940559a..00000000 --- a/archive/SecurityService.UserInterface/Pages/Diagnostics/Index.cshtml.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; -using Microsoft.AspNetCore.Authorization; - -namespace IdentityServerHost.Pages.Diagnostics; - -using System.Threading.Tasks; -using System.Linq; - -[SecurityHeaders] -[Authorize] -public class Index : PageModel -{ - public ViewModel View { get; set; } - - public async Task OnGet() - { - var localAddresses = new string[] { "127.0.0.1", "::1", HttpContext.Connection.LocalIpAddress.ToString() }; - if (!localAddresses.Contains(HttpContext.Connection.RemoteIpAddress.ToString())) - { - return NotFound(); - } - - View = new ViewModel(await HttpContext.AuthenticateAsync()); - - return Page(); - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Diagnostics/ViewModel.cs b/archive/SecurityService.UserInterface/Pages/Diagnostics/ViewModel.cs deleted file mode 100644 index c4d7ee04..00000000 --- a/archive/SecurityService.UserInterface/Pages/Diagnostics/ViewModel.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - - -using System.Buffers.Text; -using Microsoft.AspNetCore.Authentication; -using System.Text; -using System.Text.Json; -using Duende.IdentityModel; - -namespace IdentityServerHost.Pages.Diagnostics; - -using System.Collections.Generic; - -public class ViewModel -{ - public ViewModel(AuthenticateResult result) - { - AuthenticateResult = result; - - if (result.Properties.Items.ContainsKey("client_list")) - { - var encoded = result.Properties.Items["client_list"]; - var bytes = Base64Url.DecodeFromChars(encoded); - var value = Encoding.UTF8.GetString(bytes); - - Clients = JsonSerializer.Deserialize(value); - } - } - - public AuthenticateResult AuthenticateResult { get; } - public IEnumerable Clients { get; } = new List(); -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Extensions.cs b/archive/SecurityService.UserInterface/Pages/Extensions.cs deleted file mode 100644 index 9b156b0f..00000000 --- a/archive/SecurityService.UserInterface/Pages/Extensions.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - - -using Duende.IdentityServer.Models; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace IdentityServerHost.Pages; - -using System; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; - -public static class Extensions -{ - /// - /// Determines if the authentication scheme support signout. - /// - public static async Task GetSchemeSupportsSignOutAsync(this HttpContext context, string scheme) - { - var provider = context.RequestServices.GetRequiredService(); - var handler = await provider.GetHandlerAsync(context, scheme); - return (handler is IAuthenticationSignOutHandler); - } - - /// - /// Checks if the redirect URI is for a native client. - /// - public static bool IsNativeClient(this AuthorizationRequest context) - { - return !context.RedirectUri.StartsWith("https", StringComparison.Ordinal) - && !context.RedirectUri.StartsWith("http", StringComparison.Ordinal); - } - - /// - /// Renders a loading page that is used to redirect back to the redirectUri. - /// - public static IActionResult LoadingPage(this PageModel page, string redirectUri) - { - page.HttpContext.Response.StatusCode = 200; - page.HttpContext.Response.Headers["Location"] = ""; - - return page.RedirectToPage("/Redirect/Index", new { RedirectUri = redirectUri }); - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/ExternalLogin/Callback.cshtml b/archive/SecurityService.UserInterface/Pages/ExternalLogin/Callback.cshtml deleted file mode 100644 index 80fe0fb1..00000000 --- a/archive/SecurityService.UserInterface/Pages/ExternalLogin/Callback.cshtml +++ /dev/null @@ -1,19 +0,0 @@ -@page -@model IdentityServerHost.Pages.ExternalLogin.Callback - -@{ - Layout = null; -} - - - - - - - - -
    - -
    - - \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/ExternalLogin/Callback.cshtml.cs b/archive/SecurityService.UserInterface/Pages/ExternalLogin/Callback.cshtml.cs deleted file mode 100644 index 20c91094..00000000 --- a/archive/SecurityService.UserInterface/Pages/ExternalLogin/Callback.cshtml.cs +++ /dev/null @@ -1,285 +0,0 @@ -using System.Security.Authentication; -using Duende.IdentityServer; -using Duende.IdentityServer.Events; -using Duende.IdentityServer.Services; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; -using System.Security.Claims; -using Duende.IdentityModel; -using Duende.IdentityServer.Models; -using SecurityService.UserInterface.Common; - -namespace IdentityServerHost.Pages.ExternalLogin; - -using Microsoft.Extensions.Logging; -using SecurityService.BusinessLogic; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -[AllowAnonymous] -[SecurityHeaders] -public class Callback : PageModel -{ - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; - private readonly IIdentityServerInteractionService _interaction; - private readonly ILogger _logger; - private readonly IEventService _events; - - public Callback( - IIdentityServerInteractionService interaction, - IEventService events, - ILogger logger, - UserManager userManager, - SignInManager signInManager) - { - _userManager = userManager; - _signInManager = signInManager; - _interaction = interaction; - _logger = logger; - _events = events; - } - - public async Task OnGet() - { - var result = await AuthenticateExternalAsync(); - - LogExternalClaims(result.Principal); - - var (provider, providerUserId) = GetExternalProviderInfo(result); - var user = await FindOrProvisionUserAsync(provider, providerUserId, result.Principal.Claims); - - var (claims, props) = CaptureExternalContext(result); - await SignInUserAsync(user, claims, props); - - await ClearTemporaryExternalCookieAsync(); - - var returnUrl = GetReturnUrl(result); - var context = await _interaction.GetAuthorizationContextAsync(returnUrl); - - await RaiseLoginSuccessEvent(provider, providerUserId, user, context); - - return context?.IsNativeClient() == true - ? this.LoadingPage(returnUrl) - : Redirect(returnUrl); - } - - private async Task AuthenticateExternalAsync() - { - var result = await HttpContext.AuthenticateAsync( - IdentityServerConstants.ExternalCookieAuthenticationScheme); - - if (result?.Succeeded != true) - throw new AuthenticationException("External authentication error"); - - return result; - } - - private void LogExternalClaims(ClaimsPrincipal externalUser) - { - if (!_logger.IsEnabled(LogLevel.Debug)) return; - - var claims = externalUser.Claims.Select(c => $"{c.Type}: {c.Value}"); - _logger.LogDebug("External claims: {@claims}", claims); - } - - private (string provider, string providerUserId) GetExternalProviderInfo(AuthenticateResult result) - { - var externalUser = result.Principal; - - var userIdClaim = - externalUser.FindFirst(JwtClaimTypes.Subject) ?? - externalUser.FindFirst(ClaimTypes.NameIdentifier) ?? - throw new AuthenticationException("Unknown userid"); - - var provider = result.Properties.Items["scheme"]; - var providerUserId = userIdClaim.Value; - - return (provider, providerUserId); - } - - private async Task FindOrProvisionUserAsync( - string provider, string providerUserId, IEnumerable claims) - { - var user = await _userManager.FindByLoginAsync(provider, providerUserId); - - return user ?? await AutoProvisionUserAsync(provider, providerUserId, claims); - } - - private (List claims, AuthenticationProperties props) - CaptureExternalContext(AuthenticateResult result) - { - var additionalClaims = new List(); - var props = new AuthenticationProperties(); - - CaptureExternalLoginContext(result, additionalClaims, props); - - return (additionalClaims, props); - } - - private Task SignInUserAsync( - ApplicationUser user, - List claims, - AuthenticationProperties props) - { - return _signInManager.SignInWithClaimsAsync(user, props, claims); - } - - private Task RaiseLoginSuccessEvent( - string provider, - string providerUserId, - ApplicationUser user, - AuthorizationRequest context) - { - return _events.RaiseAsync( - new UserLoginSuccessEvent( - provider, - providerUserId, - user.Id, - user.UserName, - true, - context?.Client.ClientId)); - } - - - private static string GetReturnUrl(AuthenticateResult result) - { - return result.Properties.Items["returnUrl"] ?? "~/"; - } - - - private Task ClearTemporaryExternalCookieAsync() - { - return HttpContext.SignOutAsync( - IdentityServerConstants.ExternalCookieAuthenticationScheme); - } - - - private static async Task EnsureSucceededAsync(IdentityResult result) - { - if (!result.Succeeded) - throw new AuthenticationException(result.Errors.First().Description); - } - - private async Task AutoProvisionUserAsync( - string provider, - string providerUserId, - IEnumerable claims) - { - string sub = Guid.NewGuid().ToString(); - - var user = new ApplicationUser - { - Id = sub, - UserName = sub, - Email = claims.GetClaimValue(JwtClaimTypes.Email, ClaimTypes.Email) - }; - - var nameClaims = claims.BuildDisplayNameClaims(); - - await EnsureSucceededAsync(await _userManager.CreateAsync(user)); - - if (nameClaims.Any()) - { - await EnsureSucceededAsync(await _userManager - .AddClaimsAsync(user, nameClaims)); - } - - await EnsureSucceededAsync( - await _userManager.AddLoginAsync(user, new UserLoginInfo(provider, providerUserId, provider))); - - return user; - } - - - //private async Task AutoProvisionUserAsync(string provider, string providerUserId, IEnumerable claims) - //{ - // var sub = Guid.NewGuid().ToString(); - - // var user = new ApplicationUser() - // { - // Id = sub, - // UserName = sub, // don't need a username, since the user will be using an external provider to login - // }; - - // // email - // var email = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Email)?.Value ?? - // claims.FirstOrDefault(x => x.Type == ClaimTypes.Email)?.Value; - // if (email != null) - // { - // user.Email = email; - // } - - // // create a list of claims that we want to transfer into our store - // var filtered = new List(); - - // // user's display name - // var name = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Name)?.Value ?? - // claims.FirstOrDefault(x => x.Type == ClaimTypes.Name)?.Value; - // if (name != null) - // { - // filtered.Add(new Claim(JwtClaimTypes.Name, name)); - // } - // else - // { - // var first = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.GivenName)?.Value ?? - // claims.FirstOrDefault(x => x.Type == ClaimTypes.GivenName)?.Value; - // var last = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.FamilyName)?.Value ?? - // claims.FirstOrDefault(x => x.Type == ClaimTypes.Surname)?.Value; - // if (first != null && last != null) - // { - // filtered.Add(new Claim(JwtClaimTypes.Name, first + " " + last)); - // } - // else if (first != null) - // { - // filtered.Add(new Claim(JwtClaimTypes.Name, first)); - // } - // else if (last != null) - // { - // filtered.Add(new Claim(JwtClaimTypes.Name, last)); - // } - // } - - // var identityResult = await _userManager.CreateAsync(user); - // if (!identityResult.Succeeded) throw new AuthenticationException(identityResult.Errors.First().Description); - - // if (filtered.Any()) - // { - // identityResult = await _userManager.AddClaimsAsync(user, filtered); - // if (!identityResult.Succeeded) throw new AuthenticationException(identityResult.Errors.First().Description); - // } - - // identityResult = await _userManager.AddLoginAsync(user, new UserLoginInfo(provider, providerUserId, provider)); - // if (!identityResult.Succeeded) throw new AuthenticationException(identityResult.Errors.First().Description); - - // return user; - //} - - // if the external login is OIDC-based, there are certain things we need to preserve to make logout work - // this will be different for WS-Fed, SAML2p or other protocols - private void CaptureExternalLoginContext(AuthenticateResult externalResult, List localClaims, AuthenticationProperties localSignInProps) - { - // capture the idp used to login, so the session knows where the user came from - localClaims.Add(new Claim(JwtClaimTypes.IdentityProvider, externalResult.Properties.Items["scheme"])); - - // if the external system sent a session id claim, copy it over - // so we can use it for single sign-out - var sid = externalResult.Principal.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.SessionId); - if (sid != null) - { - localClaims.Add(new Claim(JwtClaimTypes.SessionId, sid.Value)); - } - - // if the external provider issued an id_token, we'll keep it for signout - var idToken = externalResult.Properties.GetTokenValue("id_token"); - if (idToken != null) - { - localSignInProps.StoreTokens(new[] { new AuthenticationToken { Name = "id_token", Value = idToken } }); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/ExternalLogin/Challenge.cshtml b/archive/SecurityService.UserInterface/Pages/ExternalLogin/Challenge.cshtml deleted file mode 100644 index d6680bda..00000000 --- a/archive/SecurityService.UserInterface/Pages/ExternalLogin/Challenge.cshtml +++ /dev/null @@ -1,19 +0,0 @@ -@page -@model IdentityServerHost.Pages.ExternalLogin.Challenge - -@{ - Layout = null; -} - - - - - - - - -
    - -
    - - \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/ExternalLogin/Challenge.cshtml.cs b/archive/SecurityService.UserInterface/Pages/ExternalLogin/Challenge.cshtml.cs deleted file mode 100644 index b4576cd6..00000000 --- a/archive/SecurityService.UserInterface/Pages/ExternalLogin/Challenge.cshtml.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Duende.IdentityServer.Services; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace IdentityServerHost.Pages.ExternalLogin; - -using System; - -[AllowAnonymous] -[SecurityHeaders] -public class Challenge : PageModel -{ - private readonly IIdentityServerInteractionService _interactionService; - - public Challenge(IIdentityServerInteractionService interactionService) - { - _interactionService = interactionService; - } - - public IActionResult OnGet(string scheme, string returnUrl) - { - if (string.IsNullOrEmpty(returnUrl)) returnUrl = "~/"; - - // validate returnUrl - either it is a valid OIDC URL or back to a local page - if (Url.IsLocalUrl(returnUrl) == false && _interactionService.IsValidReturnUrl(returnUrl) == false) - { - // user might have clicked on a malicious link - should be logged - throw new ArgumentException("invalid return URL"); - } - - // start challenge and roundtrip the return URL and scheme - var props = new AuthenticationProperties - { - RedirectUri = Url.Page("/externallogin/callback"), - - Items = - { - { "returnUrl", returnUrl }, - { "scheme", scheme }, - } - }; - - return Challenge(props, scheme); - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Grants/Index.cshtml b/archive/SecurityService.UserInterface/Pages/Grants/Index.cshtml deleted file mode 100644 index fb2957c2..00000000 --- a/archive/SecurityService.UserInterface/Pages/Grants/Index.cshtml +++ /dev/null @@ -1,86 +0,0 @@ -@page -@using Microsoft.AspNetCore.Mvc.TagHelpers -@model IdentityServerHost.Pages.Grants.Index -@{ -} - -
    -

    Client Application Permissions

    -

    Below is the list of applications you have given permission to and the resources they have access to.

    -
    - -@if (Model.View.Grants.Any() == false) -{ -
    -
    - You have not given access to any applications -
    -
    -} -else -{ -
    - @foreach (var grant in Model.View.Grants) - { -
    -
    -
    -
    - @if (grant.ClientLogoUrl != null) - { - - } - @grant.ClientName -
    -
    - - -
    -
    -
    - -
      - @if (grant.Description != null) - { -
    • - Description: @grant.Description -
    • - } -
    • - Created: @grant.Created.ToString("yyyy-MM-dd") -
    • - @if (grant.Expires.HasValue) - { -
    • - Expires: @grant.Expires.Value.ToString("yyyy-MM-dd") -
    • - } - @if (grant.IdentityGrantNames.Any()) - { -
    • - Identity Grants -
        - @foreach (var name in grant.IdentityGrantNames) - { -
      • @name
      • - } -
      -
    • - } - @if (grant.ApiGrantNames.Any()) - { -
    • - API Grants -
        - @foreach (var name in grant.ApiGrantNames) - { -
      • @name
      • - } -
      -
    • - } -
    -
    - } -
    -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Grants/Index.cshtml.cs b/archive/SecurityService.UserInterface/Pages/Grants/Index.cshtml.cs deleted file mode 100644 index 2f596b93..00000000 --- a/archive/SecurityService.UserInterface/Pages/Grants/Index.cshtml.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using Duende.IdentityServer.Events; -using Duende.IdentityServer.Extensions; -using Duende.IdentityServer.Services; -using Duende.IdentityServer.Stores; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace IdentityServerHost.Pages.Grants; - -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -[SecurityHeaders] -[Authorize] -public class Index : PageModel -{ - private readonly IIdentityServerInteractionService _interaction; - private readonly IClientStore _clients; - private readonly IResourceStore _resources; - private readonly IEventService _events; - - public Index(IIdentityServerInteractionService interaction, - IClientStore clients, - IResourceStore resources, - IEventService events) - { - _interaction = interaction; - _clients = clients; - _resources = resources; - _events = events; - } - - public ViewModel View { get; set; } - - public async Task OnGet() - { - var grants = await _interaction.GetAllUserGrantsAsync(); - - var list = new List(); - foreach (var grant in grants) - { - var client = await _clients.FindClientByIdAsync(grant.ClientId); - if (client != null) - { - var resources = await _resources.FindResourcesByScopeAsync(grant.Scopes); - - var item = new GrantViewModel() - { - ClientId = client.ClientId, - ClientName = client.ClientName ?? client.ClientId, - ClientLogoUrl = client.LogoUri, - ClientUrl = client.ClientUri, - Description = grant.Description, - Created = grant.CreationTime, - Expires = grant.Expiration, - IdentityGrantNames = resources.IdentityResources.Select(x => x.DisplayName ?? x.Name).ToArray(), - ApiGrantNames = resources.ApiScopes.Select(x => x.DisplayName ?? x.Name).ToArray() - }; - - list.Add(item); - } - } - - View = new ViewModel - { - Grants = list - }; - } - - [BindProperty] - [Required] - public string ClientId { get; set; } - - public async Task OnPost() - { - await _interaction.RevokeUserConsentAsync(ClientId); - await _events.RaiseAsync(new GrantsRevokedEvent(User.GetSubjectId(), ClientId)); - - return RedirectToPage("/Grants/Index"); - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Grants/ViewModel.cs b/archive/SecurityService.UserInterface/Pages/Grants/ViewModel.cs deleted file mode 100644 index 8ae188f2..00000000 --- a/archive/SecurityService.UserInterface/Pages/Grants/ViewModel.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace IdentityServerHost.Pages.Grants; - -using System; -using System.Collections.Generic; - -public class ViewModel -{ - public IEnumerable Grants { get; set; } -} - -public class GrantViewModel -{ - public string ClientId { get; set; } - public string ClientName { get; set; } - public string ClientUrl { get; set; } - public string ClientLogoUrl { get; set; } - public string Description { get; set; } - public DateTime Created { get; set; } - public DateTime? Expires { get; set; } - public IEnumerable IdentityGrantNames { get; set; } - public IEnumerable ApiGrantNames { get; set; } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Home/Error/Index.cshtml b/archive/SecurityService.UserInterface/Pages/Home/Error/Index.cshtml deleted file mode 100644 index d9e2d5d1..00000000 --- a/archive/SecurityService.UserInterface/Pages/Home/Error/Index.cshtml +++ /dev/null @@ -1,29 +0,0 @@ -@page -@model IdentityServerHost.Pages.Error.Index - -
    -

    Error

    -
    - -
    -
    -

    Sorry, there was an error

    - - @if (Model.View.Error != null) - { - - : @Model.View.Error.Error - - - if (Model.View.Error.ErrorDescription != null) - { -
    @Model.View.Error.ErrorDescription
    - } - } -
    - - @if (Model?.View?.Error?.RequestId != null) - { -

    Request Id: @Model.View.Error.RequestId

    - } -
    diff --git a/archive/SecurityService.UserInterface/Pages/Home/Error/Index.cshtml.cs b/archive/SecurityService.UserInterface/Pages/Home/Error/Index.cshtml.cs deleted file mode 100644 index a84e971d..00000000 --- a/archive/SecurityService.UserInterface/Pages/Home/Error/Index.cshtml.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Duende.IdentityServer.Services; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace IdentityServerHost.Pages.Error; - -using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Hosting; - -[AllowAnonymous] -[SecurityHeaders] -public class Index : PageModel -{ - private readonly IIdentityServerInteractionService _interaction; - private readonly IWebHostEnvironment _environment; - - public ViewModel View { get; set; } - - public Index(IIdentityServerInteractionService interaction, IWebHostEnvironment environment) - { - _interaction = interaction; - _environment = environment; - } - - public async Task OnGet(string errorId) - { - View = new ViewModel(); - - // retrieve error details from identityserver - var message = await _interaction.GetErrorContextAsync(errorId); - if (message != null) - { - View.Error = message; - - if (!_environment.IsDevelopment()) - { - // only show in development - message.ErrorDescription = null; - } - } - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Home/Error/ViewModel.cs b/archive/SecurityService.UserInterface/Pages/Home/Error/ViewModel.cs deleted file mode 100644 index 6a842b06..00000000 --- a/archive/SecurityService.UserInterface/Pages/Home/Error/ViewModel.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - -using Duende.IdentityServer.Models; - -namespace IdentityServerHost.Pages.Error; - -public class ViewModel -{ - public ViewModel() - { - } - - public ViewModel(string error) - { - Error = new ErrorMessage { Error = error }; - } - - public ErrorMessage Error { get; set; } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Index.cshtml b/archive/SecurityService.UserInterface/Pages/Index.cshtml deleted file mode 100644 index 34975370..00000000 --- a/archive/SecurityService.UserInterface/Pages/Index.cshtml +++ /dev/null @@ -1,55 +0,0 @@ -@page -@model IdentityServerHost.Pages.Home.Index - -
    -

    -
    - - - -
    - Welcome to Security Service - (version @Model.Version) -

    -
    - -
    -
    -
      -
    • - - - - IdentityServer publishes a - discovery document - where you can find metadata and links to all the endpoints, key material, etc. -
    • -
    • - - - - Click here to see the claims for your current session. -
    • -
    • - - - - Click here to manage your stored grants. -
    • -
    • - - - - Click here to view your pending CIBA login requests. -
    • -
    • - - - - Here are links to the - source code repository, - and ready to use samples. -
    • -
    -
    -
    diff --git a/archive/SecurityService.UserInterface/Pages/Index.cshtml.cs b/archive/SecurityService.UserInterface/Pages/Index.cshtml.cs deleted file mode 100644 index 8e10f8a6..00000000 --- a/archive/SecurityService.UserInterface/Pages/Index.cshtml.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Reflection; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace IdentityServerHost.Pages.Home; - -using System.Linq; - -[AllowAnonymous] -public class Index : PageModel -{ - public string Version { get; private set; } - - public void OnGet() - { - Version = typeof(Duende.IdentityServer.Hosting.IdentityServerMiddleware).Assembly.GetCustomAttribute()?.InformationalVersion.Split('+').First(); - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Redirect/Index.cshtml b/archive/SecurityService.UserInterface/Pages/Redirect/Index.cshtml deleted file mode 100644 index f73b4301..00000000 --- a/archive/SecurityService.UserInterface/Pages/Redirect/Index.cshtml +++ /dev/null @@ -1,14 +0,0 @@ -@page -@model IdentityServerHost.Pages.Redirect.IndexModel -@{ -} - -
    -
    -

    You are now being returned to the application

    -

    Once complete, you may close this tab.

    -
    -
    - - - diff --git a/archive/SecurityService.UserInterface/Pages/Redirect/Index.cshtml.cs b/archive/SecurityService.UserInterface/Pages/Redirect/Index.cshtml.cs deleted file mode 100644 index 06cb51d8..00000000 --- a/archive/SecurityService.UserInterface/Pages/Redirect/Index.cshtml.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace IdentityServerHost.Pages.Redirect; - -[AllowAnonymous] -public class IndexModel : PageModel -{ - public string RedirectUri { get; set; } - - public IActionResult OnGet(string redirectUri) - { - if (!Url.IsLocalUrl(redirectUri)) - { - return RedirectToPage("/Home/Error/Index"); - } - - RedirectUri = redirectUri; - return Page(); - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/SecurityHeadersAttribute.cs b/archive/SecurityService.UserInterface/Pages/SecurityHeadersAttribute.cs deleted file mode 100644 index 09081724..00000000 --- a/archive/SecurityService.UserInterface/Pages/SecurityHeadersAttribute.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - - -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace IdentityServerHost.Pages; - -public class SecurityHeadersAttribute : ActionFilterAttribute -{ - public override void OnResultExecuting(ResultExecutingContext context) - { - var result = context.Result; - if (result is PageResult) - { - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options - if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Type-Options")) - { - context.HttpContext.Response.Headers.Add("X-Content-Type-Options", "nosniff"); - } - - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options - if (!context.HttpContext.Response.Headers.ContainsKey("X-Frame-Options")) - { - context.HttpContext.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN"); - } - - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy - var csp = "default-src 'self'; object-src 'none'; frame-ancestors 'none'; sandbox allow-forms allow-same-origin allow-scripts; base-uri 'self';"; - // also consider adding upgrade-insecure-requests once you have HTTPS in place for production - //csp += "upgrade-insecure-requests;"; - // also an example if you need client images to be displayed from twitter - // csp += "img-src 'self' https://pbs.twimg.com;"; - - // once for standards compliant browsers - if (!context.HttpContext.Response.Headers.ContainsKey("Content-Security-Policy")) - { - context.HttpContext.Response.Headers.Add("Content-Security-Policy", csp); - } - // and once again for IE - if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Security-Policy")) - { - context.HttpContext.Response.Headers.Add("X-Content-Security-Policy", csp); - } - - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy - var referrer_policy = "no-referrer"; - if (!context.HttpContext.Response.Headers.ContainsKey("Referrer-Policy")) - { - context.HttpContext.Response.Headers.Add("Referrer-Policy", referrer_policy); - } - } - } -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/Shared/_Layout.cshtml b/archive/SecurityService.UserInterface/Pages/Shared/_Layout.cshtml deleted file mode 100644 index 5efb85d8..00000000 --- a/archive/SecurityService.UserInterface/Pages/Shared/_Layout.cshtml +++ /dev/null @@ -1,25 +0,0 @@ -@using Microsoft.AspNetCore.Mvc.TagHelpers - - - - - - - - Security Service - - - - - - - -
    -
    - @RenderBody() -
    -
    - - @RenderSection("scripts", required: false) - - diff --git a/archive/SecurityService.UserInterface/Pages/Shared/_Nav.cshtml b/archive/SecurityService.UserInterface/Pages/Shared/_Nav.cshtml deleted file mode 100644 index a35120dd..00000000 --- a/archive/SecurityService.UserInterface/Pages/Shared/_Nav.cshtml +++ /dev/null @@ -1,60 +0,0 @@ -@using Duende.IdentityServer.Extensions -@using Microsoft.AspNetCore.Mvc.TagHelpers -@{ - string name = null; - if (!true.Equals(ViewData["signed-out"])) - { - name = Context.User?.GetDisplayName(); - } -} - -
    -
    - -
    - - - -
    -
    - Security - Service -
    -
    - - @if (!string.IsNullOrWhiteSpace(name)) - { -
    - - -
    - } -
    -
    - - diff --git a/archive/SecurityService.UserInterface/Pages/Shared/_ValidationSummary.cshtml b/archive/SecurityService.UserInterface/Pages/Shared/_ValidationSummary.cshtml deleted file mode 100644 index 1e3ad4ed..00000000 --- a/archive/SecurityService.UserInterface/Pages/Shared/_ValidationSummary.cshtml +++ /dev/null @@ -1,8 +0,0 @@ -@using Microsoft.AspNetCore.Mvc.TagHelpers -@if (ViewContext.ModelState.IsValid == false) -{ -
    - Error -
    -
    -} \ No newline at end of file diff --git a/archive/SecurityService.UserInterface/Pages/_ViewImports.cshtml b/archive/SecurityService.UserInterface/Pages/_ViewImports.cshtml deleted file mode 100644 index 7537d10a..00000000 --- a/archive/SecurityService.UserInterface/Pages/_ViewImports.cshtml +++ /dev/null @@ -1,2 +0,0 @@ -@using IdentityServerHost.Pages -@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/archive/SecurityService.UserInterface/Pages/_ViewStart.cshtml b/archive/SecurityService.UserInterface/Pages/_ViewStart.cshtml deleted file mode 100644 index a5f10045..00000000 --- a/archive/SecurityService.UserInterface/Pages/_ViewStart.cshtml +++ /dev/null @@ -1,3 +0,0 @@ -@{ - Layout = "_Layout"; -} diff --git a/archive/SecurityService.UserInterface/SecurityService.UserInterface.csproj b/archive/SecurityService.UserInterface/SecurityService.UserInterface.csproj deleted file mode 100644 index 7ca605c8..00000000 --- a/archive/SecurityService.UserInterface/SecurityService.UserInterface.csproj +++ /dev/null @@ -1,26 +0,0 @@ - - - - net10.0 - enable - enable - true - None - - - - - - - - - - - - - - - - - - diff --git a/archive/SecurityService/Bootstrapper/IdentityServerRegistry.cs b/archive/SecurityService/Bootstrapper/IdentityServerRegistry.cs deleted file mode 100644 index b0114157..00000000 --- a/archive/SecurityService/Bootstrapper/IdentityServerRegistry.cs +++ /dev/null @@ -1,76 +0,0 @@ -namespace SecurityService.Bootstrapper -{ - using System; - using System.Diagnostics.CodeAnalysis; - using BusinessLogic; - using Common; - using Database.DbContexts; - using Lamar; - using Microsoft.AspNetCore.Identity; - using Microsoft.Extensions.Configuration; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.Hosting; - - [ExcludeFromCodeCoverage] - public class IdentityServerRegistry : ServiceRegistry - { - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - public IdentityServerRegistry() - { - // Get the DB Connection Strings - String persistedGrantStoreConnectionString = Startup.Configuration.GetConnectionString("PersistedGrantDbContext"); - String configurationConnectionString = Startup.Configuration.GetConnectionString("ConfigurationDbContext"); - String authenticationConnectionString = Startup.Configuration.GetConnectionString("AuthenticationDbContext"); - - ServiceOptions serviceOptions = new ServiceOptions(); - IConfigurationSection serviceOptionsSection = Startup.Configuration.GetSection("ServiceOptions"); - serviceOptionsSection.Bind(serviceOptions); - - this.AddSingleton(serviceOptions); - this.AddIdentity(opt => { - opt.Tokens.EmailConfirmationTokenProvider = "emailconfirmation"; - opt.Password.RequireDigit = serviceOptions.PasswordOptions.RequireDigit; - opt.Password.RequireUppercase = serviceOptions.PasswordOptions.RequireUpperCase; - opt.Password.RequiredLength = serviceOptions.PasswordOptions.RequiredLength; - opt.SignIn.RequireConfirmedEmail = serviceOptions.SignInOptions.RequireConfirmedEmail; - opt.User.RequireUniqueEmail = serviceOptions.UserOptions.RequireUniqueEmail; - }).AddEntityFrameworkStores().AddDefaultTokenProviders() - .AddTokenProvider>("emailconfirmation"); - - this.Configure(opt => opt.TokenLifespan = - TimeSpan.FromHours(serviceOptions.TokenOptions.PasswordResetTokenExpiryInHours)); - this.Configure(opt => - opt.TokenLifespan = TimeSpan.FromHours(serviceOptions.TokenOptions.EmailConfirmationTokenExpiryInHours)); - - - IIdentityServerBuilder identityServerBuilder = this.AddIdentityServer(options => - { - // https://docs.duendesoftware.com/identityserver/v5/fundamentals/resources/ - options.EmitStaticAudienceClaim = true; - - options.Events.RaiseSuccessEvents = true; - options.Events.RaiseFailureEvents = true; - options.Events.RaiseErrorEvents = true; - - options.IssuerUri = serviceOptions.IssuerUrl; - }); - - identityServerBuilder.AddAspNetIdentity(); - - if (serviceOptions.UseInMemoryDatabase) - { - identityServerBuilder.AddIntegrationTestConfiguration(); - } - else - { - identityServerBuilder.AddIdentityServerStorage(configurationConnectionString, persistedGrantStoreConnectionString, authenticationConnectionString); - } - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Bootstrapper/MediatorRegistry.cs b/archive/SecurityService/Bootstrapper/MediatorRegistry.cs deleted file mode 100644 index fb956c05..00000000 --- a/archive/SecurityService/Bootstrapper/MediatorRegistry.cs +++ /dev/null @@ -1,24 +0,0 @@ -using SimpleResults; - -namespace SecurityService.Bootstrapper; - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Reflection; -using BusinessLogic.RequestHandlers; -using BusinessLogic.Requests; -using Duende.IdentityServer.Models; -using Lamar; -using MediatR; -using Microsoft.Extensions.DependencyInjection; -using Models; - -[ExcludeFromCodeCoverage] -public class MediatorRegistry : ServiceRegistry -{ - public MediatorRegistry() - { - this.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(ApiResourceRequestHandler).Assembly)); - } -} \ No newline at end of file diff --git a/archive/SecurityService/Bootstrapper/MiddlewareRegistry.cs b/archive/SecurityService/Bootstrapper/MiddlewareRegistry.cs deleted file mode 100644 index e75eb70e..00000000 --- a/archive/SecurityService/Bootstrapper/MiddlewareRegistry.cs +++ /dev/null @@ -1,112 +0,0 @@ -using Microsoft.OpenApi; - -namespace SecurityService.Bootstrapper -{ - using System; - using System.Diagnostics.CodeAnalysis; - using System.IO; - using BusinessLogic; - using Database.DbContexts; - using Factories; - using Lamar; - using Microsoft.AspNetCore.Identity; - using Microsoft.Extensions.Configuration; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.Diagnostics.HealthChecks; - using Microsoft.Extensions.Hosting; - using Newtonsoft.Json; - using Newtonsoft.Json.Serialization; - using Shared.Extensions; - using Shared.General; - using Swashbuckle.AspNetCore.Filters; - - [ExcludeFromCodeCoverage] - public class MiddlewareRegistry : ServiceRegistry - { - public MiddlewareRegistry() - { - this.ConfigureHealthChecks(); - this.ConfigureSwagger(); - this.AddSwaggerExamplesFromAssemblyOf(); - - //this.AddRazorPages(); - //this.AddControllers(); - // .AddNewtonsoftJson(options => - //{ - // options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; - // options.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto; - // options.SerializerSettings.Formatting = Formatting.Indented; - // options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; - // options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); - //}); - - this.ConfigureHttpJsonOptions(options => - { - options.SerializerOptions.PropertyNamingPolicy = new SnakeCaseNamingPolicy(); - options.SerializerOptions.PropertyNameCaseInsensitive = true; // optional, but safer - }); - } - - private void ConfigureHealthChecks() - { - if (Startup.WebHostEnvironment.IsEnvironment("IntegrationTest")) { - this.AddHealthChecks(); - } - else if (Startup.Configuration.GetValue("ServiceOptions:UseInMemoryDatabase")) { - this.AddHealthChecks().AddMessagingService(); - } - else - { - this.AddHealthChecks() - .AddMessagingService() - .AddSqlServer(ConfigurationReader.GetConnectionString("PersistedGrantDbContext"), - "SELECT 1;", - name: "Persisted Grant DB", - failureStatus: HealthStatus.Unhealthy, - tags: new string[] { "db", "sql", "sqlserver", "persistedgrant" }) - .AddSqlServer(ConfigurationReader.GetConnectionString("ConfigurationDbContext"), - "SELECT 1;", - name: "Configuration DB", - failureStatus: HealthStatus.Unhealthy, - tags: new string[] { "db", "sql", "sqlserver", "configuration" }) - .AddSqlServer(ConfigurationReader.GetConnectionString("AuthenticationDbContext"), - "SELECT 1;", - name: "Authentication DB", - failureStatus: HealthStatus.Unhealthy, - tags: new string[] { "db", "sql", "sqlserver", "authentication" }); - } - } - - private void ConfigureSwagger() - { - this.AddSwaggerGen(c => - { - c.SwaggerDoc("v1", new OpenApiInfo - { - Title = "Authentication API", - Version = "1.0", - Description = "A REST Api to provide authentication services including management of user/client and api details.", - Contact = new OpenApiContact - { - Name = "Stuart Ferguson", - Email = "golfhandicapping@btinternet.com" - } - }); - // add a custom operation filter which sets default values - c.OperationFilter(); - c.ExampleFilters(); - - //Locate the XML files being generated by ASP.NET... - DirectoryInfo directory = new DirectoryInfo(AppContext.BaseDirectory); - FileInfo[] xmlFiles = directory.GetFiles("*.xml"); - - //... and tell Swagger to use those XML comments. - foreach (FileInfo fileInfo in xmlFiles) - { - c.IncludeXmlComments(fileInfo.FullName); - } - }); - } - } - -} diff --git a/archive/SecurityService/Bootstrapper/MiscRegistry.cs b/archive/SecurityService/Bootstrapper/MiscRegistry.cs deleted file mode 100644 index 9b7960b7..00000000 --- a/archive/SecurityService/Bootstrapper/MiscRegistry.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Microsoft.Extensions.Logging; - -namespace SecurityService.Bootstrapper -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using BusinessLogic; - using ClientProxyBase; - using Factories; - using Lamar; - using MessagingService.Client; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.Hosting; - using Shared.General; - using Shared.Middleware; - - [ExcludeFromCodeCoverage] - public class MiscRegistry : ServiceRegistry - { - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - public MiscRegistry() - { - this.AddHttpContextAccessor(); - - if (Startup.WebHostEnvironment.IsEnvironment("IntegrationTest")) { - this.AddSingleton(); - } - else { - this.RegisterHttpClient(); - } - - this.AddSingleton>(container => serviceName => { return ConfigurationReader.GetBaseServerUri(serviceName).OriginalString; }); - - bool logRequests = ConfigurationReader.GetValueOrDefault("MiddlewareLogging", "LogRequests", true); - bool logResponses = ConfigurationReader.GetValueOrDefault("MiddlewareLogging", "LogResponses", true); - LogLevel middlewareLogLevel = ConfigurationReader.GetValueOrDefault("MiddlewareLogging", "MiddlewareLogLevel", LogLevel.Warning); - - RequestResponseMiddlewareLoggingConfig config = - new RequestResponseMiddlewareLoggingConfig(middlewareLogLevel, logRequests, logResponses); - - this.AddSingleton(config); - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/EmailConfirmationTokenProvider.cs b/archive/SecurityService/Common/EmailConfirmationTokenProvider.cs deleted file mode 100644 index d163fc46..00000000 --- a/archive/SecurityService/Common/EmailConfirmationTokenProvider.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace SecurityService.Common; - -using Microsoft.AspNetCore.DataProtection; -using Microsoft.AspNetCore.Identity; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using System.Diagnostics.CodeAnalysis; - -[ExcludeFromCodeCoverage] -public class EmailConfirmationTokenProvider : DataProtectorTokenProvider where TUser : class -{ - public EmailConfirmationTokenProvider(IDataProtectionProvider dataProtectionProvider, - IOptions options, - ILogger> logger) - : base(dataProtectionProvider, options, logger) - { - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/EmailConfirmationTokenProviderOptions.cs b/archive/SecurityService/Common/EmailConfirmationTokenProviderOptions.cs deleted file mode 100644 index 1c5e1d9f..00000000 --- a/archive/SecurityService/Common/EmailConfirmationTokenProviderOptions.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace SecurityService.Common; - -using System.Diagnostics.CodeAnalysis; -using Microsoft.AspNetCore.Identity; - -[ExcludeFromCodeCoverage] -public class EmailConfirmationTokenProviderOptions : DataProtectionTokenProviderOptions -{ - -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/ApiResourceDetailsListResponseExample.cs b/archive/SecurityService/Common/Examples/ApiResourceDetailsListResponseExample.cs deleted file mode 100644 index e0398d03..00000000 --- a/archive/SecurityService/Common/Examples/ApiResourceDetailsListResponseExample.cs +++ /dev/null @@ -1,44 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using DataTransferObjects.Responses; - using Swashbuckle.AspNetCore.Filters; - - [ExcludeFromCodeCoverage] - public class ApiResourceDetailsListResponseExample : IExamplesProvider> - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public List GetExamples() - { - return new List - { - new ApiResourceDetails - { - DisplayName = ExampleData.ApiResourceDisplayName, - Name = ExampleData.ApiResourceName, - Scopes = new List - { - ExampleData.ApiResourceScope1, - ExampleData.ApiResourceScope2 - }, - UserClaims = new List - { - ExampleData.ApiResourceUserClaim1, - ExampleData.ApiResourceUserClaim2 - }, - Description = ExampleData.ApiResourceDescription, - Enabled = ExampleData.ApiResourceEnabled - } - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/ApiResourceDetailsResponseExample.cs b/archive/SecurityService/Common/Examples/ApiResourceDetailsResponseExample.cs deleted file mode 100644 index 75a02453..00000000 --- a/archive/SecurityService/Common/Examples/ApiResourceDetailsResponseExample.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using DataTransferObjects.Responses; - using Swashbuckle.AspNetCore.Filters; - - [ExcludeFromCodeCoverage] - public class ApiResourceDetailsResponseExample : IExamplesProvider - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public ApiResourceDetails GetExamples() - { - return new ApiResourceDetails - { - DisplayName = ExampleData.ApiResourceDisplayName, - Name = ExampleData.ApiResourceName, - Scopes = new List - { - ExampleData.ApiResourceScope1, - ExampleData.ApiResourceScope2 - }, - UserClaims = new List - { - ExampleData.ApiResourceUserClaim1, - ExampleData.ApiResourceUserClaim2 - }, - Description = ExampleData.ApiResourceDescription, - Enabled = ExampleData.ApiResourceEnabled - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/ApiScopeDetailsListResponseExample.cs b/archive/SecurityService/Common/Examples/ApiScopeDetailsListResponseExample.cs deleted file mode 100644 index 1770acd8..00000000 --- a/archive/SecurityService/Common/Examples/ApiScopeDetailsListResponseExample.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using DataTransferObjects.Responses; - using Swashbuckle.AspNetCore.Filters; - - [ExcludeFromCodeCoverage] - public class ApiScopeDetailsListResponseExample : IExamplesProvider> - { - /// - /// Gets the examples. - /// - /// - public List GetExamples() - { - return new List - { - new ApiScopeDetails - { - DisplayName = ExampleData.ApiScopeDisplayName, - Name = ExampleData.ApiScopeName, - Description = ExampleData.ApiScopeDescription, - Enabled = ExampleData.ApiScopeEnabled - } - }; - } - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/ApiScopeDetailsResponseExample.cs b/archive/SecurityService/Common/Examples/ApiScopeDetailsResponseExample.cs deleted file mode 100644 index 1cbf463e..00000000 --- a/archive/SecurityService/Common/Examples/ApiScopeDetailsResponseExample.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using DataTransferObjects.Responses; - using Swashbuckle.AspNetCore.Filters; - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class ApiScopeDetailsResponseExample : IExamplesProvider - { - /// - /// Gets the examples. - /// - /// - public ApiScopeDetails GetExamples() - { - return new ApiScopeDetails - { - DisplayName = ExampleData.ApiScopeDisplayName, - Name = ExampleData.ApiScopeName, - Description = ExampleData.ApiScopeDescription, - Enabled = ExampleData.ApiScopeEnabled - }; - } - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/ClientDetailsListResponseExample.cs b/archive/SecurityService/Common/Examples/ClientDetailsListResponseExample.cs deleted file mode 100644 index 124ce4e8..00000000 --- a/archive/SecurityService/Common/Examples/ClientDetailsListResponseExample.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using DataTransferObjects.Responses; - using Swashbuckle.AspNetCore.Filters; - - [ExcludeFromCodeCoverage] - public class ClientDetailsListResponseExample : IExamplesProvider> - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public List GetExamples() - { - return new List - { - new ClientDetails - { - Enabled = ExampleData.ClientEnabled, - ClientId = ExampleData.ClientId, - AllowOfflineAccess = ExampleData.ClientAllowOfflineAccess, - AllowedGrantTypes = new List - { - ExampleData.ClientAllowedGrantType1, - ExampleData.ClientAllowedGrantType2 - }, - AllowedScopes = new List - { - ExampleData.ClientAllowedScope1, - ExampleData.ClientAllowedScope2 - }, - ClientDescription = ExampleData.ClientDescription, - ClientName = ExampleData.ClientName, - ClientPostLogoutRedirectUris = new List - { - ExampleData.ClientPostLogoutRedirectUri - }, - ClientRedirectUris = new List - { - ExampleData.ClientRedirectUri - }, - RequireConsent = ExampleData.ClientRequireConsent - } - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/ClientDetailsResponseExample.cs b/archive/SecurityService/Common/Examples/ClientDetailsResponseExample.cs deleted file mode 100644 index 36296945..00000000 --- a/archive/SecurityService/Common/Examples/ClientDetailsResponseExample.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using DataTransferObjects.Responses; - using Swashbuckle.AspNetCore.Filters; - - [ExcludeFromCodeCoverage] - public class ClientDetailsResponseExample : IExamplesProvider - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public ClientDetails GetExamples() - { - return new ClientDetails - { - Enabled = ExampleData.ClientEnabled, - ClientId = ExampleData.ClientId, - AllowOfflineAccess = ExampleData.ClientAllowOfflineAccess, - AllowedGrantTypes = new List - { - ExampleData.ClientAllowedGrantType1, - ExampleData.ClientAllowedGrantType2 - }, - AllowedScopes = new List - { - ExampleData.ClientAllowedScope1, - ExampleData.ClientAllowedScope2 - }, - ClientDescription = ExampleData.ClientDescription, - ClientName = ExampleData.ClientName, - ClientPostLogoutRedirectUris = new List - { - ExampleData.ClientPostLogoutRedirectUri - }, - ClientRedirectUris = new List - { - ExampleData.ClientRedirectUri - }, - RequireConsent = ExampleData.ClientRequireConsent - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/CreateApiResourceRequestExample.cs b/archive/SecurityService/Common/Examples/CreateApiResourceRequestExample.cs deleted file mode 100644 index 1dbb142b..00000000 --- a/archive/SecurityService/Common/Examples/CreateApiResourceRequestExample.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using DataTransferObjects.Requests; - using Swashbuckle.AspNetCore.Filters; - - [ExcludeFromCodeCoverage] - public class CreateApiResourceRequestExample : IExamplesProvider - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public CreateApiResourceRequest GetExamples() - { - return new CreateApiResourceRequest - { - Description = ExampleData.ApiResourceDescription, - DisplayName = ExampleData.ApiResourceDisplayName, - Name = ExampleData.ApiResourceName, - Scopes = new List - { - ExampleData.ApiResourceScope1, - ExampleData.ApiResourceScope2 - }, - Secret = ExampleData.ApiResourceSecret, - UserClaims = new List - { - ExampleData.ApiResourceUserClaim1, - ExampleData.ApiResourceUserClaim2 - } - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/CreateApiResourceResponseExample.cs b/archive/SecurityService/Common/Examples/CreateApiResourceResponseExample.cs deleted file mode 100644 index 8a159d54..00000000 --- a/archive/SecurityService/Common/Examples/CreateApiResourceResponseExample.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using DataTransferObjects.Responses; - using Swashbuckle.AspNetCore.Filters; - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class CreateApiResourceResponseExample : IExamplesProvider - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public CreateApiResourceResponse GetExamples() - { - return new CreateApiResourceResponse - { - ApiResourceName = ExampleData.ApiResourceName - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/CreateApiScopeRequestExample.cs b/archive/SecurityService/Common/Examples/CreateApiScopeRequestExample.cs deleted file mode 100644 index 179a9735..00000000 --- a/archive/SecurityService/Common/Examples/CreateApiScopeRequestExample.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using DataTransferObjects.Requests; - using Swashbuckle.AspNetCore.Filters; - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class CreateApiScopeRequestExample : IExamplesProvider - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public CreateApiScopeRequest GetExamples() - { - return new CreateApiScopeRequest - { - Description = ExampleData.ApiScopeDescription, - Name = ExampleData.ApiScopeName, - DisplayName = ExampleData.ApiScopeDisplayName, - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/CreateApiScopeResponseExample.cs b/archive/SecurityService/Common/Examples/CreateApiScopeResponseExample.cs deleted file mode 100644 index 03a0342e..00000000 --- a/archive/SecurityService/Common/Examples/CreateApiScopeResponseExample.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using DataTransferObjects.Responses; - using Swashbuckle.AspNetCore.Filters; - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class CreateApiScopeResponseExample : IExamplesProvider - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public CreateApiScopeResponse GetExamples() - { - return new CreateApiScopeResponse - { - ApiScopeName = ExampleData.ApiScopeName - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/CreateClientRequestExample.cs b/archive/SecurityService/Common/Examples/CreateClientRequestExample.cs deleted file mode 100644 index 43f1893e..00000000 --- a/archive/SecurityService/Common/Examples/CreateClientRequestExample.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using DataTransferObjects.Requests; - using Swashbuckle.AspNetCore.Filters; - - [ExcludeFromCodeCoverage] - public class CreateClientRequestExample : IExamplesProvider - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public CreateClientRequest GetExamples() - { - return new CreateClientRequest - { - Secret = ExampleData.ClientSecret, - AllowOfflineAccess = ExampleData.ClientAllowOfflineAccess, - AllowedGrantTypes = new List - { - ExampleData.ClientAllowedGrantType1, - ExampleData.ClientAllowedGrantType2 - }, - AllowedScopes = new List - { - ExampleData.ClientAllowedScope1, - ExampleData.ClientAllowedScope2 - }, - ClientDescription = ExampleData.ClientDescription, - ClientId = ExampleData.ClientId, - ClientName = ExampleData.ClientName, - ClientPostLogoutRedirectUris = new List - { - ExampleData.ClientPostLogoutRedirectUri - }, - ClientRedirectUris = new List - { - ExampleData.ClientRedirectUri - }, - RequireConsent = ExampleData.ClientRequireConsent - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/CreateClientResponseExample.cs b/archive/SecurityService/Common/Examples/CreateClientResponseExample.cs deleted file mode 100644 index b2d6f924..00000000 --- a/archive/SecurityService/Common/Examples/CreateClientResponseExample.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using DataTransferObjects; - using Swashbuckle.AspNetCore.Filters; - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class CreateClientResponseExample : IExamplesProvider - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public CreateClientResponse GetExamples() - { - return new CreateClientResponse - { - ClientId = ExampleData.ClientId - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/CreateIdentityResourceRequestExample.cs b/archive/SecurityService/Common/Examples/CreateIdentityResourceRequestExample.cs deleted file mode 100644 index 79dfbf4f..00000000 --- a/archive/SecurityService/Common/Examples/CreateIdentityResourceRequestExample.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using DataTransferObjects.Requests; - using Swashbuckle.AspNetCore.Filters; - - [ExcludeFromCodeCoverage] - public class CreateIdentityResourceRequestExample : IExamplesProvider - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public CreateIdentityResourceRequest GetExamples() - { - return new CreateIdentityResourceRequest - { - Description = ExampleData.IdentityResourceDescription, - DisplayName = ExampleData.IdentityResourceDisplayName, - Claims = new List - { - ExampleData.IdentityResourceClaim1, - ExampleData.IdentityResourceClaim2 - }, - Emphasize = ExampleData.IdentityResourceEmphasize, - Name = ExampleData.IdentityResourceName, - Required = ExampleData.IdentityResourceRequired, - ShowInDiscoveryDocument = ExampleData.IdentityResourceShowInDiscoveryDocument - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/CreateIdentityResourceResponseExample.cs b/archive/SecurityService/Common/Examples/CreateIdentityResourceResponseExample.cs deleted file mode 100644 index d0ec4be2..00000000 --- a/archive/SecurityService/Common/Examples/CreateIdentityResourceResponseExample.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using DataTransferObjects.Responses; - using Swashbuckle.AspNetCore.Filters; - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class CreateIdentityResourceResponseExample : IExamplesProvider - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public CreateIdentityResourceResponse GetExamples() - { - return new CreateIdentityResourceResponse - { - IdentityResourceName = ExampleData.IdentityResourceName - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/CreateRoleRequestExample.cs b/archive/SecurityService/Common/Examples/CreateRoleRequestExample.cs deleted file mode 100644 index 6d846300..00000000 --- a/archive/SecurityService/Common/Examples/CreateRoleRequestExample.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using DataTransferObjects.Requests; - using Swashbuckle.AspNetCore.Filters; - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class CreateRoleRequestExample : IExamplesProvider - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public CreateRoleRequest GetExamples() - { - return new CreateRoleRequest - { - RoleName = ExampleData.RoleName - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/CreateRoleResponseExample.cs b/archive/SecurityService/Common/Examples/CreateRoleResponseExample.cs deleted file mode 100644 index 4eaee5df..00000000 --- a/archive/SecurityService/Common/Examples/CreateRoleResponseExample.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using DataTransferObjects.Responses; - using Swashbuckle.AspNetCore.Filters; - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class CreateRoleResponseExample : IExamplesProvider - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public CreateRoleResponse GetExamples() - { - return new CreateRoleResponse - { - RoleId = ExampleData.RoleId - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/CreateUserRequestExample.cs b/archive/SecurityService/Common/Examples/CreateUserRequestExample.cs deleted file mode 100644 index 57d19f46..00000000 --- a/archive/SecurityService/Common/Examples/CreateUserRequestExample.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using DataTransferObjects; - using Swashbuckle.AspNetCore.Filters; - - [ExcludeFromCodeCoverage] - public class CreateUserRequestExample : IExamplesProvider - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public CreateUserRequest GetExamples() - { - return new CreateUserRequest - { - Claims = new Dictionary - { - {ExampleData.UserClaim1Name, ExampleData.UserClaim1Value}, - {ExampleData.UserClaim2Name, ExampleData.UserClaim2Value} - }, - EmailAddress = ExampleData.UserEmailAddress, - FamilyName = ExampleData.UserFamilyName, - GivenName = ExampleData.UserGivenName, - MiddleName = ExampleData.UserMiddleName, - PhoneNumber = ExampleData.UserPhoneNumber, - Roles = new List - { - ExampleData.RoleName - } - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/CreateUserResponseExample.cs b/archive/SecurityService/Common/Examples/CreateUserResponseExample.cs deleted file mode 100644 index fab27593..00000000 --- a/archive/SecurityService/Common/Examples/CreateUserResponseExample.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using DataTransferObjects; - using Swashbuckle.AspNetCore.Filters; - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class CreateUserResponseExample : IExamplesProvider - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public CreateUserResponse GetExamples() - { - return new CreateUserResponse - { - UserId = ExampleData.UserId - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/ExampleData.cs b/archive/SecurityService/Common/Examples/ExampleData.cs deleted file mode 100644 index 82562546..00000000 --- a/archive/SecurityService/Common/Examples/ExampleData.cs +++ /dev/null @@ -1,253 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using System; - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - internal static class ExampleData - { - #region Fields - - /// - /// The API resource description - /// - public static String ApiResourceDescription = "Example Api Respource"; - - /// - /// The API resource display name - /// - public static String ApiResourceDisplayName = "Example Api"; - - /// - /// The API resource enabled - /// - public static Boolean ApiResourceEnabled = true; - - /// - /// The API resource name - /// - public static String ApiResourceName = "Example Api"; - - /// - /// The API resource scope1 - /// - public static String ApiResourceScope1 = "ExampleScope1"; - - /// - /// The API resource scope2 - /// - public static String ApiResourceScope2 = "ExampleScope2"; - - /// - /// The API resource secret - /// - public static String ApiResourceSecret = "ExampleApiSecret"; - - /// - /// The API resource user claim1 - /// - public static String ApiResourceUserClaim1 = "ExampleUserClaim1"; - - /// - /// The API resource user claim2 - /// - public static String ApiResourceUserClaim2 = "ExampleUserClaim2"; - - /// - /// The API scope description - /// - public static String ApiScopeDescription = "Example Api Scope"; - - /// - /// The API scope display name - /// - public static String ApiScopeDisplayName = "Example Api Scope Display Name"; - - /// - /// The API scope enabled - /// - public static Boolean ApiScopeEnabled = true; - - /// - /// The API scope name - /// - public static String ApiScopeName = "Example Api Scope Name"; - - /// - /// The client allowed grant type1 - /// - public static String ClientAllowedGrantType1 = "Grant1"; - - /// - /// The client allowed grant type2 - /// - public static String ClientAllowedGrantType2 = "Grant2"; - - /// - /// The client allowed scope1 - /// - public static String ClientAllowedScope1 = "AllowedScope1"; - - /// - /// The client allowed scope2 - /// - public static String ClientAllowedScope2 = "AllowedScope2"; - - /// - /// The client allow offline access - /// - public static Boolean ClientAllowOfflineAccess = true; - - /// - /// The client description - /// - public static String ClientDescription = "Example Client Description"; - - /// - /// The client enabled - /// - public static Boolean ClientEnabled = true; - - /// - /// The client identifier - /// - public static String ClientId = "ExampleClientId"; - - /// - /// The client name - /// - public static String ClientName = "Example Client"; - - /// - /// The client post logout redirect URI - /// - public static String ClientPostLogoutRedirectUri = "http://localhost/signout"; - - /// - /// The client redirect URI - /// - public static String ClientRedirectUri = "http://localhost/signin"; - - /// - /// The client require consent - /// - public static Boolean ClientRequireConsent = true; - - /// - /// The client secret - /// - public static String ClientSecret = "ClientSecret1"; - - /// - /// The identity resource claim1 - /// - public static String IdentityResourceClaim1 = "Example Claim 1"; - - /// - /// The identity resource claim2 - /// - public static String IdentityResourceClaim2 = "Example Claim 2"; - - /// - /// The identity resource description - /// - public static String IdentityResourceDescription = "Example Identity Resource Description"; - - /// - /// The identity resource display name - /// - public static String IdentityResourceDisplayName = "Example Identity Resource Display Name"; - - /// - /// The identity resource emphasize - /// - public static Boolean IdentityResourceEmphasize = true; - - /// - /// The identity resource name - /// - public static String IdentityResourceName = "Example Identity Resource"; - - /// - /// The identity resource required - /// - public static Boolean IdentityResourceRequired = true; - - /// - /// The identity resource show in discovery document - /// - public static Boolean IdentityResourceShowInDiscoveryDocument = true; - - /// - /// The role identifier - /// - public static Guid RoleId = Guid.Parse("32E13195-A5B5-46B5-A84B-CF63BE06A9EF"); - - /// - /// The role name - /// - public static String RoleName = "Example Role"; - - /// - /// The user claim1 name - /// - public static String UserClaim1Name = "ExampleUserClaim1"; - - /// - /// The user claim1 value - /// - public static String UserClaim1Value = "ExampleUserClaim1Value"; - - /// - /// The user claim2 name - /// - public static String UserClaim2Name = "ExampleUserClaim2"; - - /// - /// The user claim2 value - /// - public static String UserClaim2Value = "ExampleUserClaim2Value"; - - /// - /// The user email address - /// - public static String UserEmailAddress = "exampleuser@exampleuseremail.co.uk"; - - /// - /// The user family name - /// - public static String UserFamilyName = "Example Family Name"; - - /// - /// The user given name - /// - public static String UserGivenName = "Example Given Name"; - - /// - /// The user identifier - /// - public static Guid UserId = Guid.Parse("8A927E15-AC95-421A-B1DC-2EF76AC6096B"); - - /// - /// The user middle name - /// - public static String UserMiddleName = "Example Middle Name"; - - /// - /// The user name - /// - public static String UserName = "exampleuser@exampleuseremail.co.uk"; - - /// - /// The user password - /// - public static String UserPassword = "password"; - - /// - /// The user phone number - /// - public static String UserPhoneNumber = "1234567890"; - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/IdentityResourceDetailsListResponseExample.cs b/archive/SecurityService/Common/Examples/IdentityResourceDetailsListResponseExample.cs deleted file mode 100644 index ca10e080..00000000 --- a/archive/SecurityService/Common/Examples/IdentityResourceDetailsListResponseExample.cs +++ /dev/null @@ -1,44 +0,0 @@ -/// -/// -/// -namespace SecurityService.Common.Examples -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using DataTransferObjects.Responses; - using Swashbuckle.AspNetCore.Filters; - - [ExcludeFromCodeCoverage] - public class IdentityResourceDetailsListResponseExample : IExamplesProvider> - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public List GetExamples() - { - return new List - { - new IdentityResourceDetails - { - DisplayName = ExampleData.IdentityResourceDisplayName, - Description = ExampleData.IdentityResourceDescription, - Name = ExampleData.IdentityResourceName, - Claims = new List - { - ExampleData.IdentityResourceClaim1, - ExampleData.IdentityResourceClaim2 - }, - Emphasize = ExampleData.IdentityResourceEmphasize, - Required = ExampleData.IdentityResourceRequired, - ShowInDiscoveryDocument = ExampleData.IdentityResourceShowInDiscoveryDocument - } - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/IdentityResourceDetailsResponseExample.cs b/archive/SecurityService/Common/Examples/IdentityResourceDetailsResponseExample.cs deleted file mode 100644 index f7caf310..00000000 --- a/archive/SecurityService/Common/Examples/IdentityResourceDetailsResponseExample.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using DataTransferObjects.Responses; - using Swashbuckle.AspNetCore.Filters; - - [ExcludeFromCodeCoverage] - public class IdentityResourceDetailsResponseExample : IExamplesProvider - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public IdentityResourceDetails GetExamples() - { - return new IdentityResourceDetails - { - DisplayName = ExampleData.IdentityResourceDisplayName, - Description = ExampleData.IdentityResourceDescription, - Name = ExampleData.IdentityResourceName, - Claims = new List - { - ExampleData.IdentityResourceClaim1, - ExampleData.IdentityResourceClaim2 - }, - Emphasize = ExampleData.IdentityResourceEmphasize, - Required = ExampleData.IdentityResourceRequired, - ShowInDiscoveryDocument = ExampleData.IdentityResourceShowInDiscoveryDocument - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/RoleDetailsListResponseExample.cs b/archive/SecurityService/Common/Examples/RoleDetailsListResponseExample.cs deleted file mode 100644 index b0ed5871..00000000 --- a/archive/SecurityService/Common/Examples/RoleDetailsListResponseExample.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using DataTransferObjects.Responses; - using Swashbuckle.AspNetCore.Filters; - - [ExcludeFromCodeCoverage] - public class RoleDetailsListResponseExample : IExamplesProvider> - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public List GetExamples() - { - return new List - { - new RoleDetails - { - RoleId = ExampleData.RoleId, - RoleName = ExampleData.RoleName - } - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/RoleDetailsResponseExample.cs b/archive/SecurityService/Common/Examples/RoleDetailsResponseExample.cs deleted file mode 100644 index a049619e..00000000 --- a/archive/SecurityService/Common/Examples/RoleDetailsResponseExample.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using DataTransferObjects.Responses; - using Swashbuckle.AspNetCore.Filters; - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public class RoleDetailsResponseExample : IExamplesProvider - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public RoleDetails GetExamples() - { - return new RoleDetails - { - RoleId = ExampleData.RoleId, - RoleName = ExampleData.RoleName - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/UserDetailsListResponseExample.cs b/archive/SecurityService/Common/Examples/UserDetailsListResponseExample.cs deleted file mode 100644 index c6121418..00000000 --- a/archive/SecurityService/Common/Examples/UserDetailsListResponseExample.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using DataTransferObjects.Responses; - using Swashbuckle.AspNetCore.Filters; - - [ExcludeFromCodeCoverage] - public class UserDetailsListResponseExample : IExamplesProvider> - { - /// - /// Gets the examples. - /// - /// - public List GetExamples() - { - return new List - { - new UserDetails - { - UserId = ExampleData.UserId, - Claims = new Dictionary - { - { ExampleData.UserClaim1Name, ExampleData.UserClaim1Value }, - { ExampleData.UserClaim2Name, ExampleData.UserClaim2Value } - }, - EmailAddress = ExampleData.UserEmailAddress, - PhoneNumber = ExampleData.UserPhoneNumber, - Roles = new List - { - ExampleData.RoleName - }, - UserName = ExampleData.UserName - } - }; - } - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Examples/UserDetailsResponseExample.cs b/archive/SecurityService/Common/Examples/UserDetailsResponseExample.cs deleted file mode 100644 index 70150910..00000000 --- a/archive/SecurityService/Common/Examples/UserDetailsResponseExample.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace SecurityService.Common.Examples -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using DataTransferObjects.Responses; - using Swashbuckle.AspNetCore.Filters; - - [ExcludeFromCodeCoverage] - public class UserDetailsResponseExample : IExamplesProvider - { - #region Methods - - /// - /// Gets the examples. - /// - /// - public UserDetails GetExamples() - { - return new UserDetails - { - UserId = ExampleData.UserId, - Claims = new Dictionary - { - {ExampleData.UserClaim1Name, ExampleData.UserClaim1Value}, - {ExampleData.UserClaim2Name, ExampleData.UserClaim2Value} - }, - EmailAddress = ExampleData.UserEmailAddress, - PhoneNumber = ExampleData.UserPhoneNumber, - Roles = new List - { - ExampleData.RoleName - }, - UserName = ExampleData.UserName - }; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/Extensions.cs b/archive/SecurityService/Common/Extensions.cs deleted file mode 100644 index e3759e73..00000000 --- a/archive/SecurityService/Common/Extensions.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace SecurityService.Common -{ - using System; - using System.Diagnostics.CodeAnalysis; - using Duende.IdentityServer.Models; - using IdentityServerHost.Quickstart.UI; - using Microsoft.AspNetCore.Mvc; - - [ExcludeFromCodeCoverage] - public static class Extensions - { - /// - /// Checks if the redirect URI is for a native client. - /// - /// - public static bool IsNativeClient(this AuthorizationRequest context) - { - return !context.RedirectUri.StartsWith("https", StringComparison.Ordinal) - && !context.RedirectUri.StartsWith("http", StringComparison.Ordinal); - } - } -} diff --git a/archive/SecurityService/Common/SecurityHeadersAttribute.cs b/archive/SecurityService/Common/SecurityHeadersAttribute.cs deleted file mode 100644 index 19530031..00000000 --- a/archive/SecurityService/Common/SecurityHeadersAttribute.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - -namespace SecurityService.Common -{ - using System.Diagnostics.CodeAnalysis; - using Microsoft.AspNetCore.Mvc; - using Microsoft.AspNetCore.Mvc.Filters; - - [ExcludeFromCodeCoverage] - public class SecurityHeadersAttribute : ActionFilterAttribute - { - public override void OnResultExecuting(ResultExecutingContext context) - { - var result = context.Result; - if (result is ViewResult) - { - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options - if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Type-Options")) - { - context.HttpContext.Response.Headers.Add("X-Content-Type-Options", "nosniff"); - } - - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options - if (!context.HttpContext.Response.Headers.ContainsKey("X-Frame-Options")) - { - context.HttpContext.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN"); - } - - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy - var csp = "default-src 'self'; object-src 'none'; frame-ancestors 'none'; sandbox allow-forms allow-same-origin allow-scripts; base-uri 'self';"; - // also consider adding upgrade-insecure-requests once you have HTTPS in place for production - //csp += "upgrade-insecure-requests;"; - // also an example if you need client images to be displayed from twitter - // csp += "img-src 'self' https://pbs.twimg.com;"; - - // once for standards compliant browsers - if (!context.HttpContext.Response.Headers.ContainsKey("Content-Security-Policy")) - { - context.HttpContext.Response.Headers.Add("Content-Security-Policy", csp); - } - // and once again for IE - if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Security-Policy")) - { - context.HttpContext.Response.Headers.Add("X-Content-Security-Policy", csp); - } - - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy - var referrer_policy = "no-referrer"; - if (!context.HttpContext.Response.Headers.ContainsKey("Referrer-Policy")) - { - context.HttpContext.Response.Headers.Add("Referrer-Policy", referrer_policy); - } - } - } - } -} diff --git a/archive/SecurityService/Common/StartupExtensions.cs b/archive/SecurityService/Common/StartupExtensions.cs deleted file mode 100644 index 1ab4ffdb..00000000 --- a/archive/SecurityService/Common/StartupExtensions.cs +++ /dev/null @@ -1,56 +0,0 @@ -using Microsoft.Extensions.Logging; - -namespace SecurityService -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using Database.DbContexts; - using Duende.IdentityServer.EntityFramework.DbContexts; - using Duende.IdentityServer.Models; - using Microsoft.EntityFrameworkCore; - using Microsoft.Extensions.DependencyInjection; - using Shared.General; - - [ExcludeFromCodeCoverage] - public static class StartupExtensions - { - #region Methods - - public static IIdentityServerBuilder AddIdentityServerStorage(this IIdentityServerBuilder builder, - String configurationConnectionString, - String persistedGrantStoreConenctionString, - String authenticationConenctionString) { - builder.AddConfigurationStore(options => { options.ConfigureDbContext = c => c.UseSqlServer(configurationConnectionString, sqlOptions => sqlOptions.MigrationsAssembly("SecurityService.SqlServerMigrations")) - .EnableSensitiveDataLogging() - .LogTo(Console.WriteLine, LogLevel.Information); }); - - builder.AddOperationalStore(options => { options.ConfigureDbContext = c => c.UseSqlServer(persistedGrantStoreConenctionString, sqlOptions => sqlOptions.MigrationsAssembly("SecurityService.SqlServerMigrations")) - .EnableSensitiveDataLogging() - .LogTo(Console.WriteLine, LogLevel.Information); }); - - builder.Services.AddDbContext(builder => builder.UseSqlServer(authenticationConenctionString, sqlOptions => sqlOptions.MigrationsAssembly("SecurityService.SqlServerMigrations") - ).EnableSensitiveDataLogging() - .LogTo(Console.WriteLine, LogLevel.Information)); - - return builder; - } - - public static IIdentityServerBuilder AddIntegrationTestConfiguration(this IIdentityServerBuilder builder) - { - builder.AddInMemoryClients(new List()); - builder.AddInMemoryApiResources(new List()); - builder.AddInMemoryIdentityResources(new List()); - - builder.AddConfigurationStore(options => { options.ConfigureDbContext = c => c.UseInMemoryDatabase("Configuration"); }); - builder.AddOperationalStore(options => { options.ConfigureDbContext = c => c.UseInMemoryDatabase("PersistedGrant"); }); - builder.Services.AddDbContext(builder => builder.UseInMemoryDatabase("Authentication")); - - builder.AddInMemoryPersistedGrants(); - - return builder; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/SwaggerDefaultValues.cs b/archive/SecurityService/Common/SwaggerDefaultValues.cs deleted file mode 100644 index 42885d2a..00000000 --- a/archive/SecurityService/Common/SwaggerDefaultValues.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Microsoft.OpenApi; - -namespace SecurityService -{ - using System.Diagnostics.CodeAnalysis; - using System.Linq; - using Microsoft.AspNetCore.Mvc.ApiExplorer; - using Swashbuckle.AspNetCore.SwaggerGen; - - [ExcludeFromCodeCoverage] - public class SwaggerDefaultValues : IOperationFilter - { - /// - /// Applies the filter to the specified operation using the given context. - /// - /// The operation to apply the filter to. - /// The current operation filter context. - public void Apply(OpenApiOperation operation, - OperationFilterContext context) - { - ApiDescription apiDescription = context.ApiDescription; - - if (operation.Parameters == null) - { - return; - } - - foreach (OpenApiParameter parameter in operation.Parameters) - { - ApiParameterDescription description = apiDescription.ParameterDescriptions.First(p => p.Name == parameter.Name); - - if (parameter.Description == null) - { - parameter.Description = description.ModelMetadata?.Description; - } - - parameter.Required |= description.IsRequired; - } - } - } -} \ No newline at end of file diff --git a/archive/SecurityService/Common/SwaggerJsonConverter.cs b/archive/SecurityService/Common/SwaggerJsonConverter.cs deleted file mode 100644 index cd7be23f..00000000 --- a/archive/SecurityService/Common/SwaggerJsonConverter.cs +++ /dev/null @@ -1,77 +0,0 @@ -namespace SecurityService -{ - using System; - using System.Diagnostics.CodeAnalysis; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - - [ExcludeFromCodeCoverage] - public class SwaggerJsonConverter : JsonConverter - { - #region Properties - - /// - /// Gets a value indicating whether this can read JSON. - /// - /// - /// true if this can read JSON; otherwise, false. - /// - public override Boolean CanRead => false; - - #endregion - - #region Methods - - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// - /// true if this instance can convert the specified object type; otherwise, false. - /// - public override Boolean CanConvert(Type objectType) - { - return true; - } - - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// - /// The object value. - /// - /// - /// - public override Object ReadJson(JsonReader reader, - Type objectType, - Object existingValue, - JsonSerializer serializer) - { - // Not used because CanRead returns false - return new Object(); - } - - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, - Object value, - JsonSerializer serializer) - { - // Disable sending the $type in the serialized json - serializer.TypeNameHandling = TypeNameHandling.None; - - JToken t = JToken.FromObject(value); - t.WriteTo(writer); - } - - #endregion - } -} diff --git a/archive/SecurityService/Config.cs b/archive/SecurityService/Config.cs deleted file mode 100644 index 9faba2ea..00000000 --- a/archive/SecurityService/Config.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Duende.IdentityModel; - -namespace SecurityService -{ - using System.Diagnostics.CodeAnalysis; - using System.Security.Claims; - using System.Text.Json; - using Duende.IdentityServer; - using Duende.IdentityServer.Models; - using Duende.IdentityServer.Test; - - [ExcludeFromCodeCoverage] - public static class Config - { - public static IEnumerable IdentityResources => - new IdentityResource[] - { - new IdentityResources.OpenId(), - new IdentityResources.Profile(), - }; - - public static IEnumerable ApiScopes => - new ApiScope[] - { - new ApiScope("scope1"), - new ApiScope("scope2"), - }; - - public static IEnumerable Clients => - new List - { - // machine to machine client (from quickstart 1) - new Client - { - ClientId = "client", - ClientSecrets = { new Secret("secret".Sha256()) }, - - AllowedGrantTypes = GrantTypes.ClientCredentials, - // scopes that client has access to - AllowedScopes = { "api1" } - }, - // interactive ASP.NET Core MVC client - new Client - { - ClientId = "mvc", - ClientSecrets = { new Secret("secret".Sha256()) }, - - AllowedGrantTypes = GrantTypes.Code, - - // where to redirect to after login - RedirectUris = { "https://localhost:5004/signin-oidc" }, - - // where to redirect to after logout - PostLogoutRedirectUris = { "https://localhost:5004/signout-callback-oidc" }, - - AllowedScopes = new List - { - IdentityServerConstants.StandardScopes.OpenId, - IdentityServerConstants.StandardScopes.Profile - } - } - }; - - public static List Users - { - get - { - var address = new - { - street_address = "One Hacker Way", - locality = "Heidelberg", - postal_code = 69118, - country = "Germany" - }; - - return new List - { - new TestUser - { - SubjectId = "818727", - Username = "alice", - Password = "alice", - Claims = - { - new Claim(JwtClaimTypes.Name, "Alice Smith"), - new Claim(JwtClaimTypes.GivenName, "Alice"), - new Claim(JwtClaimTypes.FamilyName, "Smith"), - new Claim(JwtClaimTypes.Email, "AliceSmith@email.com"), - new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean), - new Claim(JwtClaimTypes.WebSite, "https://alice.com"), - new Claim(JwtClaimTypes.Address, JsonSerializer.Serialize(address), IdentityServerConstants.ClaimValueTypes.Json) - } - }, - new TestUser - { - SubjectId = "88421113", - Username = "bob", - Password = "bob", - Claims = - { - new Claim(JwtClaimTypes.Name, "Bob Smith"), - new Claim(JwtClaimTypes.GivenName, "Bob"), - new Claim(JwtClaimTypes.FamilyName, "Smith"), - new Claim(JwtClaimTypes.Email, "BobSmith@email.com"), - new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean), - new Claim(JwtClaimTypes.WebSite, "https://bob.com"), - new Claim(JwtClaimTypes.Address, JsonSerializer.Serialize(address), IdentityServerConstants.ClaimValueTypes.Json) - } - } - }; - } - } - } -} diff --git a/archive/SecurityService/Dockerfile b/archive/SecurityService/Dockerfile deleted file mode 100644 index f05b5871..00000000 --- a/archive/SecurityService/Dockerfile +++ /dev/null @@ -1,37 +0,0 @@ -FROM stuartferguson/txnprocbase AS base -WORKDIR /app - -FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build - -# Set the ARG for your GitHub Secret -ARG NUGET_TOKEN - -WORKDIR /src -COPY ["Certificates/*.*", "Certificates/"] -COPY ["SecurityService/NuGet.Config", "."] -# Replace the placeholders in the NuGet.config file with the GitHub Secret -RUN sed -i "s|NUGET_TOKEN|${NUGET_TOKEN}|g" NuGet.Config - -COPY ["SecurityService/SecurityService.csproj", "SecurityService/"] -COPY ["SecurityService.BusinessLogic/SecurityService.BusinessLogic.csproj", "SecurityService.BusinessLogic/"] -COPY ["SecurityService.DataTransferObjects/SecurityService.DataTransferObjects.csproj", "SecurityService.DataTransferObjects/"] - -RUN dotnet restore "SecurityService/SecurityService.csproj" -COPY . . -WORKDIR /src/SecurityService -RUN dotnet build "SecurityService.csproj" -c Release -o /app - -WORKDIR /src/Certificates -# Sort out certificate stuff here -RUN cp aspnetapp-root-cert.cer /usr/local/share/ca-certificates/ -RUN update-ca-certificates - -WORKDIR /src/SecurityService -FROM build AS publish -RUN dotnet publish "SecurityService.csproj" -c Release -o /app - -FROM base AS final -WORKDIR /app -COPY --from=publish /app . -USER app -ENTRYPOINT ["dotnet", "SecurityService.dll"] \ No newline at end of file diff --git a/archive/SecurityService/DockerfileWindows b/archive/SecurityService/DockerfileWindows deleted file mode 100644 index e12fbf50..00000000 --- a/archive/SecurityService/DockerfileWindows +++ /dev/null @@ -1,27 +0,0 @@ -FROM stuartferguson/txnprocbasewindows AS base -USER ContainerAdministrator -WORKDIR /app - -FROM mcr.microsoft.com/dotnet/sdk:10.0-windowsservercore-ltsc2022 AS build -WORKDIR /src -COPY ["Certificates/*.*", "Certificates/"] -COPY ["SecurityService/NuGet.Config", "."] -COPY ["SecurityService/SecurityService.csproj", "SecurityService/"] -COPY ["SecurityService.BusinessLogic/SecurityService.BusinessLogic.csproj", "SecurityService.BusinessLogic/"] -COPY ["SecurityService.DataTransferObjects/SecurityService.DataTransferObjects.csproj", "SecurityService.DataTransferObjects/"] - -RUN dotnet restore "SecurityService/SecurityService.csproj" -COPY . . -WORKDIR "/src/SecurityService" -RUN dotnet build "SecurityService.csproj" -c Release -o /app -WORKDIR "/src/Certificates" -RUN powershell -Command Import-PfxCertificate -FilePath "aspnetapp-root-cert.pfx" -Password (ConvertTo-SecureString -String 'password' -AsPlainText -Force) -CertStoreLocation Cert:\LocalMachine\Root - -WORKDIR "/src/SecurityService" -FROM build AS publish -RUN dotnet publish "SecurityService.csproj" -c Release -o /app - -FROM base AS final -WORKDIR /app -COPY --from=publish /app . -ENTRYPOINT ["dotnet", "SecurityService.dll"] \ No newline at end of file diff --git a/archive/SecurityService/Endpoints/ApiResourceEndpoints.cs b/archive/SecurityService/Endpoints/ApiResourceEndpoints.cs deleted file mode 100644 index 3774e59b..00000000 --- a/archive/SecurityService/Endpoints/ApiResourceEndpoints.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Microsoft.AspNetCore.Routing; - -namespace SecurityService.Endpoints -{ - using Microsoft.AspNetCore.Builder; - - public static class ApiResourceEndpoints - { - public static void MapApiResourceEndpoints(this IEndpointRouteBuilder endpoints) - { - endpoints.MapPost("api/apiresources", Handlers.ApiResourceHandler.CreateApiResource) - .WithName("CreateApiResource"); - - endpoints.MapGet("api/apiresources/{apiResourceName}", Handlers.ApiResourceHandler.GetApiResource) - .WithName("GetApiResource"); - - endpoints.MapGet("api/apiresources", Handlers.ApiResourceHandler.GetApiResources) - .WithName("GetApiResources"); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService/Endpoints/ApiScopeEndpoints.cs b/archive/SecurityService/Endpoints/ApiScopeEndpoints.cs deleted file mode 100644 index 01ca68e4..00000000 --- a/archive/SecurityService/Endpoints/ApiScopeEndpoints.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Microsoft.AspNetCore.Routing; - -namespace SecurityService.Endpoints -{ - using Microsoft.AspNetCore.Builder; - - public static class ApiScopeEndpoints - { - public static void MapApiScopeEndpoints(this IEndpointRouteBuilder endpoints) - { - endpoints.MapPost("api/apiscopes", Handlers.ApiScopeHandler.CreateApiScope) - .WithName("CreateApiScope"); - - endpoints.MapGet("api/apiscopes/{apiScopeName}", Handlers.ApiScopeHandler.GetApiScope) - .WithName("GetApiScope"); - - endpoints.MapGet("api/apiscopes", Handlers.ApiScopeHandler.GetApiScopes) - .WithName("GetApiScopes"); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService/Endpoints/ClientEndpoints.cs b/archive/SecurityService/Endpoints/ClientEndpoints.cs deleted file mode 100644 index 1d1e13f1..00000000 --- a/archive/SecurityService/Endpoints/ClientEndpoints.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Microsoft.AspNetCore.Routing; - -namespace SecurityService.Endpoints -{ - using Microsoft.AspNetCore.Builder; - - public static class ClientEndpoints - { - public static void MapClientEndpoints(this IEndpointRouteBuilder endpoints) - { - endpoints.MapPost("api/clients", Handlers.ClientHandler.CreateClient) - .WithName("CreateClient"); - - endpoints.MapGet("api/clients/{clientId}", Handlers.ClientHandler.GetClient) - .WithName("GetClient"); - - endpoints.MapGet("api/clients", Handlers.ClientHandler.GetClients) - .WithName("GetClients"); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService/Endpoints/DeveloperEndpoints.cs b/archive/SecurityService/Endpoints/DeveloperEndpoints.cs deleted file mode 100644 index d31eb1f5..00000000 --- a/archive/SecurityService/Endpoints/DeveloperEndpoints.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore.Routing; - -namespace SecurityService.Endpoints -{ - using Microsoft.AspNetCore.Builder; - - public static class DeveloperEndpoints - { - public static void MapDeveloperEndpoints(this IEndpointRouteBuilder endpoints) - { - endpoints.MapGet("api/developer/lastemail", Handlers.DeveloperHandler.GetLastEmailMessage) - .WithName("GetLastEmailMessage"); - - endpoints.MapGet("api/developer/lastsms", Handlers.DeveloperHandler.GetLastSMSMessage) - .WithName("GetLastSMSMessage"); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService/Endpoints/IdentityResourceEndpoints.cs b/archive/SecurityService/Endpoints/IdentityResourceEndpoints.cs deleted file mode 100644 index 60948c97..00000000 --- a/archive/SecurityService/Endpoints/IdentityResourceEndpoints.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.AspNetCore.Routing; - -namespace SecurityService.Endpoints -{ - using Microsoft.AspNetCore.Builder; - - public static class IdentityResourceEndpoints - { - public static void MapIdentityResourceEndpoints(this IEndpointRouteBuilder endpoints) - { - endpoints.MapPost("api/identityresources", Handlers.IdentityResourceHandler.CreateIdentityResource) - .WithName("CreateIdentityResource"); - - - endpoints.MapGet("api/identityresources/{apiResourceName}", Handlers.IdentityResourceHandler.GetIdentityResource) - .WithName("GetIdentityResource"); - - endpoints.MapGet("api/identityresources", Handlers.IdentityResourceHandler.GetIdentityResources) - .WithName("GetIdentityResources"); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService/Endpoints/RoleEndpoints.cs b/archive/SecurityService/Endpoints/RoleEndpoints.cs deleted file mode 100644 index c88773bd..00000000 --- a/archive/SecurityService/Endpoints/RoleEndpoints.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Microsoft.AspNetCore.Routing; - -namespace SecurityService.Endpoints -{ - using Microsoft.AspNetCore.Builder; - - public static class RoleEndpoints - { - public static void MapRoleEndpoints(this IEndpointRouteBuilder endpoints) - { - endpoints.MapPost("api/roles", Handlers.RoleHandler.CreateRole) - .WithName("CreateRole"); - - endpoints.MapGet("api/roles/{roleId:guid}", Handlers.RoleHandler.GetRole) - .WithName("GetRole"); - - endpoints.MapGet("api/roles", Handlers.RoleHandler.GetRoles) - .WithName("GetRoles"); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService/Endpoints/UserEndpoints.cs b/archive/SecurityService/Endpoints/UserEndpoints.cs deleted file mode 100644 index 659df721..00000000 --- a/archive/SecurityService/Endpoints/UserEndpoints.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Microsoft.AspNetCore.Routing; - -namespace SecurityService.Endpoints -{ - using Microsoft.AspNetCore.Builder; - - public static class UserEndpoints - { - public static void MapUserEndpoints(this IEndpointRouteBuilder endpoints) - { - endpoints.MapPost("api/users", Handlers.UserHandler.CreateUser) - .WithName("CreateUser"); - - endpoints.MapGet("api/users/{userId:guid}", Handlers.UserHandler.GetUser) - .WithName("GetUser"); - - endpoints.MapGet("api/users", Handlers.UserHandler.GetUsers) - .WithName("GetUsers"); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService/Extensions.cs b/archive/SecurityService/Extensions.cs deleted file mode 100644 index c48f579f..00000000 --- a/archive/SecurityService/Extensions.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - - -using System; -using Duende.IdentityServer.Models; -using Microsoft.AspNetCore.Mvc; - -namespace IdentityServerHost.Quickstart.UI -{ - using System.Diagnostics.CodeAnalysis; - - [ExcludeFromCodeCoverage] - public static class Extensions - { - /// - /// Checks if the redirect URI is for a native client. - /// - /// - public static bool IsNativeClient(this AuthorizationRequest context) - { - return !context.RedirectUri.StartsWith("https", StringComparison.Ordinal) - && !context.RedirectUri.StartsWith("http", StringComparison.Ordinal); - } - - //public static IActionResult LoadingPage(this Controller controller, string viewName, string redirectUri) - //{ - // controller.HttpContext.Response.StatusCode = 200; - // controller.HttpContext.Response.Headers["Location"] = ""; - - // return controller.View(viewName, new RedirectViewModel { RedirectUrl = redirectUri }); - //} - } -} diff --git a/archive/SecurityService/Factories/ModelFactory.cs b/archive/SecurityService/Factories/ModelFactory.cs deleted file mode 100644 index 28ea355d..00000000 --- a/archive/SecurityService/Factories/ModelFactory.cs +++ /dev/null @@ -1,179 +0,0 @@ -namespace SecurityService.Factories -{ - using System.Collections.Generic; - using System.Linq; - using DataTransferObjects.Responses; - using Duende.IdentityServer.Models; - - public static class ModelFactory { - #region Methods - - public static UserDetails ConvertFrom(Models.UserDetails model) { - if (model == null) { - return null; - } - - return new UserDetails { - UserName = model.Username, - PhoneNumber = model.PhoneNumber, - Roles = model.Roles, - Claims = model.Claims, - UserId = model.UserId, - EmailAddress = model.Email, - RegistrationDateTime = model.RegistrationDateTime - }; - } - - public static RoleDetails ConvertFrom(Models.RoleDetails model) { - if (model == null) { - return null; - } - - return new RoleDetails { RoleId = model.RoleId, RoleName = model.RoleName }; - } - - public static List ConvertFrom(List model) { - if (model == null || model.Any() == false) { - return new List(); - } - - List userDetailsList = new List(); - - foreach (Models.UserDetails userDetails in model) { - userDetailsList.Add(ConvertFrom(userDetails)); - } - - return userDetailsList; - } - - public static List ConvertFrom(List model) { - if (model == null || model.Any() == false) { - return new List(); - } - - List roleDetailsList = new List(); - - foreach (Models.RoleDetails roleDetails in model) { - roleDetailsList.Add(ConvertFrom(roleDetails)); - } - - return roleDetailsList; - } - - public static ClientDetails ConvertFrom(Client model) { - if (model == null) { - return null; - } - - return new ClientDetails { - ClientId = model.ClientId, - AllowedScopes = model.AllowedScopes.ToList(), - AllowedGrantTypes = model.AllowedGrantTypes.ToList(), - ClientName = model.ClientName, - ClientDescription = model.Description, - Enabled = model.Enabled, - ClientPostLogoutRedirectUris = model.PostLogoutRedirectUris.ToList(), - RequireConsent = model.RequireConsent, - ClientRedirectUris = model.RedirectUris.ToList(), - AllowOfflineAccess = model.AllowOfflineAccess - }; - } - - public static List ConvertFrom(List model) { - if (model == null || model.Any() == false) { - return new List(); - } - - List clientDetailsList = new List(); - - foreach (Client client in model) { - clientDetailsList.Add(ConvertFrom(client)); - } - - return clientDetailsList; - } - - public static ApiResourceDetails ConvertFrom(ApiResource model) { - if (model == null) { - return null; - } - - return new ApiResourceDetails { - Description = model.Description, - Scopes = model.Scopes.ToList(), - Name = model.Name, - DisplayName = model.DisplayName, - UserClaims = model.UserClaims.ToList(), - Enabled = model.Enabled - }; - } - - public static ApiScopeDetails ConvertFrom(ApiScope model) { - if (model == null) { - return null; - } - - return new ApiScopeDetails { Enabled = model.Enabled, DisplayName = model.DisplayName, Name = model.Name, Description = model.Description }; - } - - public static List ConvertFrom(List model) { - if (model == null || model.Any() == false) { - return new List(); - } - - List apiScopeDetailsList = new List(); - - foreach (ApiScope apiScope in model) { - apiScopeDetailsList.Add(ConvertFrom(apiScope)); - } - - return apiScopeDetailsList; - } - - public static IdentityResourceDetails ConvertFrom(IdentityResource model) { - if (model == null) { - return null; - } - - return new IdentityResourceDetails { - Claims = model.UserClaims.ToList(), - DisplayName = model.DisplayName, - Emphasize = model.Emphasize, - Required = model.Required, - ShowInDiscoveryDocument = model.ShowInDiscoveryDocument, - Description = model.Description, - Name = model.Name - }; - } - - public static List ConvertFrom(List model) { - if (model == null || model.Any() == false) { - return new List(); - } - - List apiResourceDetailsList = new List(); - - foreach (ApiResource apiResource in model) { - apiResourceDetailsList.Add(ConvertFrom(apiResource)); - } - - return apiResourceDetailsList; - } - - public static List ConvertFrom(List model) { - if (model == null || model.Any() == false) { - return new List(); - } - - List identityResourceDetailsList = new List(); - - foreach (IdentityResource identityResource in model) { - identityResourceDetailsList.Add(ConvertFrom(identityResource)); - } - - return identityResourceDetailsList; - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/Handlers/ApiResourceHandler.cs b/archive/SecurityService/Handlers/ApiResourceHandler.cs deleted file mode 100644 index e34117a5..00000000 --- a/archive/SecurityService/Handlers/ApiResourceHandler.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using SecurityService.BusinessLogic.Requests; -using Shared.Results; -using Shared.Results.Web; -using SimpleResults; - -namespace SecurityService.Handlers -{ - using DataTransferObjects.Requests; - using Factories; - using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Mvc; - using SecurityService.BusinessLogic; - - public static class ApiResourceHandler - { - public static async Task CreateApiResource(IMediator mediator, - CreateApiResourceRequest createApiResourceRequest, - CancellationToken cancellationToken) - { - SecurityServiceCommands.CreateApiResourceCommand command = new SecurityServiceCommands.CreateApiResourceCommand( - createApiResourceRequest.Name, - createApiResourceRequest.DisplayName, - createApiResourceRequest.Description, - createApiResourceRequest.Secret, - createApiResourceRequest.Scopes, - createApiResourceRequest.UserClaims); - - Result result = await mediator.Send(command, cancellationToken); - - return ResponseFactory.FromResult(result); - } - - public static async Task GetApiResource(IMediator mediator, - string apiResourceName, - CancellationToken cancellationToken) - { - SecurityServiceQueries.GetApiResourceQuery query = new SecurityServiceQueries.GetApiResourceQuery(apiResourceName); - - Result result = await mediator.Send(query, cancellationToken); - - return ResponseFactory.FromResult(result, ModelFactory.ConvertFrom); - } - - public static async Task GetApiResources(IMediator mediator, - CancellationToken cancellationToken) - { - SecurityServiceQueries.GetApiResourcesQuery query = new SecurityServiceQueries.GetApiResourcesQuery(); - - Result> result = await mediator.Send(query, cancellationToken); - - return ResponseFactory.FromResult(result, ModelFactory.ConvertFrom); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService/Handlers/ApiScopeHandler.cs b/archive/SecurityService/Handlers/ApiScopeHandler.cs deleted file mode 100644 index 99338e1c..00000000 --- a/archive/SecurityService/Handlers/ApiScopeHandler.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using SecurityService.BusinessLogic.Requests; -using Shared.Results; -using Shared.Results.Web; -using SimpleResults; - -namespace SecurityService.Handlers -{ - using DataTransferObjects.Requests; - using Factories; - using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Mvc; - using SecurityService.BusinessLogic; - - public static class ApiScopeHandler - { - public static async Task CreateApiScope(IMediator mediator, - CreateApiScopeRequest createApiScopeRequest, - CancellationToken cancellationToken) - { - SecurityServiceCommands.CreateApiScopeCommand command = new SecurityServiceCommands.CreateApiScopeCommand( - createApiScopeRequest.Name, - createApiScopeRequest.DisplayName, - createApiScopeRequest.Description); - - Result result = await mediator.Send(command, cancellationToken); - - return ResponseFactory.FromResult(result); - } - - public static async Task GetApiScope(IMediator mediator, - string apiScopeName, - CancellationToken cancellationToken) - { - SecurityServiceQueries.GetApiScopeQuery query = new SecurityServiceQueries.GetApiScopeQuery(apiScopeName); - - Result result = await mediator.Send(query, cancellationToken); - - return ResponseFactory.FromResult(result, ModelFactory.ConvertFrom); - } - - public static async Task GetApiScopes(IMediator mediator, - CancellationToken cancellationToken) - { - SecurityServiceQueries.GetApiScopesQuery query = new SecurityServiceQueries.GetApiScopesQuery(); - - Result> result = await mediator.Send(query, cancellationToken); - - return ResponseFactory.FromResult(result, ModelFactory.ConvertFrom); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService/Handlers/ClientHandler.cs b/archive/SecurityService/Handlers/ClientHandler.cs deleted file mode 100644 index ecb62dba..00000000 --- a/archive/SecurityService/Handlers/ClientHandler.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using SecurityService.BusinessLogic.Requests; -using Shared.Results.Web; -using SimpleResults; - -namespace SecurityService.Handlers -{ - using DataTransferObjects.Requests; - using Factories; - using Microsoft.AspNetCore.Http; - - public static class ClientHandler - { - public static async Task CreateClient(IMediator mediator, - CreateClientRequest createClientRequest, - CancellationToken cancellationToken) - { - SecurityServiceCommands.CreateClientCommand command = new SecurityServiceCommands.CreateClientCommand( - createClientRequest.ClientId, - createClientRequest.Secret, - createClientRequest.ClientName, - createClientRequest.ClientDescription, - createClientRequest.AllowedScopes, - createClientRequest.AllowedGrantTypes, - createClientRequest.ClientUri, - createClientRequest.ClientRedirectUris, - createClientRequest.ClientPostLogoutRedirectUris, - createClientRequest.RequireConsent, - createClientRequest.AllowOfflineAccess); - - Result result = await mediator.Send(command, cancellationToken); - - return ResponseFactory.FromResult(result); - } - - public static async Task GetClient(IMediator mediator, - string clientId, - CancellationToken cancellationToken) - { - SecurityServiceQueries.GetClientQuery query = new SecurityServiceQueries.GetClientQuery(clientId); - - Result result = await mediator.Send(query, cancellationToken); - - return ResponseFactory.FromResult(result, ModelFactory.ConvertFrom); - } - - public static async Task GetClients(IMediator mediator, - CancellationToken cancellationToken) - { - SecurityServiceQueries.GetClientsQuery query = new SecurityServiceQueries.GetClientsQuery(); - - Result> result = await mediator.Send(query, cancellationToken); - - return ResponseFactory.FromResult(result, ModelFactory.ConvertFrom); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService/Handlers/DeveloperHandler.cs b/archive/SecurityService/Handlers/DeveloperHandler.cs deleted file mode 100644 index 6e80a381..00000000 --- a/archive/SecurityService/Handlers/DeveloperHandler.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Microsoft.Extensions.Hosting; -using SecurityService.BusinessLogic; -using System.Threading; -using System.Threading.Tasks; -using MessagingService.Client; -using MessagingService.DataTransferObjects; -using Microsoft.AspNetCore.Http; - -namespace SecurityService.Handlers -{ - using Bootstrapper; - using Microsoft.AspNetCore.Mvc; - - public static class DeveloperHandler - { - public static Task GetLastEmailMessage(IMessagingServiceClient messagingServiceClient, - CancellationToken cancellationToken) - { - if (Startup.WebHostEnvironment.IsEnvironment("IntegrationTest") - && messagingServiceClient.GetType() == typeof(TestMessagingServiceClient)) - { - SendEmailRequest lastEmailRequest = ((TestMessagingServiceClient)messagingServiceClient).LastEmailRequest; - return Task.FromResult(Results.Ok(lastEmailRequest) as IResult); - } - - return Task.FromResult(Results.NotFound() as IResult); - } - - public static Task GetLastSMSMessage(IMessagingServiceClient messagingServiceClient, - CancellationToken cancellationToken) - { - if (Startup.WebHostEnvironment.IsEnvironment("IntegrationTest") && messagingServiceClient.GetType() == typeof(TestMessagingServiceClient)) { - SendSMSRequest lastSmsRequest = ((TestMessagingServiceClient)messagingServiceClient).LastSMSRequest; - return Task.FromResult(Results.Ok(lastSmsRequest) as IResult); - } - - return Task.FromResult(Results.NotFound() as IResult); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService/Handlers/IdentityResourceHandler.cs b/archive/SecurityService/Handlers/IdentityResourceHandler.cs deleted file mode 100644 index 62b82f42..00000000 --- a/archive/SecurityService/Handlers/IdentityResourceHandler.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.Collections.Generic; -using MediatR; -using SecurityService.BusinessLogic.Requests; -using Shared.Results; -using Shared.Results.Web; -using SimpleResults; -using System.Threading; -using System.Threading.Tasks; - -namespace SecurityService.Handlers -{ - using DataTransferObjects.Requests; - using Factories; - using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Mvc; - using SecurityService.BusinessLogic; - - public static class IdentityResourceHandler - { - public static async Task CreateIdentityResource(IMediator mediator, - CreateIdentityResourceRequest createIdentityResourceRequest, - CancellationToken cancellationToken) - { - SecurityServiceCommands.CreateIdentityResourceCommand command = new( - createIdentityResourceRequest.Name, - createIdentityResourceRequest.DisplayName, - createIdentityResourceRequest.Description, - createIdentityResourceRequest.Required, - createIdentityResourceRequest.Emphasize, - createIdentityResourceRequest.ShowInDiscoveryDocument, - createIdentityResourceRequest.Claims); - - Result result = await mediator.Send(command, cancellationToken); - - return ResponseFactory.FromResult(result); - } - - public static async Task GetIdentityResource(IMediator mediator, - string apiResourceName, - CancellationToken cancellationToken) - { - SecurityServiceQueries.GetIdentityResourceQuery query = new(apiResourceName); - - Result result = await mediator.Send(query, cancellationToken); - - return ResponseFactory.FromResult(result, ModelFactory.ConvertFrom); - } - - public static async Task GetIdentityResources(IMediator mediator, - CancellationToken cancellationToken) - { - SecurityServiceQueries.GetIdentityResourcesQuery query = new(); - - Result> result = await mediator.Send(query, cancellationToken); - - return ResponseFactory.FromResult(result, ModelFactory.ConvertFrom); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService/Handlers/RoleHandler.cs b/archive/SecurityService/Handlers/RoleHandler.cs deleted file mode 100644 index be76f83c..00000000 --- a/archive/SecurityService/Handlers/RoleHandler.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using SecurityService.BusinessLogic.Requests; -using Shared.Results; -using Shared.Results.Web; -using SimpleResults; - -namespace SecurityService.Handlers -{ - using DataTransferObjects.Requests; - using Factories; - using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Mvc; - using SecurityService.BusinessLogic; - - public static class RoleHandler - { - public static async Task CreateRole(IMediator mediator, - CreateRoleRequest createRoleRequest, - CancellationToken cancellationToken) - { - Guid roleId = Guid.NewGuid(); - - SecurityServiceCommands.CreateRoleCommand command = new(roleId, createRoleRequest.RoleName); - - Result result = await mediator.Send(command, cancellationToken); - - return ResponseFactory.FromResult(result); - } - - public static async Task GetRole(IMediator mediator, - Guid roleId, - CancellationToken cancellationToken) - { - SecurityServiceQueries.GetRoleQuery query = new(roleId); - - Result result = await mediator.Send(query, cancellationToken); - - return ResponseFactory.FromResult(result, ModelFactory.ConvertFrom); - } - - public static async Task GetRoles(IMediator mediator, - CancellationToken cancellationToken) - { - SecurityServiceQueries.GetRolesQuery query = new(); - - Result> result = await mediator.Send(query, cancellationToken); - - return ResponseFactory.FromResult(result, ModelFactory.ConvertFrom); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService/Handlers/UserHandler.cs b/archive/SecurityService/Handlers/UserHandler.cs deleted file mode 100644 index 66669233..00000000 --- a/archive/SecurityService/Handlers/UserHandler.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using SecurityService.BusinessLogic.Requests; -using Shared.Results; -using Shared.Results.Web; -using SimpleResults; - -namespace SecurityService.Handlers -{ - using DataTransferObjects; - using Factories; - using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Mvc; - using SecurityService.BusinessLogic; - - public static class UserHandler - { - public static async Task CreateUser(IMediator mediator, - CreateUserRequest createUserRequest, - CancellationToken cancellationToken) - { - Guid userId = Guid.NewGuid(); - - SecurityServiceCommands.CreateUserCommand command = new( - userId, - createUserRequest.GivenName, - createUserRequest.MiddleName, - createUserRequest.FamilyName, - createUserRequest.EmailAddress, - createUserRequest.Password, - createUserRequest.EmailAddress, - createUserRequest.PhoneNumber, - createUserRequest.Claims, - createUserRequest.Roles); - - Result result = await mediator.Send(command, cancellationToken); - - return ResponseFactory.FromResult(result); - } - - public static async Task GetUser(IMediator mediator, - Guid userId, - CancellationToken cancellationToken) - { - SecurityServiceQueries.GetUserQuery query = new(userId); - - Result result = await mediator.Send(query, cancellationToken); - - return ResponseFactory.FromResult(result, ModelFactory.ConvertFrom); - } - - public static async Task GetUsers(IMediator mediator, - string? userName, - CancellationToken cancellationToken) - { - SecurityServiceQueries.GetUsersQuery query = new(userName); - - Result> result = await mediator.Send(query, cancellationToken); - - return ResponseFactory.FromResult(result, ModelFactory.ConvertFrom); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService/HostedServices/DatabaseInitializer.cs b/archive/SecurityService/HostedServices/DatabaseInitializer.cs deleted file mode 100644 index 112259df..00000000 --- a/archive/SecurityService/HostedServices/DatabaseInitializer.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System; -using Duende.IdentityServer.EntityFramework.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.Hosting; -using SecurityService.Database.DbContexts; -using Microsoft.Extensions.Logging; -using Shared.Logger; - -public class DatabaseInitializer : IHostedService, IDisposable -{ - private readonly IServiceProvider Services; - private readonly IHostApplicationLifetime Lifetime; - private readonly CancellationTokenSource InternalCts = new(); - private Task? StartupTask; - - public DatabaseInitializer(IServiceProvider services, IHostApplicationLifetime lifetime) { - Services = services; - this.Lifetime = lifetime; - } - - public Task StartAsync(CancellationToken cancellationToken) - { - // start migrations/seeding on the threadpool so StartAsync returns quickly if you want. - StartupTask = Task.Run(() => RunMigrationsAsync(InternalCts.Token), CancellationToken.None); - return Task.CompletedTask; - } - - private async Task RunMigrationsAsync(CancellationToken token) - { - try { - - Logger.LogWarning("About to start DatabaseMigrations"); - - using IServiceScope scope = Services.CreateScope(); - PersistedGrantDbContext persistedGrant = scope.ServiceProvider.GetRequiredService(); - ConfigurationDbContext config = scope.ServiceProvider.GetRequiredService(); - AuthenticationDbContext auth = scope.ServiceProvider.GetRequiredService(); - - if (persistedGrant.Database.IsRelational()) { - await persistedGrant.Database.MigrateAsync(token); - await persistedGrant.SetDbInSimpleMode(token); - } - - if (config.Database.IsRelational()){ - await config.Database.MigrateAsync(token); - await config.SetDbInSimpleMode(token); - } - - if (auth.Database.IsRelational()) { - await auth.Database.MigrateAsync(token); - await auth.SetDbInSimpleMode(token); - } - - Logger.LogWarning("Database Migrations Successful"); - } - catch (OperationCanceledException) when (token.IsCancellationRequested) - { - Logger.LogInformation("DatabaseInitializer migration canceled."); - } - catch (Exception ex) - { - Logger.LogError("DatabaseInitializer migration failed.", ex); - // Request host shutdown: - try - { - Environment.ExitCode = 1; - Lifetime.StopApplication(); - } - catch - { - // ignore any exception from StopApplication, we are already failing - } - - // Rethrow to ensure host doesn't continue starting successfully. - throw; - } - } - - public async Task StopAsync(CancellationToken cancellationToken) - { - // per-service shutdown window - TimeSpan perServiceTimeout = TimeSpan.FromSeconds(20); - - // request cancel of internal work - await this.InternalCts.CancelAsync(); - - if (StartupTask == null) - return; - - using var linked = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); - Task timeout = Task.Delay(perServiceTimeout, linked.Token); - Task completed = await Task.WhenAny(StartupTask, timeout); - - if (completed == timeout) - { - Logger.LogWarning($"DatabaseInitializer did not finish within {perServiceTimeout.TotalSeconds}s; continuing shutdown."); - // host will continue shutdown; hosted service StopAsync returned after per-service timeout. - } - else - { - await linked.CancelAsync(); // cancel the delay - await StartupTask; // propagate exceptions if any - } - } - - public void Dispose() => InternalCts.Dispose(); -} \ No newline at end of file diff --git a/archive/SecurityService/NuGet.Config b/archive/SecurityService/NuGet.Config deleted file mode 100644 index 3086e202..00000000 --- a/archive/SecurityService/NuGet.Config +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/archive/SecurityService/Program.cs b/archive/SecurityService/Program.cs deleted file mode 100644 index fd2de618..00000000 --- a/archive/SecurityService/Program.cs +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - - -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Hosting; -using NLog.Extensions.Logging; -using Serilog; -using Serilog.Events; -using Serilog.Sinks.SystemConsole.Themes; -using Shared.Logger; -using Shared.Middleware; -using System; -using Sentry.Extensibility; - -namespace SecurityService -{ - using Lamar.Microsoft.DependencyInjection; - using Microsoft.AspNetCore.Server.Kestrel.Core; - using Microsoft.AspNetCore.Server.Kestrel.Https; - using Microsoft.Extensions.Configuration; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.Logging; - using Newtonsoft.Json; - using Newtonsoft.Json.Serialization; - using NLog; - using Shared.General; - using System.Diagnostics.CodeAnalysis; - using System.IO; - using System.Linq; - using System.Net; - using System.Reflection; - using System.Security.Authentication; - using System.Security.Cryptography.X509Certificates; - - [ExcludeFromCodeCoverage] - public class Program - { - public static IHostBuilder CreateHostBuilder(String[] args) - { - //At this stage, we only need our hosting file for ip and ports - String contentRoot = Directory.GetCurrentDirectory(); - String nlogConfigPath = Path.Combine(contentRoot, "nlog.config"); - - LogManager.Setup(b => - { - b.SetupLogFactory(setup => - { - setup.AddCallSiteHiddenAssembly(typeof(NlogLogger).Assembly); - setup.AddCallSiteHiddenAssembly(typeof(Shared.Logger.Logger).Assembly); - setup.AddCallSiteHiddenAssembly(typeof(TenantMiddleware).Assembly); - }); - b.LoadConfigurationFromFile(nlogConfigPath); - }); - - IHostBuilder hostBuilder = Host.CreateDefaultBuilder(args); - hostBuilder.UseWindowsService(); - hostBuilder.UseLamar(); - hostBuilder.ConfigureLogging(logging => { - logging.AddConsole(); - logging.AddNLog(); - }); - - ConfigureWeb(hostBuilder); - - return hostBuilder; - } - - private static void ConfigureWeb(IHostBuilder hostBuilder) { - FileInfo fi = new FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location); - IConfigurationRoot config = new ConfigurationBuilder().SetBasePath(fi.Directory.FullName).AddJsonFile("hosting.json", optional: false) - .AddJsonFile("hosting.development.json", optional: true).AddEnvironmentVariables().Build(); - - hostBuilder.ConfigureWebHostDefaults(webBuilder => - { - webBuilder.ConfigureAppConfiguration((context, configBuilder) => - { - var env = context.HostingEnvironment; - - configBuilder.SetBasePath(fi.Directory.FullName) - .AddJsonFile("hosting.json", optional: true) - .AddJsonFile($"hosting.{env.EnvironmentName}.json", optional: true) - .AddJsonFile("/home/txnproc/config/appsettings.json", optional: true, reloadOnChange: true) - .AddJsonFile($"/home/txnproc/config/appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true) - .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) - .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true) - .AddEnvironmentVariables(); - - // Build a snapshot of configuration so we can use it immediately (e.g. for Sentry) - var builtConfig = configBuilder.Build(); - - // Keep existing static usage (if you must), and initialise the ConfigurationReader now. - Startup.Configuration = builtConfig; - ConfigurationReader.Initialise(Startup.Configuration); - - // Configure Sentry on the webBuilder using the config snapshot. - var sentrySection = builtConfig.GetSection("SentryConfiguration"); - if (sentrySection.Exists()) - { - // Replace the condition below if you intended to only enable Sentry in certain environments. - if (env.IsDevelopment() == false) - { - webBuilder.UseSentry(o => - { - o.Dsn = builtConfig["SentryConfiguration:Dsn"]; - o.SendDefaultPii = true; - o.MaxRequestBodySize = RequestSize.Always; - o.CaptureBlockingCalls = true; - o.Release = Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown"; - }); - } - } - }); - - webBuilder.UseStartup(); - webBuilder.ConfigureServices(services => - { - services.AddRazorPages(); - - // This is important, the call to AddControllers() - // cannot be made before the usage of ConfigureWebHostDefaults - services.AddControllers() - .AddNewtonsoftJson(options => - { - options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; - options.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto; - options.SerializerSettings.Formatting = Formatting.Indented; - options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; - options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); - }); ; - }); - webBuilder.UseConfiguration(config); - webBuilder.UseKestrel(options => - { - var urls = config.GetSection("urls").Value.Split(":"); - var port = Int32.Parse(urls[2]); - - options.Listen(IPAddress.Any, - port, - listenOptions => - { - // Enable support for HTTP1 and HTTP2 (required if you want to host gRPC endpoints) - listenOptions.Protocols = HttpProtocols.Http1AndHttp2; - // Configure Kestrel to use a certificate from a local .PFX file for hosting HTTPS - listenOptions.UseHttps(Program.LoadCertificate(fi.Directory.FullName)); - }); - }); - - }); - } - - private static X509Certificate2 LoadCertificate(String path) - { - //just to ensure that we are picking the right file! little bit of ugly code: - var files = Directory.GetFiles(path); - var certificateFile = files.First(name => name.Contains("pfx")); - - var cert = new X509Certificate2(certificateFile, "password"); - return cert; - } - - public static void Main(String[] args) - { - Log.Logger = new LoggerConfiguration() - .MinimumLevel.Verbose() - .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) - .MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information) - .MinimumLevel.Override("System", LogEventLevel.Warning) - .MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information) - .Enrich.FromLogContext() - // uncomment to write to Azure diagnostics stream - //.WriteTo.File( - // @"D:\home\LogFiles\Application\identityserver.txt", - // fileSizeLimitBytes: 1_000_000, - // rollOnFileSizeLimit: true, - // shared: true, - // flushToDiskInterval: TimeSpan.FromSeconds(1)) - .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Code) - .CreateLogger(); - - Program.CreateHostBuilder(args).Build().Run(); - } - } -} \ No newline at end of file diff --git a/archive/SecurityService/SecurityHeadersAttribute.cs b/archive/SecurityService/SecurityHeadersAttribute.cs deleted file mode 100644 index 02e4fb2c..00000000 --- a/archive/SecurityService/SecurityHeadersAttribute.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - - -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using System.Diagnostics.CodeAnalysis; - -namespace IdentityServerHost.Quickstart.UI -{ - [ExcludeFromCodeCoverage] - public class SecurityHeadersAttribute : ActionFilterAttribute - { - public override void OnResultExecuting(ResultExecutingContext context) - { - var result = context.Result; - if (result is ViewResult) - { - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options - if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Type-Options")) - { - context.HttpContext.Response.Headers.Add("X-Content-Type-Options", "nosniff"); - } - - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options - if (!context.HttpContext.Response.Headers.ContainsKey("X-Frame-Options")) - { - context.HttpContext.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN"); - } - - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy - var csp = "default-src 'self'; object-src 'none'; frame-ancestors 'none'; sandbox allow-forms allow-same-origin allow-scripts; base-uri 'self';"; - // also consider adding upgrade-insecure-requests once you have HTTPS in place for production - //csp += "upgrade-insecure-requests;"; - // also an example if you need client images to be displayed from twitter - // csp += "img-src 'self' https://pbs.twimg.com;"; - - // once for standards compliant browsers - if (!context.HttpContext.Response.Headers.ContainsKey("Content-Security-Policy")) - { - context.HttpContext.Response.Headers.Add("Content-Security-Policy", csp); - } - // and once again for IE - if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Security-Policy")) - { - context.HttpContext.Response.Headers.Add("X-Content-Security-Policy", csp); - } - - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy - var referrer_policy = "no-referrer"; - if (!context.HttpContext.Response.Headers.ContainsKey("Referrer-Policy")) - { - context.HttpContext.Response.Headers.Add("Referrer-Policy", referrer_policy); - } - } - } - } -} diff --git a/archive/SecurityService/SecurityService.csproj b/archive/SecurityService/SecurityService.csproj deleted file mode 100644 index e4099c36..00000000 --- a/archive/SecurityService/SecurityService.csproj +++ /dev/null @@ -1,90 +0,0 @@ - - - - net10.0 - 5e9b93dd-258d-47d7-a6d3-42e86a745857 - Linux - - - - - - - - - - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - - - - - - - - - - - - - - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - - - - - diff --git a/archive/SecurityService/Startup.cs b/archive/SecurityService/Startup.cs deleted file mode 100644 index 08c8c617..00000000 --- a/archive/SecurityService/Startup.cs +++ /dev/null @@ -1,154 +0,0 @@ -using Microsoft.AspNetCore.Routing; -using SecurityService.Endpoints; - -namespace SecurityService -{ - using Bootstrapper; - using HealthChecks.UI.Client; - using Lamar; - using Microsoft.AspNetCore.Builder; - using Microsoft.AspNetCore.Diagnostics.HealthChecks; - using Microsoft.AspNetCore.Hosting; - using Microsoft.AspNetCore.HttpOverrides; - using Microsoft.Extensions.Configuration; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.Hosting; - using Microsoft.Extensions.Logging; - using Shared.Extensions; - using Shared.General; - using Shared.Logger; - using Shared.Middleware; - using System.Diagnostics.CodeAnalysis; - using ILogger = Microsoft.Extensions.Logging.ILogger; - - [ExcludeFromCodeCoverage] - public class Startup - { - #region Fields - - private static Container Container; - - public static Container GetContainer() => Container; - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The web host environment. - public Startup(IWebHostEnvironment webHostEnvironment) - { - Startup.WebHostEnvironment = webHostEnvironment; - } - - #endregion - - #region Properties - - /// - /// Gets or sets the configuration. - /// - /// - /// The configuration. - /// - public static IConfigurationRoot Configuration { get; set; } - - /// - /// Gets or sets the hosting environment. - /// - /// - /// The hosting environment. - /// - public static IWebHostEnvironment WebHostEnvironment { get; set; } - - #endregion - - #region Methods - - /// - /// Configures the specified application. - /// - /// The application. - /// The env. - /// The logger factory. - public void Configure(IApplicationBuilder app, - IWebHostEnvironment env, - ILoggerFactory loggerFactory) - { - if (env.IsDevelopment()) { - app.UseDeveloperExceptionPage(); - } - - ILogger logger = loggerFactory.CreateLogger("Security Service"); - - Logger.Initialise(logger); - Startup.Configuration.LogConfiguration(Logger.LogWarning); - app.UseMiddleware(); - app.AddRequestResponseLogging(); - app.AddExceptionHandler(); - - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseRouting(); - - app.UseIdentityServer(); - - app.UseAuthorization(); - app.UseHttpsRedirection(); - app.UseStaticFiles(); - - app.UseForwardedHeaders(new ForwardedHeadersOptions - { - ForwardedHeaders = ForwardedHeaders.XForwardedProto - }); - - app.UseEndpoints(this.MapEndpoints); - - app.UseSwagger(); - - app.UseSwaggerUI(); - } - - private void MapEndpoints(IEndpointRouteBuilder endpoints) { - endpoints.MapRazorPages(); - endpoints.MapDefaultControllerRoute(); - - endpoints.MapApiResourceEndpoints(); - endpoints.MapApiScopeEndpoints(); - endpoints.MapIdentityResourceEndpoints(); - endpoints.MapUserEndpoints(); - endpoints.MapRoleEndpoints(); - endpoints.MapClientEndpoints(); - endpoints.MapDeveloperEndpoints(); - - endpoints.MapHealthChecks("health", new HealthCheckOptions { Predicate = _ => true, ResponseWriter = Shared.HealthChecks.HealthCheckMiddleware.WriteResponse }); - endpoints.MapHealthChecks("healthui", new HealthCheckOptions { Predicate = _ => true, ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse }); - } - - /// - /// Configures the container. - /// - /// The services. - public void ConfigureContainer(ServiceRegistry services) - { - ConfigurationReader.Initialise(Startup.Configuration); - - services.IncludeRegistry(); - services.IncludeRegistry(); - services.IncludeRegistry(); - services.IncludeRegistry(); - - // Register the hosted service via the ServiceRegistry (Lamar) - services.AddHostedService(); - - Startup.Container = new Container(services); - } - - #endregion - } -} \ No newline at end of file diff --git a/archive/SecurityService/UpdateUI.ps1 b/archive/SecurityService/UpdateUI.ps1 deleted file mode 100644 index e7323d04..00000000 --- a/archive/SecurityService/UpdateUI.ps1 +++ /dev/null @@ -1,40 +0,0 @@ -$source = "https://github.com/DuendeSoftware/IdentityServer.Quickstart.UI.AspNetIdentity/archive/main.zip" -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -Invoke-WebRequest $source -OutFile ui.zip - -Expand-Archive ui.zip - -if (!(Test-Path -Path QuickStart)) { mkdir QuickStart } -if (!(Test-Path -Path Views)) { mkdir Views } -if (!(Test-Path -Path wwwroot)) { mkdir wwwroot } - -copy .\ui\IdentityServer.Quickstart.UI.AspNetIdentity-main\Quickstart\* QuickStart -recurse -force -copy .\ui\IdentityServer.Quickstart.UI.AspNetIdentity-main\Views\* Views -recurse -force -copy .\ui\IdentityServer.Quickstart.UI.AspNetIdentity-main\wwwroot\* wwwroot -recurse -force - -# Now split the Quickstart into Controllers and View models -if (!(Test-Path -Path Controllers)) { mkdir Controllers } -if (!(Test-Path -Path ViewModels)) { mkdir ViewModels } - -$controllerDir = Join-Path $PSScriptRoot "\Controllers" -$viewModelDir = Join-Path $PSScriptRoot "\ViewModels\" - -foreach ($d in $dir){ - $controllerFilter = @('*Controller*.cs') - if (!(Test-Path -Path $controllerDir\$d)) { mkdir Controllers\$d } - if (!(Test-Path -Path $viewModelDir\$d)) { mkdir ViewModels\$d } - - Get-ChildItem -Path QuickStart\$d -Include *Controller*.cs -Recurse | ForEach-Object { - Copy-Item -Path $_.FullName -Destination $controllerDir\$d - } - - if (!(Test-Path -Path $controllerDir\$d)) { mkdir ViewModels\$d } - Get-ChildItem -Path QuickStart\$d -Exclude *Controller*.cs -Recurse | ForEach-Object { - Copy-Item -Path $_.FullName -Destination $viewModelDir\$d - } -} -copy .\ui\IdentityServer.Quickstart.UI.AspNetIdentity-main\Quickstart\*.cs -force - -del ui.zip -del ui -recurse -del QuickStart -recurse \ No newline at end of file diff --git a/archive/SecurityService/appsettings.json b/archive/SecurityService/appsettings.json deleted file mode 100644 index 58560b0f..00000000 --- a/archive/SecurityService/appsettings.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "ServiceOptions": { - "PublicOrigin": "https://127.0.0.1:5001", - "IssuerUrl": "https://127.0.0.1:5001", - "ClientId": "serviceClient", - "ClientSecret": "d192cbc46d834d0da90e8a9d50ded543", - "PasswordOptions": { - "RequiredLength": 6, - "RequireDigit": true, - "RequireUpperCase": true - }, - "UserOptions": { - "RequireUniqueEmail": true - }, - "SignInOptions": { - "RequireConfirmedEmail": true - }, - "TokenOptions": { - "EmailConfirmationTokenExpiryInHours": 48, - "PasswordResetTokenExpiryInHours": 2 - } - }, - "ConnectionStrings": { - "PersistedGrantDbContext": "server=127.0.0.1;database=PersistedGrantStore;user id=sa;password=Sc0tland;Encrypt=false", - "ConfigurationDbContext": "server=127.0.0.1;database=Configuration;user id=sa;password=Sc0tland;Encrypt=false", - "AuthenticationDbContext": "server=127.0.0.1;database=Authentication;user id=sa;password=Sc0tland;Encrypt=false" - }, - "AppSettings": { - } -} diff --git a/archive/SecurityService/appsettings.staging.json b/archive/SecurityService/appsettings.staging.json deleted file mode 100644 index 7cd8d238..00000000 --- a/archive/SecurityService/appsettings.staging.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ConnectionStrings": { - "PersistedGrantDbContext": "server=127.0.0.1;database=PersistedGrantStore;user id=sa;password=Sc0tland;Encrypt=false", - "ConfigurationDbContext": "server=127.0.0.1;database=Configuration;user id=sa;password=Sc0tland;Encrypt=false", - "AuthenticationDbContext": "server=127.0.0.1;database=Authentication;user id=sa;password=Sc0tland;Encrypt=false" - } -} diff --git a/archive/SecurityService/aspnetapp-root-cert.cer b/archive/SecurityService/aspnetapp-root-cert.cer deleted file mode 100644 index a0e05300..00000000 Binary files a/archive/SecurityService/aspnetapp-root-cert.cer and /dev/null differ diff --git a/archive/SecurityService/aspnetapp-web-api.pfx b/archive/SecurityService/aspnetapp-web-api.pfx deleted file mode 100644 index 35f55788..00000000 Binary files a/archive/SecurityService/aspnetapp-web-api.pfx and /dev/null differ diff --git a/archive/SecurityService/hosting.json b/archive/SecurityService/hosting.json deleted file mode 100644 index 30120150..00000000 --- a/archive/SecurityService/hosting.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "urls": "https://*:5001" -} diff --git a/archive/SecurityService/keys/is-signing-key-7B5CA49B919774AC72B8177C782E2F1F.json b/archive/SecurityService/keys/is-signing-key-7B5CA49B919774AC72B8177C782E2F1F.json deleted file mode 100644 index fd1672b5..00000000 --- a/archive/SecurityService/keys/is-signing-key-7B5CA49B919774AC72B8177C782E2F1F.json +++ /dev/null @@ -1 +0,0 @@ -{"Version":1,"Id":"7B5CA49B919774AC72B8177C782E2F1F","Created":"2021-06-07T10:28:54.6099029Z","Algorithm":"RS256","IsX509Certificate":false,"Data":"CfDJ8H5gBCU3HeBLkiGMiivJ_jvOk5_wygvDGTXsBhrj8_V1hCHO6ON3v25-zj2ZIZTqxGnUEqINszYhizmCK9jOWQyqkww_K6x9H_LfAmGiWsaSp5kcwlDZKNEFNH2_rrzUF7EEr0OxWXqAlZW-zHLQZChY6smHjrKIlwL6MAE5eQKKogOUly2yvpzdx1iGk7vle4Q21HnQBY1lLnsxDtV-NmkLzNPfW-O7Am0cO1fSDkUKnJJG91Na9aNNIehnWlRHfaYMTvoS36h1Xqv3iFCcu-MfOATXUga_OAgbwshObgmCfm_3Y0GqO-_NxWUcU4WvuxKlpThqBkkOT9I-fBVmG1_XF_YuF5ZmIcrT16vSk36pH_4FRXQqlPppmApcwu0cjbz0JppGhMtc34UCRUeoIWSkVGs3H9A8_U3hlthHVI4bEGSLuYLN7uP_niwrY6-8XXGW6KuZYBiRWc5f5RLXa_6Xb6QmWl07LJoNFaK4gUda2rXvALPB4UQHO3POFodl4h1ZLAD0kfIMJHooYh1nDlT05bXP2IJeEj-RpDGxQcyu1fFnvC0myuPpppX_lOLeIHWwaeY3-P7878RC1afkv4huhP1abN1VeaeXH-pEeCmAcKnbTKV4gj9K4MFmX0-vHWxYf6ZnT-yVn21Y6VLpNhoNUj3dcFWAD0zyPrIoVib-_uVUBmlLWFp0SeoD7OzSgIYcOv4ss-8zCBP71qzlD9pR6XcHAe4BAPFADlqo5WZqGbvY3xw1JC7R5jXVwaUoSHTRf4qAcqvzyz7Y_zCotFytEwrW9XV5ofUJTFRPUbsYQVhK0Ft1X9FYcurHCQRJlTN6DeKFCbWS3uw-m6cZOM0AYALVvNWxDeyPDfitq168vJ5Z2IKs9btgFhdovXoAHve0SHxKMCRXBbQPnAMyjbxMfXQuwnDigJg1b9k85gCW5XcElJdmkOESMIMCgtbz45wO6CX5uFEQ3xIMzdrtsCKqRr4Kl5g0ZodvgSkggP1tmdsuUCDtz7-1IhYBsTq5KWK_r5Zt1MdqyvKlUbWmLrRvCeov80r-XmlQWoVmX8DFY3UKh2SRJTc4FmBurVOPAZfGpS36ZQSS83OMK-1v0GxUO0_ErRfL3V12vsI68MlYddfGYdHBJm2a4t89O9EPDDjC6skwoiQREwEp-Jx5qwPYqVEDuth-BIZCSpocNRvMKIEkBnSEUcPDTLA7k9C1kefbyvlPCOrG6XdXE6qxUfbRMGgb3XXBlJ7ogEqkDgZJwswUP98pbjlv_2pJOzWjhmrYEGDIRrgrpTHDmNSFJyQDr4gtmgdmj7phFVywTbUgdqYIQSmqwxtIjifDS9myAFJDun00uOyDZw03Knu5OKMPUw5LUcqJGWNK3ZEwNKrCTswZVozZ1Eax0F48KNfSpR8B9Tih4mtuRiVK6tc042zo6bWuQmbUYfy_sM7fzMgqtP0mX4IeWzbPFKNDusR6_FJhPafiw5ukZ1R3SvIlt27iiSf4J3UCjkDs0w7AJqP9wUBVaHoASdJ0K0Z9kndK8_ZDyZRB70k42buz140jk0mZvP57zPT-0W73i78_7Qdecu2uhuFW9I6ehhr26R90l6CNsNePYj1Etpv3gokdkQD2StyFwTCUkyWevlk6DX4ZXCb_Xc4HSeEtnfU3QjzZbQRPwctuhB1hy4e_Ge7xGtlcbhQPugo6F1YWRHB-gaUF9oqNPMVivs7s1qGlPVQ7bqGH2lYaXEPGIhOzjUILi3VwPE1xGR_z4ZWyT39DkO65h_eky4PKAf4LY8nIQ3WYDv5CvpOSwvDH1Cd047aGKhemWlML0FJydOJtHyXDBf6TSm9n0DoQdrVvinhF8s83i43CyGRtWOyMpv0P7Lyf-ZmHE6NB5qWyOq2zRCfbckmVFTR7Cf1HSeZZdsfsEurPMDvoYOQu__WTHDdK30zPJNIn0JXqLSV_2RIyUMpOUJ6F5toXJ5OKFUzxeGotRQYlwOOltxKxdAyDyApRNleUT6ad0pBaPcj9wVFjRSxeHsmJDolXoFRRzrEXmt5P5zKxWD2AeInGbRX1HQBUnK9nTUV9m1hdMhQMAKsPFB7NmPXJAVcOLzFYNbWv7p-67HASyEKXPG1pxIZ3MeJcqkEb_bEk_69-Fq-03JHbLKloiqt7jDJc_XeCeonrtTU--vs33cGIquO0EUmacLOOS_RXOBJiqYt_18eKNv7-fvVU_Saso24osBXe6Z0zyK2TT7j-zDgfh22hlJd8UkTDR0znLUtj5qlff4uNHzOi5VYjFotzO576hsgwPjrX7RdlnFeFWTdvX_-Pwkb3Nbrhq8LdoDJ3ZybV1ZNNIWr4pqq0XI-Tjl8HRBKg929v1JNSlON3U7o81pLtq4ufPbTupiYdSAMs1441iBV6ptNRSOrBRkYdb6c8Pti83NO4Z15g1w95dW4Pu1eb8GvGpF9erjiVrw9UAUu-4gb3Zyhnz6R-rfWQ","DataProtected":true} \ No newline at end of file diff --git a/archive/SecurityService/nlog.config b/archive/SecurityService/nlog.config deleted file mode 100644 index 1e7940b8..00000000 --- a/archive/SecurityService/nlog.config +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/archive/SecurityService/wwwroot/css/app.css b/archive/SecurityService/wwwroot/css/app.css deleted file mode 100644 index 7f490de8..00000000 --- a/archive/SecurityService/wwwroot/css/app.css +++ /dev/null @@ -1,2706 +0,0 @@ -*, ::before, ::after { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-gradient-from-position: ; - --tw-gradient-via-position: ; - --tw-gradient-to-position: ; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - --tw-contain-size: ; - --tw-contain-layout: ; - --tw-contain-paint: ; - --tw-contain-style: ; -} - -::backdrop { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-gradient-from-position: ; - --tw-gradient-via-position: ; - --tw-gradient-to-position: ; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - --tw-contain-size: ; - --tw-contain-layout: ; - --tw-contain-paint: ; - --tw-contain-style: ; -} - -/* -! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com -*/ - -/* -1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) -2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) -*/ - -*, -::before, -::after { - box-sizing: border-box; - /* 1 */ - border-width: 0; - /* 2 */ - border-style: solid; - /* 2 */ - border-color: #e5e7eb; - /* 2 */ -} - -::before, -::after { - --tw-content: ''; -} - -/* -1. Use a consistent sensible line-height in all browsers. -2. Prevent adjustments of font size after orientation changes in iOS. -3. Use a more readable tab size. -4. Use the user's configured `sans` font-family by default. -5. Use the user's configured `sans` font-feature-settings by default. -6. Use the user's configured `sans` font-variation-settings by default. -7. Disable tap highlights on iOS -*/ - -html, -:host { - line-height: 1.5; - /* 1 */ - -webkit-text-size-adjust: 100%; - /* 2 */ - -moz-tab-size: 4; - /* 3 */ - -o-tab-size: 4; - tab-size: 4; - /* 3 */ - font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - /* 4 */ - font-feature-settings: normal; - /* 5 */ - font-variation-settings: normal; - /* 6 */ - -webkit-tap-highlight-color: transparent; - /* 7 */ -} - -/* -1. Remove the margin in all browsers. -2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. -*/ - -body { - margin: 0; - /* 1 */ - line-height: inherit; - /* 2 */ -} - -/* -1. Add the correct height in Firefox. -2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) -3. Ensure horizontal rules are visible by default. -*/ - -hr { - height: 0; - /* 1 */ - color: inherit; - /* 2 */ - border-top-width: 1px; - /* 3 */ -} - -/* -Add the correct text decoration in Chrome, Edge, and Safari. -*/ - -abbr:where([title]) { - -webkit-text-decoration: underline dotted; - text-decoration: underline dotted; -} - -/* -Remove the default font size and weight for headings. -*/ - -h1, -h2, -h3, -h4, -h5, -h6 { - font-size: inherit; - font-weight: inherit; -} - -/* -Reset links to optimize for opt-in styling instead of opt-out. -*/ - -a { - color: inherit; - text-decoration: inherit; -} - -/* -Add the correct font weight in Edge and Safari. -*/ - -b, -strong { - font-weight: bolder; -} - -/* -1. Use the user's configured `mono` font-family by default. -2. Use the user's configured `mono` font-feature-settings by default. -3. Use the user's configured `mono` font-variation-settings by default. -4. Correct the odd `em` font sizing in all browsers. -*/ - -code, -kbd, -samp, -pre { - font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; - /* 1 */ - font-feature-settings: normal; - /* 2 */ - font-variation-settings: normal; - /* 3 */ - font-size: 1em; - /* 4 */ -} - -/* -Add the correct font size in all browsers. -*/ - -small { - font-size: 80%; -} - -/* -Prevent `sub` and `sup` elements from affecting the line height in all browsers. -*/ - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sub { - bottom: -0.25em; -} - -sup { - top: -0.5em; -} - -/* -1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) -2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) -3. Remove gaps between table borders by default. -*/ - -table { - text-indent: 0; - /* 1 */ - border-color: inherit; - /* 2 */ - border-collapse: collapse; - /* 3 */ -} - -/* -1. Change the font styles in all browsers. -2. Remove the margin in Firefox and Safari. -3. Remove default padding in all browsers. -*/ - -button, -input, -optgroup, -select, -textarea { - font-family: inherit; - /* 1 */ - font-feature-settings: inherit; - /* 1 */ - font-variation-settings: inherit; - /* 1 */ - font-size: 100%; - /* 1 */ - font-weight: inherit; - /* 1 */ - line-height: inherit; - /* 1 */ - letter-spacing: inherit; - /* 1 */ - color: inherit; - /* 1 */ - margin: 0; - /* 2 */ - padding: 0; - /* 3 */ -} - -/* -Remove the inheritance of text transform in Edge and Firefox. -*/ - -button, -select { - text-transform: none; -} - -/* -1. Correct the inability to style clickable types in iOS and Safari. -2. Remove default button styles. -*/ - -button, -input:where([type='button']), -input:where([type='reset']), -input:where([type='submit']) { - -webkit-appearance: button; - /* 1 */ - background-color: transparent; - /* 2 */ - background-image: none; - /* 2 */ -} - -/* -Use the modern Firefox focus style for all focusable elements. -*/ - -:-moz-focusring { - outline: auto; -} - -/* -Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) -*/ - -:-moz-ui-invalid { - box-shadow: none; -} - -/* -Add the correct vertical alignment in Chrome and Firefox. -*/ - -progress { - vertical-align: baseline; -} - -/* -Correct the cursor style of increment and decrement buttons in Safari. -*/ - -::-webkit-inner-spin-button, -::-webkit-outer-spin-button { - height: auto; -} - -/* -1. Correct the odd appearance in Chrome and Safari. -2. Correct the outline style in Safari. -*/ - -[type='search'] { - -webkit-appearance: textfield; - /* 1 */ - outline-offset: -2px; - /* 2 */ -} - -/* -Remove the inner padding in Chrome and Safari on macOS. -*/ - -::-webkit-search-decoration { - -webkit-appearance: none; -} - -/* -1. Correct the inability to style clickable types in iOS and Safari. -2. Change font properties to `inherit` in Safari. -*/ - -::-webkit-file-upload-button { - -webkit-appearance: button; - /* 1 */ - font: inherit; - /* 2 */ -} - -/* -Add the correct display in Chrome and Safari. -*/ - -summary { - display: list-item; -} - -/* -Removes the default spacing and border for appropriate elements. -*/ - -blockquote, -dl, -dd, -h1, -h2, -h3, -h4, -h5, -h6, -hr, -figure, -p, -pre { - margin: 0; -} - -fieldset { - margin: 0; - padding: 0; -} - -legend { - padding: 0; -} - -ol, -ul, -menu { - list-style: none; - margin: 0; - padding: 0; -} - -/* -Reset default styling for dialogs. -*/ - -dialog { - padding: 0; -} - -/* -Prevent resizing textareas horizontally by default. -*/ - -textarea { - resize: vertical; -} - -/* -1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) -2. Set the default placeholder color to the user's configured gray 400 color. -*/ - -input::-moz-placeholder, textarea::-moz-placeholder { - opacity: 1; - /* 1 */ - color: #9ca3af; - /* 2 */ -} - -input::placeholder, -textarea::placeholder { - opacity: 1; - /* 1 */ - color: #9ca3af; - /* 2 */ -} - -/* -Set the default cursor for buttons. -*/ - -button, -[role="button"] { - cursor: pointer; -} - -/* -Make sure disabled buttons don't get the pointer cursor. -*/ - -:disabled { - cursor: default; -} - -/* -1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) -2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) - This can trigger a poorly considered lint error in some tools but is included by design. -*/ - -img, -svg, -video, -canvas, -audio, -iframe, -embed, -object { - display: block; - /* 1 */ - vertical-align: middle; - /* 2 */ -} - -/* -Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) -*/ - -img, -video { - max-width: 100%; - height: auto; -} - -/* Make elements with the HTML hidden attribute stay hidden by default */ - -[hidden]:where(:not([hidden="until-found"])) { - display: none; -} - -input:where([type='text']),input:where(:not([type])),input:where([type='email']),input:where([type='url']),input:where([type='password']),input:where([type='number']),input:where([type='date']),input:where([type='datetime-local']),input:where([type='month']),input:where([type='search']),input:where([type='tel']),input:where([type='time']),input:where([type='week']),select:where([multiple]),textarea,select { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - background-color: #fff; - border-color: #6b7280; - border-width: 1px; - border-radius: 0px; - padding-top: 0.5rem; - padding-right: 0.75rem; - padding-bottom: 0.5rem; - padding-left: 0.75rem; - font-size: 1rem; - line-height: 1.5rem; - --tw-shadow: 0 0 #0000; -} - -input:where([type='text']):focus, input:where(:not([type])):focus, input:where([type='email']):focus, input:where([type='url']):focus, input:where([type='password']):focus, input:where([type='number']):focus, input:where([type='date']):focus, input:where([type='datetime-local']):focus, input:where([type='month']):focus, input:where([type='search']):focus, input:where([type='tel']):focus, input:where([type='time']):focus, input:where([type='week']):focus, select:where([multiple]):focus, textarea:focus, select:focus { - outline: 2px solid transparent; - outline-offset: 2px; - --tw-ring-inset: var(--tw-empty,/*!*/ /*!*/); - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: #2563eb; - --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); - --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color); - box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); - border-color: #2563eb; -} - -input::-moz-placeholder, textarea::-moz-placeholder { - color: #6b7280; - opacity: 1; -} - -input::placeholder,textarea::placeholder { - color: #6b7280; - opacity: 1; -} - -::-webkit-datetime-edit-fields-wrapper { - padding: 0; -} - -::-webkit-date-and-time-value { - min-height: 1.5em; - text-align: inherit; -} - -::-webkit-datetime-edit { - display: inline-flex; -} - -::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field { - padding-top: 0; - padding-bottom: 0; -} - -select { - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e"); - background-position: right 0.5rem center; - background-repeat: no-repeat; - background-size: 1.5em 1.5em; - padding-right: 2.5rem; - -webkit-print-color-adjust: exact; - print-color-adjust: exact; -} - -select:where([multiple]),select:where([size]:not([size="1"])) { - background-image: initial; - background-position: initial; - background-repeat: unset; - background-size: initial; - padding-right: 0.75rem; - -webkit-print-color-adjust: unset; - print-color-adjust: unset; -} - -input:where([type='checkbox']),input:where([type='radio']) { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - padding: 0; - -webkit-print-color-adjust: exact; - print-color-adjust: exact; - display: inline-block; - vertical-align: middle; - background-origin: border-box; - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; - flex-shrink: 0; - height: 1rem; - width: 1rem; - color: #2563eb; - background-color: #fff; - border-color: #6b7280; - border-width: 1px; - --tw-shadow: 0 0 #0000; -} - -input:where([type='checkbox']) { - border-radius: 0px; -} - -input:where([type='radio']) { - border-radius: 100%; -} - -input:where([type='checkbox']):focus,input:where([type='radio']):focus { - outline: 2px solid transparent; - outline-offset: 2px; - --tw-ring-inset: var(--tw-empty,/*!*/ /*!*/); - --tw-ring-offset-width: 2px; - --tw-ring-offset-color: #fff; - --tw-ring-color: #2563eb; - --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); - --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); - box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); -} - -input:where([type='checkbox']):checked,input:where([type='radio']):checked { - border-color: transparent; - background-color: currentColor; - background-size: 100% 100%; - background-position: center; - background-repeat: no-repeat; -} - -input:where([type='checkbox']):checked { - background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e"); -} - -@media (forced-colors: active) { - input:where([type='checkbox']):checked { - -webkit-appearance: auto; - -moz-appearance: auto; - appearance: auto; - } -} - -input:where([type='radio']):checked { - background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e"); -} - -@media (forced-colors: active) { - input:where([type='radio']):checked { - -webkit-appearance: auto; - -moz-appearance: auto; - appearance: auto; - } -} - -input:where([type='checkbox']):checked:hover,input:where([type='checkbox']):checked:focus,input:where([type='radio']):checked:hover,input:where([type='radio']):checked:focus { - border-color: transparent; - background-color: currentColor; -} - -input:where([type='checkbox']):indeterminate { - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e"); - border-color: transparent; - background-color: currentColor; - background-size: 100% 100%; - background-position: center; - background-repeat: no-repeat; -} - -@media (forced-colors: active) { - input:where([type='checkbox']):indeterminate { - -webkit-appearance: auto; - -moz-appearance: auto; - appearance: auto; - } -} - -input:where([type='checkbox']):indeterminate:hover,input:where([type='checkbox']):indeterminate:focus { - border-color: transparent; - background-color: currentColor; -} - -input:where([type='file']) { - background: unset; - border-color: inherit; - border-width: 0; - border-radius: 0; - padding: 0; - font-size: unset; - line-height: inherit; -} - -input:where([type='file']):focus { - outline: 1px solid ButtonText; - outline: 1px auto -webkit-focus-ring-color; -} - -html { - height: 100%; - font-size: 14px; -} - -@media (min-width: 768px) { - html { - font-size: 16px; - } -} - -body { - height: 100%; - --tw-bg-opacity: 1; - background-color: rgb(248 249 250 / var(--tw-bg-opacity, 1)); -} - -.container { - width: 100%; -} - -@media (min-width: 640px) { - .container { - max-width: 640px; - } -} - -@media (min-width: 768px) { - .container { - max-width: 768px; - } -} - -@media (min-width: 1024px) { - .container { - max-width: 1024px; - } -} - -@media (min-width: 1280px) { - .container { - max-width: 1280px; - } -} - -@media (min-width: 1536px) { - .container { - max-width: 1536px; - } -} - -/* Navigation Menu Items */ - -.nav-menu-item { - display: flex !important; - flex-direction: row; - align-items: center; - padding: 0.625rem 0.75rem; - color: rgb(209 213 219); - border-radius: 0.375rem; - transition: all 0.15s; - cursor: pointer; - width: 100%; -} - -.nav-menu-item:hover { - background-color: #1f2125; - color: white; -} - -.nav-menu-item.active { - background-color: #007bff; - color: white; - box-shadow: 0 0.125rem 0.25rem rgba(0,0,0,0.075); -} - -.nav-menu-icon { - display: inline-flex; - align-items: center; - justify-content: center; - width: 1.25rem; - height: 1.25rem; - margin-right: 0.75rem; - flex-shrink: 0; -} - -.nav-menu-text { - font-size: 0.875rem; - font-weight: 500; - line-height: 1.25rem; - white-space: nowrap; -} - -.nav-menu-item:hover .nav-menu-icon svg { - transform: scale(1.1); - transition: transform 0.15s ease-in-out; -} - -/* Buttons */ - -.btn { - display: inline-flex; - align-items: center; - justify-content: center; - border-radius: 0.25rem; - border-width: 1px; - border-color: transparent; - padding-left: 1rem; - padding-right: 1rem; - padding-top: 0.5rem; - padding-bottom: 0.5rem; - font-weight: 500; - transition-property: all; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -.btn:focus { - outline: 2px solid transparent; - outline-offset: 2px; - --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); - --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); - box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); - --tw-ring-offset-width: 2px; -} - -.btn-primary { - --tw-bg-opacity: 1; - background-color: rgb(0 123 255 / var(--tw-bg-opacity, 1)); - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity, 1)); - --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); - --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.btn-primary:hover { - --tw-bg-opacity: 1; - background-color: rgb(29 78 216 / var(--tw-bg-opacity, 1)); -} - -.btn-primary:focus { - --tw-ring-opacity: 1; - --tw-ring-color: rgb(0 123 255 / var(--tw-ring-opacity, 1)); -} - -.btn-secondary { - --tw-bg-opacity: 1; - background-color: rgb(108 117 125 / var(--tw-bg-opacity, 1)); - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity, 1)); - --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); - --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.btn-secondary:hover { - --tw-bg-opacity: 1; - background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1)); -} - -.btn-secondary:focus { - --tw-ring-opacity: 1; - --tw-ring-color: rgb(108 117 125 / var(--tw-ring-opacity, 1)); -} - -.btn-success { - --tw-bg-opacity: 1; - background-color: rgb(40 167 69 / var(--tw-bg-opacity, 1)); - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity, 1)); - --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); - --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.btn-success:hover { - --tw-bg-opacity: 1; - background-color: rgb(21 128 61 / var(--tw-bg-opacity, 1)); -} - -.btn-success:focus { - --tw-ring-opacity: 1; - --tw-ring-color: rgb(40 167 69 / var(--tw-ring-opacity, 1)); -} - -.btn-danger { - --tw-bg-opacity: 1; - background-color: rgb(220 53 69 / var(--tw-bg-opacity, 1)); - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity, 1)); - --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); - --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.btn-danger:hover { - --tw-bg-opacity: 1; - background-color: rgb(185 28 28 / var(--tw-bg-opacity, 1)); -} - -.btn-danger:focus { - --tw-ring-opacity: 1; - --tw-ring-color: rgb(220 53 69 / var(--tw-ring-opacity, 1)); -} - -.btn-sm { - padding-left: 0.75rem; - padding-right: 0.75rem; - padding-top: 0.375rem; - padding-bottom: 0.375rem; - font-size: 0.875rem; - line-height: 1.25rem; -} - -/* Cards */ - -.card { - border-radius: 0.5rem; - --tw-bg-opacity: 1; - background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1)); - --tw-shadow: 0 0.125rem 0.25rem rgba(0,0,0,0.075); - --tw-shadow-colored: 0 0.125rem 0.25rem var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - /* NOTE: overflow-hidden is intentionally omitted so that absolutely-positioned - children (e.g. multi-select dropdown panels) can escape the card boundary. */ -} - -.card-header { - overflow: hidden; - border-top-left-radius: 0.5rem; - border-top-right-radius: 0.5rem; - border-bottom-width: 1px; - --tw-border-opacity: 1; - border-color: rgb(222 226 230 / var(--tw-border-opacity, 1)); - --tw-bg-opacity: 1; - background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1)); - padding-left: 1.5rem; - padding-right: 1.5rem; - padding-top: 1rem; - padding-bottom: 1rem; -} - -.card-body { - padding: 1.5rem; -} - -.card-title { - font-size: 1.125rem; - line-height: 1.75rem; - font-weight: 600; - --tw-text-opacity: 1; - color: rgb(17 24 39 / var(--tw-text-opacity, 1)); -} - -/* Info boxes (AdminLTE small boxes) */ - -.info-box { - display: flex; - align-items: center; - border-radius: 0.5rem; - --tw-bg-opacity: 1; - background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1)); - padding: 1rem; - --tw-shadow: 0 0.125rem 0.25rem rgba(0,0,0,0.075); - --tw-shadow-colored: 0 0.125rem 0.25rem var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - transition-property: box-shadow; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 200ms; -} - -.info-box:hover { - --tw-shadow: 0 0.5rem 1rem rgba(0,0,0,0.15); - --tw-shadow-colored: 0 0.5rem 1rem var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.info-box-icon { - margin-right: 1rem; - display: flex; - height: 4rem; - width: 4rem; - flex-shrink: 0; - align-items: center; - justify-content: center; - border-radius: 0.25rem; - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity, 1)); -} - -.info-box-content { - flex: 1 1 0%; -} - -.info-box-text { - font-size: 0.875rem; - line-height: 1.25rem; - font-weight: 500; - text-transform: uppercase; - --tw-text-opacity: 1; - color: rgb(75 85 99 / var(--tw-text-opacity, 1)); -} - -.info-box-number { - font-size: 1.5rem; - line-height: 2rem; - font-weight: 700; - --tw-text-opacity: 1; - color: rgb(17 24 39 / var(--tw-text-opacity, 1)); -} - -/* Forms */ - -.form-control, - .input { - display: block; - width: 100%; - border-radius: 0.25rem; - border-width: 1px; - --tw-border-opacity: 1; - border-color: rgb(209 213 219 / var(--tw-border-opacity, 1)); - padding-left: 0.75rem; - padding-right: 0.75rem; - padding-top: 0.5rem; - padding-bottom: 0.5rem; - --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); - --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -.form-control:focus, - .input:focus { - --tw-border-opacity: 1; - border-color: rgb(0 123 255 / var(--tw-border-opacity, 1)); - --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); - --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color); - box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); - --tw-ring-opacity: 1; - --tw-ring-color: rgb(0 123 255 / var(--tw-ring-opacity, 1)); -} - -/* Tables */ - -.table { - min-width: 100%; -} - -.table > :not([hidden]) ~ :not([hidden]) { - --tw-divide-y-reverse: 0; - border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); - border-bottom-width: calc(1px * var(--tw-divide-y-reverse)); - --tw-divide-opacity: 1; - border-color: rgb(229 231 235 / var(--tw-divide-opacity, 1)); -} - -.table thead { - --tw-bg-opacity: 1; - background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1)); -} - -.table th { - padding-left: 1.5rem; - padding-right: 1.5rem; - padding-top: 0.75rem; - padding-bottom: 0.75rem; - text-align: left; - font-size: 0.75rem; - line-height: 1rem; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.05em; - --tw-text-opacity: 1; - color: rgb(75 85 99 / var(--tw-text-opacity, 1)); -} - -.table td { - white-space: nowrap; - padding-left: 1.5rem; - padding-right: 1.5rem; - padding-top: 1rem; - padding-bottom: 1rem; - font-size: 0.875rem; - line-height: 1.25rem; - --tw-text-opacity: 1; - color: rgb(17 24 39 / var(--tw-text-opacity, 1)); -} - -.table tbody > :not([hidden]) ~ :not([hidden]) { - --tw-divide-y-reverse: 0; - border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); - border-bottom-width: calc(1px * var(--tw-divide-y-reverse)); - --tw-divide-opacity: 1; - border-color: rgb(229 231 235 / var(--tw-divide-opacity, 1)); -} - -.table tbody { - --tw-bg-opacity: 1; - background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1)); -} - -/* Badges */ - -.badge { - display: inline-flex; - align-items: center; - border-radius: 9999px; - padding-left: 0.625rem; - padding-right: 0.625rem; - padding-top: 0.125rem; - padding-bottom: 0.125rem; - font-size: 0.75rem; - line-height: 1rem; - font-weight: 500; -} - -.badge-secondary { - --tw-bg-opacity: 1; - background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1)); - --tw-text-opacity: 1; - color: rgb(31 41 55 / var(--tw-text-opacity, 1)); -} - -.badge-success { - --tw-bg-opacity: 1; - background-color: rgb(220 252 231 / var(--tw-bg-opacity, 1)); - --tw-text-opacity: 1; - color: rgb(22 101 52 / var(--tw-text-opacity, 1)); -} - -.badge-danger { - --tw-bg-opacity: 1; - background-color: rgb(254 226 226 / var(--tw-bg-opacity, 1)); - --tw-text-opacity: 1; - color: rgb(153 27 27 / var(--tw-text-opacity, 1)); -} - -.badge-warning { - --tw-bg-opacity: 1; - background-color: rgb(254 249 195 / var(--tw-bg-opacity, 1)); - --tw-text-opacity: 1; - color: rgb(133 77 14 / var(--tw-text-opacity, 1)); -} - -.visible { - visibility: visible; -} - -.collapse { - visibility: collapse; -} - -.static { - position: static; -} - -.fixed { - position: fixed; -} - -.absolute { - position: absolute; -} - -.relative { - position: relative; -} - -.inset-0 { - inset: 0px; -} - -.bottom-0 { - bottom: 0px; -} - -.bottom-4 { - bottom: 1rem; -} - -.left-0 { - left: 0px; -} - -.right-0 { - right: 0px; -} - -.right-4 { - right: 1rem; -} - -.top-20 { - top: 5rem; -} - -.z-10 { - z-index: 10; -} - -.z-50 { - z-index: 50; -} - -.mx-4 { - margin-left: 1rem; - margin-right: 1rem; -} - -.mx-auto { - margin-left: auto; - margin-right: auto; -} - -.-mb-px { - margin-bottom: -1px; -} - -.mb-1 { - margin-bottom: 0.25rem; -} - -.mb-2 { - margin-bottom: 0.5rem; -} - -.mb-3 { - margin-bottom: 0.75rem; -} - -.mb-4 { - margin-bottom: 1rem; -} - -.mb-6 { - margin-bottom: 1.5rem; -} - -.mb-8 { - margin-bottom: 2rem; -} - -.ml-1 { - margin-left: 0.25rem; -} - -.ml-2 { - margin-left: 0.5rem; -} - -.ml-3 { - margin-left: 0.75rem; -} - -.ml-6 { - margin-left: 1.5rem; -} - -.ml-7 { - margin-left: 1.75rem; -} - -.ml-auto { - margin-left: auto; -} - -.mr-1 { - margin-right: 0.25rem; -} - -.mr-2 { - margin-right: 0.5rem; -} - -.mr-3 { - margin-right: 0.75rem; -} - -.mt-0\.5 { - margin-top: 0.125rem; -} - -.mt-1 { - margin-top: 0.25rem; -} - -.mt-12 { - margin-top: 3rem; -} - -.mt-2 { - margin-top: 0.5rem; -} - -.mt-3 { - margin-top: 0.75rem; -} - -.mt-4 { - margin-top: 1rem; -} - -.mt-5 { - margin-top: 1.25rem; -} - -.mt-6 { - margin-top: 1.5rem; -} - -.mt-8 { - margin-top: 2rem; -} - -.block { - display: block; -} - -.inline-block { - display: inline-block; -} - -.flex { - display: flex; -} - -.inline-flex { - display: inline-flex; -} - -.table { - display: table; -} - -.grid { - display: grid; -} - -.hidden { - display: none; -} - -.h-10 { - height: 2.5rem; -} - -.h-12 { - height: 3rem; -} - -.h-16 { - height: 4rem; -} - -.h-2\.5 { - height: 0.625rem; -} - -.h-20 { - height: 5rem; -} - -.h-24 { - height: 6rem; -} - -.h-3 { - height: 0.75rem; -} - -.h-4 { - height: 1rem; -} - -.h-5 { - height: 1.25rem; -} - -.h-6 { - height: 1.5rem; -} - -.h-8 { - height: 2rem; -} - -.h-full { - height: 100%; -} - -.h-screen { - height: 100vh; -} - -.max-h-60 { - max-height: 15rem; -} - -.min-h-\[60vh\] { - min-height: 60vh; -} - -.min-h-screen { - min-height: 100vh; -} - -.w-1\/2 { - width: 50%; -} - -.w-10 { - width: 2.5rem; -} - -.w-12 { - width: 3rem; -} - -.w-16 { - width: 4rem; -} - -.w-20 { - width: 5rem; -} - -.w-24 { - width: 6rem; -} - -.w-3 { - width: 0.75rem; -} - -.w-4 { - width: 1rem; -} - -.w-48 { - width: 12rem; -} - -.w-5 { - width: 1.25rem; -} - -.w-56 { - width: 14rem; -} - -.w-6 { - width: 1.5rem; -} - -.w-64 { - width: 16rem; -} - -.w-8 { - width: 2rem; -} - -.w-96 { - width: 24rem; -} - -.w-full { - width: 100%; -} - -.min-w-\[200px\] { - min-width: 200px; -} - -.min-w-full { - min-width: 100%; -} - -.max-w-2xl { - max-width: 42rem; -} - -.max-w-4xl { - max-width: 56rem; -} - -.max-w-7xl { - max-width: 80rem; -} - -.max-w-lg { - max-width: 32rem; -} - -.max-w-xs { - max-width: 20rem; -} - -.flex-1 { - flex: 1 1 0%; -} - -.flex-shrink-0 { - flex-shrink: 0; -} - -.rotate-180 { - --tw-rotate: 180deg; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -@keyframes spin { - to { - transform: rotate(360deg); - } -} - -.animate-spin { - animation: spin 1s linear infinite; -} - -.cursor-pointer { - cursor: pointer; -} - -.select-none { - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; -} - -.grid-cols-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); -} - -.grid-cols-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); -} - -.flex-col { - flex-direction: column; -} - -.flex-wrap { - flex-wrap: wrap; -} - -.items-start { - align-items: flex-start; -} - -.items-end { - align-items: flex-end; -} - -.items-center { - align-items: center; -} - -.justify-end { - justify-content: flex-end; -} - -.justify-center { - justify-content: center; -} - -.justify-between { - justify-content: space-between; -} - -.gap-1 { - gap: 0.25rem; -} - -.gap-2 { - gap: 0.5rem; -} - -.gap-3 { - gap: 0.75rem; -} - -.gap-4 { - gap: 1rem; -} - -.gap-6 { - gap: 1.5rem; -} - -.space-x-1 > :not([hidden]) ~ :not([hidden]) { - --tw-space-x-reverse: 0; - margin-right: calc(0.25rem * var(--tw-space-x-reverse)); - margin-left: calc(0.25rem * calc(1 - var(--tw-space-x-reverse))); -} - -.space-x-2 > :not([hidden]) ~ :not([hidden]) { - --tw-space-x-reverse: 0; - margin-right: calc(0.5rem * var(--tw-space-x-reverse)); - margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse))); -} - -.space-x-3 > :not([hidden]) ~ :not([hidden]) { - --tw-space-x-reverse: 0; - margin-right: calc(0.75rem * var(--tw-space-x-reverse)); - margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse))); -} - -.space-x-4 > :not([hidden]) ~ :not([hidden]) { - --tw-space-x-reverse: 0; - margin-right: calc(1rem * var(--tw-space-x-reverse)); - margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); -} - -.space-x-8 > :not([hidden]) ~ :not([hidden]) { - --tw-space-x-reverse: 0; - margin-right: calc(2rem * var(--tw-space-x-reverse)); - margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse))); -} - -.space-y-1 > :not([hidden]) ~ :not([hidden]) { - --tw-space-y-reverse: 0; - margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(0.25rem * var(--tw-space-y-reverse)); -} - -.space-y-2 > :not([hidden]) ~ :not([hidden]) { - --tw-space-y-reverse: 0; - margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(0.5rem * var(--tw-space-y-reverse)); -} - -.space-y-3 > :not([hidden]) ~ :not([hidden]) { - --tw-space-y-reverse: 0; - margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(0.75rem * var(--tw-space-y-reverse)); -} - -.space-y-4 > :not([hidden]) ~ :not([hidden]) { - --tw-space-y-reverse: 0; - margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(1rem * var(--tw-space-y-reverse)); -} - -.space-y-6 > :not([hidden]) ~ :not([hidden]) { - --tw-space-y-reverse: 0; - margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(1.5rem * var(--tw-space-y-reverse)); -} - -.divide-y > :not([hidden]) ~ :not([hidden]) { - --tw-divide-y-reverse: 0; - border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); - border-bottom-width: calc(1px * var(--tw-divide-y-reverse)); -} - -.divide-gray-200 > :not([hidden]) ~ :not([hidden]) { - --tw-divide-opacity: 1; - border-color: rgb(229 231 235 / var(--tw-divide-opacity, 1)); -} - -.overflow-auto { - overflow: auto; -} - -.overflow-hidden { - overflow: hidden; -} - -.overflow-x-auto { - overflow-x: auto; -} - -.overflow-y-auto { - overflow-y: auto; -} - -.truncate { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.whitespace-nowrap { - white-space: nowrap; -} - -.rounded { - border-radius: 0.25rem; -} - -.rounded-full { - border-radius: 9999px; -} - -.rounded-lg { - border-radius: 0.5rem; -} - -.rounded-md { - border-radius: 0.375rem; -} - -.border { - border-width: 1px; -} - -.border-b { - border-bottom-width: 1px; -} - -.border-b-2 { - border-bottom-width: 2px; -} - -.border-l { - border-left-width: 1px; -} - -.border-l-4 { - border-left-width: 4px; -} - -.border-t { - border-top-width: 1px; -} - -.border-admin-darker { - --tw-border-opacity: 1; - border-color: rgb(31 33 37 / var(--tw-border-opacity, 1)); -} - -.border-admin-primary { - --tw-border-opacity: 1; - border-color: rgb(0 123 255 / var(--tw-border-opacity, 1)); -} - -.border-blue-200 { - --tw-border-opacity: 1; - border-color: rgb(191 219 254 / var(--tw-border-opacity, 1)); -} - -.border-blue-500 { - --tw-border-opacity: 1; - border-color: rgb(59 130 246 / var(--tw-border-opacity, 1)); -} - -.border-blue-600 { - --tw-border-opacity: 1; - border-color: rgb(37 99 235 / var(--tw-border-opacity, 1)); -} - -.border-gray-100 { - --tw-border-opacity: 1; - border-color: rgb(243 244 246 / var(--tw-border-opacity, 1)); -} - -.border-gray-200 { - --tw-border-opacity: 1; - border-color: rgb(229 231 235 / var(--tw-border-opacity, 1)); -} - -.border-gray-300 { - --tw-border-opacity: 1; - border-color: rgb(209 213 219 / var(--tw-border-opacity, 1)); -} - -.border-green-200 { - --tw-border-opacity: 1; - border-color: rgb(187 247 208 / var(--tw-border-opacity, 1)); -} - -.border-green-500 { - --tw-border-opacity: 1; - border-color: rgb(34 197 94 / var(--tw-border-opacity, 1)); -} - -.border-red-200 { - --tw-border-opacity: 1; - border-color: rgb(254 202 202 / var(--tw-border-opacity, 1)); -} - -.border-red-400 { - --tw-border-opacity: 1; - border-color: rgb(248 113 113 / var(--tw-border-opacity, 1)); -} - -.border-red-500 { - --tw-border-opacity: 1; - border-color: rgb(239 68 68 / var(--tw-border-opacity, 1)); -} - -.border-white { - --tw-border-opacity: 1; - border-color: rgb(255 255 255 / var(--tw-border-opacity, 1)); -} - -.border-yellow-200 { - --tw-border-opacity: 1; - border-color: rgb(254 240 138 / var(--tw-border-opacity, 1)); -} - -.border-yellow-400 { - --tw-border-opacity: 1; - border-color: rgb(250 204 21 / var(--tw-border-opacity, 1)); -} - -.border-yellow-500 { - --tw-border-opacity: 1; - border-color: rgb(234 179 8 / var(--tw-border-opacity, 1)); -} - -.bg-admin-danger { - --tw-bg-opacity: 1; - background-color: rgb(220 53 69 / var(--tw-bg-opacity, 1)); -} - -.bg-admin-darker { - --tw-bg-opacity: 1; - background-color: rgb(31 33 37 / var(--tw-bg-opacity, 1)); -} - -.bg-admin-info { - --tw-bg-opacity: 1; - background-color: rgb(23 162 184 / var(--tw-bg-opacity, 1)); -} - -.bg-admin-light { - --tw-bg-opacity: 1; - background-color: rgb(248 249 250 / var(--tw-bg-opacity, 1)); -} - -.bg-admin-primary { - --tw-bg-opacity: 1; - background-color: rgb(0 123 255 / var(--tw-bg-opacity, 1)); -} - -.bg-admin-sidebar { - --tw-bg-opacity: 1; - background-color: rgb(44 48 52 / var(--tw-bg-opacity, 1)); -} - -.bg-admin-success { - --tw-bg-opacity: 1; - background-color: rgb(40 167 69 / var(--tw-bg-opacity, 1)); -} - -.bg-admin-warning { - --tw-bg-opacity: 1; - background-color: rgb(255 193 7 / var(--tw-bg-opacity, 1)); -} - -.bg-black { - --tw-bg-opacity: 1; - background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1)); -} - -.bg-blue-100 { - --tw-bg-opacity: 1; - background-color: rgb(219 234 254 / var(--tw-bg-opacity, 1)); -} - -.bg-blue-50 { - --tw-bg-opacity: 1; - background-color: rgb(239 246 255 / var(--tw-bg-opacity, 1)); -} - -.bg-blue-600 { - --tw-bg-opacity: 1; - background-color: rgb(37 99 235 / var(--tw-bg-opacity, 1)); -} - -.bg-gray-100 { - --tw-bg-opacity: 1; - background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1)); -} - -.bg-gray-200 { - --tw-bg-opacity: 1; - background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1)); -} - -.bg-gray-50 { - --tw-bg-opacity: 1; - background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1)); -} - -.bg-gray-600 { - --tw-bg-opacity: 1; - background-color: rgb(75 85 99 / var(--tw-bg-opacity, 1)); -} - -.bg-green-100 { - --tw-bg-opacity: 1; - background-color: rgb(220 252 231 / var(--tw-bg-opacity, 1)); -} - -.bg-green-50 { - --tw-bg-opacity: 1; - background-color: rgb(240 253 244 / var(--tw-bg-opacity, 1)); -} - -.bg-green-600 { - --tw-bg-opacity: 1; - background-color: rgb(22 163 74 / var(--tw-bg-opacity, 1)); -} - -.bg-purple-100 { - --tw-bg-opacity: 1; - background-color: rgb(243 232 255 / var(--tw-bg-opacity, 1)); -} - -.bg-purple-50 { - --tw-bg-opacity: 1; - background-color: rgb(250 245 255 / var(--tw-bg-opacity, 1)); -} - -.bg-purple-600 { - --tw-bg-opacity: 1; - background-color: rgb(147 51 234 / var(--tw-bg-opacity, 1)); -} - -.bg-red-100 { - --tw-bg-opacity: 1; - background-color: rgb(254 226 226 / var(--tw-bg-opacity, 1)); -} - -.bg-red-50 { - --tw-bg-opacity: 1; - background-color: rgb(254 242 242 / var(--tw-bg-opacity, 1)); -} - -.bg-red-600 { - --tw-bg-opacity: 1; - background-color: rgb(220 38 38 / var(--tw-bg-opacity, 1)); -} - -.bg-teal-600 { - --tw-bg-opacity: 1; - background-color: rgb(13 148 136 / var(--tw-bg-opacity, 1)); -} - -.bg-white { - --tw-bg-opacity: 1; - background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1)); -} - -.bg-yellow-100 { - --tw-bg-opacity: 1; - background-color: rgb(254 249 195 / var(--tw-bg-opacity, 1)); -} - -.bg-yellow-50 { - --tw-bg-opacity: 1; - background-color: rgb(254 252 232 / var(--tw-bg-opacity, 1)); -} - -.bg-opacity-50 { - --tw-bg-opacity: 0.5; -} - -.bg-gradient-to-br { - background-image: linear-gradient(to bottom right, var(--tw-gradient-stops)); -} - -.bg-gradient-to-r { - background-image: linear-gradient(to right, var(--tw-gradient-stops)); -} - -.from-admin-primary { - --tw-gradient-from: #007bff var(--tw-gradient-from-position); - --tw-gradient-to: rgb(0 123 255 / 0) var(--tw-gradient-to-position); - --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); -} - -.from-blue-500 { - --tw-gradient-from: #3b82f6 var(--tw-gradient-from-position); - --tw-gradient-to: rgb(59 130 246 / 0) var(--tw-gradient-to-position); - --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); -} - -.to-admin-secondary { - --tw-gradient-to: #6c757d var(--tw-gradient-to-position); -} - -.to-purple-600 { - --tw-gradient-to: #9333ea var(--tw-gradient-to-position); -} - -.p-0 { - padding: 0px; -} - -.p-1 { - padding: 0.25rem; -} - -.p-2 { - padding: 0.5rem; -} - -.p-3 { - padding: 0.75rem; -} - -.p-4 { - padding: 1rem; -} - -.p-5 { - padding: 1.25rem; -} - -.p-6 { - padding: 1.5rem; -} - -.p-8 { - padding: 2rem; -} - -.px-2 { - padding-left: 0.5rem; - padding-right: 0.5rem; -} - -.px-3 { - padding-left: 0.75rem; - padding-right: 0.75rem; -} - -.px-4 { - padding-left: 1rem; - padding-right: 1rem; -} - -.px-6 { - padding-left: 1.5rem; - padding-right: 1.5rem; -} - -.px-7 { - padding-left: 1.75rem; - padding-right: 1.75rem; -} - -.px-8 { - padding-left: 2rem; - padding-right: 2rem; -} - -.py-1 { - padding-top: 0.25rem; - padding-bottom: 0.25rem; -} - -.py-1\.5 { - padding-top: 0.375rem; - padding-bottom: 0.375rem; -} - -.py-12 { - padding-top: 3rem; - padding-bottom: 3rem; -} - -.py-2 { - padding-top: 0.5rem; - padding-bottom: 0.5rem; -} - -.py-3 { - padding-top: 0.75rem; - padding-bottom: 0.75rem; -} - -.py-4 { - padding-top: 1rem; - padding-bottom: 1rem; -} - -.py-5 { - padding-top: 1.25rem; - padding-bottom: 1.25rem; -} - -.py-6 { - padding-top: 1.5rem; - padding-bottom: 1.5rem; -} - -.py-8 { - padding-top: 2rem; - padding-bottom: 2rem; -} - -.pb-6 { - padding-bottom: 1.5rem; -} - -.pl-3 { - padding-left: 0.75rem; -} - -.pl-4 { - padding-left: 1rem; -} - -.pr-3 { - padding-right: 0.75rem; -} - -.pt-0 { - padding-top: 0px; -} - -.pt-4 { - padding-top: 1rem; -} - -.pt-6 { - padding-top: 1.5rem; -} - -.text-left { - text-align: left; -} - -.\!text-center { - text-align: center !important; -} - -.text-center { - text-align: center; -} - -.\!text-right { - text-align: right !important; -} - -.text-right { - text-align: right; -} - -.font-mono { - font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; -} - -.text-2xl { - font-size: 1.5rem; - line-height: 2rem; -} - -.text-3xl { - font-size: 1.875rem; - line-height: 2.25rem; -} - -.text-lg { - font-size: 1.125rem; - line-height: 1.75rem; -} - -.text-sm { - font-size: 0.875rem; - line-height: 1.25rem; -} - -.text-xl { - font-size: 1.25rem; - line-height: 1.75rem; -} - -.text-xs { - font-size: 0.75rem; - line-height: 1rem; -} - -.font-bold { - font-weight: 700; -} - -.font-medium { - font-weight: 500; -} - -.font-semibold { - font-weight: 600; -} - -.uppercase { - text-transform: uppercase; -} - -.italic { - font-style: italic; -} - -.leading-6 { - line-height: 1.5rem; -} - -.leading-tight { - line-height: 1.25; -} - -.tracking-wider { - letter-spacing: 0.05em; -} - -.text-admin-danger { - --tw-text-opacity: 1; - color: rgb(220 53 69 / var(--tw-text-opacity, 1)); -} - -.text-admin-primary { - --tw-text-opacity: 1; - color: rgb(0 123 255 / var(--tw-text-opacity, 1)); -} - -.text-admin-warning { - --tw-text-opacity: 1; - color: rgb(255 193 7 / var(--tw-text-opacity, 1)); -} - -.text-blue-500 { - --tw-text-opacity: 1; - color: rgb(59 130 246 / var(--tw-text-opacity, 1)); -} - -.text-blue-600 { - --tw-text-opacity: 1; - color: rgb(37 99 235 / var(--tw-text-opacity, 1)); -} - -.text-blue-700 { - --tw-text-opacity: 1; - color: rgb(29 78 216 / var(--tw-text-opacity, 1)); -} - -.text-blue-800 { - --tw-text-opacity: 1; - color: rgb(30 64 175 / var(--tw-text-opacity, 1)); -} - -.text-blue-900 { - --tw-text-opacity: 1; - color: rgb(30 58 138 / var(--tw-text-opacity, 1)); -} - -.text-gray-300 { - --tw-text-opacity: 1; - color: rgb(209 213 219 / var(--tw-text-opacity, 1)); -} - -.text-gray-400 { - --tw-text-opacity: 1; - color: rgb(156 163 175 / var(--tw-text-opacity, 1)); -} - -.text-gray-500 { - --tw-text-opacity: 1; - color: rgb(107 114 128 / var(--tw-text-opacity, 1)); -} - -.text-gray-600 { - --tw-text-opacity: 1; - color: rgb(75 85 99 / var(--tw-text-opacity, 1)); -} - -.text-gray-700 { - --tw-text-opacity: 1; - color: rgb(55 65 81 / var(--tw-text-opacity, 1)); -} - -.text-gray-800 { - --tw-text-opacity: 1; - color: rgb(31 41 55 / var(--tw-text-opacity, 1)); -} - -.text-gray-900 { - --tw-text-opacity: 1; - color: rgb(17 24 39 / var(--tw-text-opacity, 1)); -} - -.text-green-500 { - --tw-text-opacity: 1; - color: rgb(34 197 94 / var(--tw-text-opacity, 1)); -} - -.text-green-600 { - --tw-text-opacity: 1; - color: rgb(22 163 74 / var(--tw-text-opacity, 1)); -} - -.text-green-700 { - --tw-text-opacity: 1; - color: rgb(21 128 61 / var(--tw-text-opacity, 1)); -} - -.text-green-800 { - --tw-text-opacity: 1; - color: rgb(22 101 52 / var(--tw-text-opacity, 1)); -} - -.text-green-900 { - --tw-text-opacity: 1; - color: rgb(20 83 45 / var(--tw-text-opacity, 1)); -} - -.text-purple-600 { - --tw-text-opacity: 1; - color: rgb(147 51 234 / var(--tw-text-opacity, 1)); -} - -.text-purple-900 { - --tw-text-opacity: 1; - color: rgb(88 28 135 / var(--tw-text-opacity, 1)); -} - -.text-red-500 { - --tw-text-opacity: 1; - color: rgb(239 68 68 / var(--tw-text-opacity, 1)); -} - -.text-red-600 { - --tw-text-opacity: 1; - color: rgb(220 38 38 / var(--tw-text-opacity, 1)); -} - -.text-red-700 { - --tw-text-opacity: 1; - color: rgb(185 28 28 / var(--tw-text-opacity, 1)); -} - -.text-red-800 { - --tw-text-opacity: 1; - color: rgb(153 27 27 / var(--tw-text-opacity, 1)); -} - -.text-white { - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity, 1)); -} - -.text-yellow-400 { - --tw-text-opacity: 1; - color: rgb(250 204 21 / var(--tw-text-opacity, 1)); -} - -.text-yellow-500 { - --tw-text-opacity: 1; - color: rgb(234 179 8 / var(--tw-text-opacity, 1)); -} - -.text-yellow-600 { - --tw-text-opacity: 1; - color: rgb(202 138 4 / var(--tw-text-opacity, 1)); -} - -.text-yellow-700 { - --tw-text-opacity: 1; - color: rgb(161 98 7 / var(--tw-text-opacity, 1)); -} - -.text-yellow-800 { - --tw-text-opacity: 1; - color: rgb(133 77 14 / var(--tw-text-opacity, 1)); -} - -.underline { - text-decoration-line: underline; -} - -.opacity-25 { - opacity: 0.25; -} - -.opacity-75 { - opacity: 0.75; -} - -.shadow { - --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.shadow-admin { - --tw-shadow: 0 0.125rem 0.25rem rgba(0,0,0,0.075); - --tw-shadow-colored: 0 0.125rem 0.25rem var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.shadow-admin-lg { - --tw-shadow: 0 0.5rem 1rem rgba(0,0,0,0.15); - --tw-shadow-colored: 0 0.5rem 1rem var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.shadow-lg { - --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.shadow-md { - --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.shadow-sm { - --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); - --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.blur { - --tw-blur: blur(8px); - filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); -} - -.filter { - filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); -} - -.transition-colors { - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -.transition-shadow { - transition-property: box-shadow; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -.transition-transform { - transition-property: transform; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -.duration-150 { - transition-duration: 150ms; -} - -.scrollbar-thin::-webkit-scrollbar { - width: 8px; - height: 8px; -} - -.scrollbar-thin::-webkit-scrollbar-track { - --tw-bg-opacity: 1; - background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1)); -} - -.scrollbar-thin::-webkit-scrollbar-thumb { - border-radius: 0.25rem; - --tw-bg-opacity: 1; - background-color: rgb(156 163 175 / var(--tw-bg-opacity, 1)); -} - -.scrollbar-thin::-webkit-scrollbar-thumb:hover { - --tw-bg-opacity: 1; - background-color: rgb(107 114 128 / var(--tw-bg-opacity, 1)); -} - -/* Design-system CSS custom properties (available throughout the app) */ - -:root { - --color-admin-primary: #007bff; - --color-admin-secondary: #6c757d; - --color-admin-success: #28a745; - --color-admin-info: #17a2b8; - --color-admin-warning: #ffc107; - --color-admin-danger: #dc3545; -} - -/* AdminLTE-inspired components */ - -/* Base styles */ - -/* Utility classes */ - -.hover\:bg-blue-700:hover { - --tw-bg-opacity: 1; - background-color: rgb(29 78 216 / var(--tw-bg-opacity, 1)); -} - -.hover\:bg-gray-100:hover { - --tw-bg-opacity: 1; - background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1)); -} - -.hover\:bg-gray-300:hover { - --tw-bg-opacity: 1; - background-color: rgb(209 213 219 / var(--tw-bg-opacity, 1)); -} - -.hover\:bg-gray-50:hover { - --tw-bg-opacity: 1; - background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1)); -} - -.hover\:bg-green-700:hover { - --tw-bg-opacity: 1; - background-color: rgb(21 128 61 / var(--tw-bg-opacity, 1)); -} - -.hover\:bg-teal-700:hover { - --tw-bg-opacity: 1; - background-color: rgb(15 118 110 / var(--tw-bg-opacity, 1)); -} - -.hover\:bg-yellow-200:hover { - --tw-bg-opacity: 1; - background-color: rgb(254 240 138 / var(--tw-bg-opacity, 1)); -} - -.hover\:text-blue-800:hover { - --tw-text-opacity: 1; - color: rgb(30 64 175 / var(--tw-text-opacity, 1)); -} - -.hover\:text-gray-200:hover { - --tw-text-opacity: 1; - color: rgb(229 231 235 / var(--tw-text-opacity, 1)); -} - -.hover\:text-gray-900:hover { - --tw-text-opacity: 1; - color: rgb(17 24 39 / var(--tw-text-opacity, 1)); -} - -.hover\:text-green-800:hover { - --tw-text-opacity: 1; - color: rgb(22 101 52 / var(--tw-text-opacity, 1)); -} - -.hover\:text-purple-800:hover { - --tw-text-opacity: 1; - color: rgb(107 33 168 / var(--tw-text-opacity, 1)); -} - -.hover\:text-red-800:hover { - --tw-text-opacity: 1; - color: rgb(153 27 27 / var(--tw-text-opacity, 1)); -} - -.hover\:underline:hover { - text-decoration-line: underline; -} - -.hover\:no-underline:hover { - text-decoration-line: none; -} - -.hover\:shadow-lg:hover { - --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.hover\:shadow-md:hover { - --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -.focus\:border-transparent:focus { - border-color: transparent; -} - -.focus\:outline-none:focus { - outline: 2px solid transparent; - outline-offset: 2px; -} - -.focus\:ring-2:focus { - --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); - --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); - box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); -} - -.focus\:ring-blue-500:focus { - --tw-ring-opacity: 1; - --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1)); -} - -@media (min-width: 640px) { - .sm\:block { - display: block; - } - - .sm\:flex-row { - flex-direction: row; - } -} - -@media (min-width: 768px) { - .md\:flex { - display: flex; - } - - .md\:hidden { - display: none; - } - - .md\:w-64 { - width: 16rem; - } - - .md\:grid-cols-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - .md\:grid-cols-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } - - .md\:grid-cols-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - - .md\:grid-cols-5 { - grid-template-columns: repeat(5, minmax(0, 1fr)); - } -} - -@media (min-width: 1024px) { - .lg\:grid-cols-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - .lg\:grid-cols-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } - - .lg\:grid-cols-5 { - grid-template-columns: repeat(5, minmax(0, 1fr)); - } -} - -@media (min-width: 1280px) { - .xl\:grid-cols-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } -} diff --git a/archive/SecurityService/wwwroot/css/site.css b/archive/SecurityService/wwwroot/css/site.css deleted file mode 100644 index f02c0b19..00000000 --- a/archive/SecurityService/wwwroot/css/site.css +++ /dev/null @@ -1,39 +0,0 @@ -.welcome-page .logo { - width: 64px; -} - -.icon-banner { - width: 32px; -} - -.body-container { - margin-top: 60px; - padding-bottom: 40px; -} - -.welcome-page li { - list-style: none; - padding: 4px; -} - -.logged-out-page iframe { - display: none; - width: 0; - height: 0; -} - -.grants-page .card { - margin-top: 20px; - border-bottom: 1px solid lightgray; -} -.grants-page .card .card-title { - font-size: 120%; - font-weight: bold; -} -.grants-page .card .card-title img { - width: 100px; - height: 100px; -} -.grants-page .card label { - font-weight: bold; -} diff --git a/archive/SecurityService/wwwroot/css/site.min.css b/archive/SecurityService/wwwroot/css/site.min.css deleted file mode 100644 index f3e19857..00000000 --- a/archive/SecurityService/wwwroot/css/site.min.css +++ /dev/null @@ -1 +0,0 @@ -.welcome-page .logo{width:64px;}.icon-banner{width:32px;}.body-container{margin-top:60px;padding-bottom:40px;}.welcome-page li{list-style:none;padding:4px;}.logged-out-page iframe{display:none;width:0;height:0;}.grants-page .card{margin-top:20px;border-bottom:1px solid #d3d3d3;}.grants-page .card .card-title{font-size:120%;font-weight:bold;}.grants-page .card .card-title img{width:100px;height:100px;}.grants-page .card label{font-weight:bold;} \ No newline at end of file diff --git a/archive/SecurityService/wwwroot/css/site.scss b/archive/SecurityService/wwwroot/css/site.scss deleted file mode 100644 index 29d9c853..00000000 --- a/archive/SecurityService/wwwroot/css/site.scss +++ /dev/null @@ -1,50 +0,0 @@ -.welcome-page { - .logo { - width: 64px; - } -} - -.icon-banner { - width: 32px; -} - -.body-container { - margin-top: 60px; - padding-bottom: 40px; -} - -.welcome-page { - li { - list-style: none; - padding: 4px; - } -} - -.logged-out-page { - iframe { - display: none; - width: 0; - height: 0; - } -} - -.grants-page { - .card { - margin-top: 20px; - border-bottom: 1px solid lightgray; - - .card-title { - img { - width: 100px; - height: 100px; - } - - font-size: 120%; - font-weight: bold; - } - - label { - font-weight: bold; - } - } -} diff --git a/archive/SecurityService/wwwroot/duende-logo.svg b/archive/SecurityService/wwwroot/duende-logo.svg deleted file mode 100644 index 5fa55bf3..00000000 --- a/archive/SecurityService/wwwroot/duende-logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/archive/SecurityService/wwwroot/favicon.ico b/archive/SecurityService/wwwroot/favicon.ico deleted file mode 100644 index f7ecfd99..00000000 Binary files a/archive/SecurityService/wwwroot/favicon.ico and /dev/null differ diff --git a/archive/SecurityService/wwwroot/js/signin-redirect.js b/archive/SecurityService/wwwroot/js/signin-redirect.js deleted file mode 100644 index 6ebc5691..00000000 --- a/archive/SecurityService/wwwroot/js/signin-redirect.js +++ /dev/null @@ -1 +0,0 @@ -window.location.href = document.querySelector("meta[http-equiv=refresh]").getAttribute("data-url"); diff --git a/archive/SecurityService/wwwroot/js/signout-redirect.js b/archive/SecurityService/wwwroot/js/signout-redirect.js deleted file mode 100644 index cdfc5e78..00000000 --- a/archive/SecurityService/wwwroot/js/signout-redirect.js +++ /dev/null @@ -1,6 +0,0 @@ -window.addEventListener("load", function () { - var a = document.querySelector("a.PostLogoutRedirectUri"); - if (a) { - window.location = a.href; - } -}); diff --git a/archive/SecurityService/wwwroot/lib/bootstrap/LICENSE b/archive/SecurityService/wwwroot/lib/bootstrap/LICENSE deleted file mode 100644 index 173a9ebb..00000000 --- a/archive/SecurityService/wwwroot/lib/bootstrap/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2011-2020 Twitter, Inc. -Copyright (c) 2011-2020 The Bootstrap Authors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/archive/SecurityService/wwwroot/lib/bootstrap/README.md b/archive/SecurityService/wwwroot/lib/bootstrap/README.md deleted file mode 100644 index 35ce9fea..00000000 --- a/archive/SecurityService/wwwroot/lib/bootstrap/README.md +++ /dev/null @@ -1,209 +0,0 @@ -

    - - Bootstrap logo - -

    - -

    Bootstrap

    - -

    - Sleek, intuitive, and powerful front-end framework for faster and easier web development. -
    - Explore Bootstrap docs » -
    -
    - Report bug - · - Request feature - · - Themes - · - Blog -

    - - -## Table of contents - -- [Quick start](#quick-start) -- [Status](#status) -- [What's included](#whats-included) -- [Bugs and feature requests](#bugs-and-feature-requests) -- [Documentation](#documentation) -- [Contributing](#contributing) -- [Community](#community) -- [Versioning](#versioning) -- [Creators](#creators) -- [Thanks](#thanks) -- [Copyright and license](#copyright-and-license) - - -## Quick start - -Several quick start options are available: - -- [Download the latest release.](https://github.com/twbs/bootstrap/archive/v4.5.3.zip) -- Clone the repo: `git clone https://github.com/twbs/bootstrap.git` -- Install with [npm](https://www.npmjs.com/): `npm install bootstrap` -- Install with [yarn](https://yarnpkg.com/): `yarn add bootstrap@4.5.3` -- Install with [Composer](https://getcomposer.org/): `composer require twbs/bootstrap:4.5.3` -- Install with [NuGet](https://www.nuget.org/): CSS: `Install-Package bootstrap` Sass: `Install-Package bootstrap.sass` - -Read the [Getting started page](https://getbootstrap.com/docs/4.5/getting-started/introduction/) for information on the framework contents, templates and examples, and more. - - -## Status - -[![Slack](https://bootstrap-slack.herokuapp.com/badge.svg)](https://bootstrap-slack.herokuapp.com/) -[![Build Status](https://github.com/twbs/bootstrap/workflows/JS%20Tests/badge.svg?branch=v4-dev)](https://github.com/twbs/bootstrap/actions?query=workflow%3AJS+Tests+branch%3Av4-dev) -[![npm version](https://img.shields.io/npm/v/bootstrap)](https://www.npmjs.com/package/bootstrap) -[![Gem version](https://img.shields.io/gem/v/bootstrap)](https://rubygems.org/gems/bootstrap) -[![Meteor Atmosphere](https://img.shields.io/badge/meteor-twbs%3Abootstrap-blue)](https://atmospherejs.com/twbs/bootstrap) -[![Packagist Prerelease](https://img.shields.io/packagist/vpre/twbs/bootstrap)](https://packagist.org/packages/twbs/bootstrap) -[![NuGet](https://img.shields.io/nuget/vpre/bootstrap)](https://www.nuget.org/packages/bootstrap/absoluteLatest) -[![peerDependencies Status](https://img.shields.io/david/peer/twbs/bootstrap)](https://david-dm.org/twbs/bootstrap?type=peer) -[![devDependency Status](https://img.shields.io/david/dev/twbs/bootstrap)](https://david-dm.org/twbs/bootstrap?type=dev) -[![Coverage Status](https://img.shields.io/coveralls/github/twbs/bootstrap/v4-dev)](https://coveralls.io/github/twbs/bootstrap?branch=v4-dev) -[![CSS gzip size](https://img.badgesize.io/twbs/bootstrap/v4-dev/dist/css/bootstrap.min.css?compression=gzip&label=CSS%20gzip%20size)](https://github.com/twbs/bootstrap/blob/v4-dev/dist/css/bootstrap.min.css) -[![JS gzip size](https://img.badgesize.io/twbs/bootstrap/v4-dev/dist/js/bootstrap.min.js?compression=gzip&label=JS%20gzip%20size)](https://github.com/twbs/bootstrap/blob/v4-dev/dist/js/bootstrap.min.js) -[![BrowserStack Status](https://www.browserstack.com/automate/badge.svg?badge_key=SkxZcStBeExEdVJqQ2hWYnlWckpkNmNEY213SFp6WHFETWk2bGFuY3pCbz0tLXhqbHJsVlZhQnRBdEpod3NLSDMzaHc9PQ==--3d0b75245708616eb93113221beece33e680b229)](https://www.browserstack.com/automate/public-build/SkxZcStBeExEdVJqQ2hWYnlWckpkNmNEY213SFp6WHFETWk2bGFuY3pCbz0tLXhqbHJsVlZhQnRBdEpod3NLSDMzaHc9PQ==--3d0b75245708616eb93113221beece33e680b229) -[![Backers on Open Collective](https://img.shields.io/opencollective/backers/bootstrap)](#backers) -[![Sponsors on Open Collective](https://img.shields.io/opencollective/sponsors/bootstrap)](#sponsors) - - -## What's included - -Within the download you'll find the following directories and files, logically grouping common assets and providing both compiled and minified variations. You'll see something like this: - -```text -bootstrap/ -└── dist/ - ├── css/ - │ ├── bootstrap-grid.css - │ ├── bootstrap-grid.css.map - │ ├── bootstrap-grid.min.css - │ ├── bootstrap-grid.min.css.map - │ ├── bootstrap-reboot.css - │ ├── bootstrap-reboot.css.map - │ ├── bootstrap-reboot.min.css - │ ├── bootstrap-reboot.min.css.map - │ ├── bootstrap.css - │ ├── bootstrap.css.map - │ ├── bootstrap.min.css - │ └── bootstrap.min.css.map - └── js/ - ├── bootstrap.bundle.js - ├── bootstrap.bundle.js.map - ├── bootstrap.bundle.min.js - ├── bootstrap.bundle.min.js.map - ├── bootstrap.js - ├── bootstrap.js.map - ├── bootstrap.min.js - └── bootstrap.min.js.map -``` - -We provide compiled CSS and JS (`bootstrap.*`), as well as compiled and minified CSS and JS (`bootstrap.min.*`). [source maps](https://developers.google.com/web/tools/chrome-devtools/javascript/source-maps) (`bootstrap.*.map`) are available for use with certain browsers' developer tools. Bundled JS files (`bootstrap.bundle.js` and minified `bootstrap.bundle.min.js`) include [Popper](https://popper.js.org/), but not [jQuery](https://jquery.com/). - - -## Bugs and feature requests - -Have a bug or a feature request? Please first read the [issue guidelines](https://github.com/twbs/bootstrap/blob/v4-dev/.github/CONTRIBUTING.md#using-the-issue-tracker) and search for existing and closed issues. If your problem or idea is not addressed yet, [please open a new issue](https://github.com/twbs/bootstrap/issues/new). - - -## Documentation - -Bootstrap's documentation, included in this repo in the root directory, is built with [Jekyll](https://jekyllrb.com/) and publicly hosted on GitHub Pages at . The docs may also be run locally. - -Documentation search is powered by [Algolia's DocSearch](https://community.algolia.com/docsearch/). Working on our search? Be sure to set `debug: true` in `site/docs/4.5/assets/js/src/search.js` file. - -### Running documentation locally - -1. Run through the [tooling setup](https://getbootstrap.com/docs/4.5/getting-started/build-tools/#tooling-setup) to install Jekyll (the site builder) and other Ruby dependencies with `bundle install`. -2. Run `npm install` to install Node.js dependencies. -3. Run `npm start` to compile CSS and JavaScript files, generate our docs, and watch for changes. -4. Open `http://localhost:9001` in your browser, and voilà. - -Learn more about using Jekyll by reading its [documentation](https://jekyllrb.com/docs/). - -### Documentation for previous releases - -You can find all our previous releases docs on . - -[Previous releases](https://github.com/twbs/bootstrap/releases) and their documentation are also available for download. - - -## Contributing - -Please read through our [contributing guidelines](https://github.com/twbs/bootstrap/blob/v4-dev/.github/CONTRIBUTING.md). Included are directions for opening issues, coding standards, and notes on development. - -Moreover, if your pull request contains JavaScript patches or features, you must include [relevant unit tests](https://github.com/twbs/bootstrap/tree/v4-dev/js/tests). All HTML and CSS should conform to the [Code Guide](https://github.com/mdo/code-guide), maintained by [Mark Otto](https://github.com/mdo). - -Editor preferences are available in the [editor config](https://github.com/twbs/bootstrap/blob/v4-dev/.editorconfig) for easy use in common text editors. Read more and download plugins at . - - -## Community - -Get updates on Bootstrap's development and chat with the project maintainers and community members. - -- Follow [@getbootstrap on Twitter](https://twitter.com/getbootstrap). -- Read and subscribe to [The Official Bootstrap Blog](https://blog.getbootstrap.com/). -- Join [the official Slack room](https://bootstrap-slack.herokuapp.com/). -- Chat with fellow Bootstrappers in IRC. On the `irc.freenode.net` server, in the `##bootstrap` channel. -- Implementation help may be found at Stack Overflow (tagged [`bootstrap-4`](https://stackoverflow.com/questions/tagged/bootstrap-4)). -- Developers should use the keyword `bootstrap` on packages which modify or add to the functionality of Bootstrap when distributing through [npm](https://www.npmjs.com/browse/keyword/bootstrap) or similar delivery mechanisms for maximum discoverability. - - -## Versioning - -For transparency into our release cycle and in striving to maintain backward compatibility, Bootstrap is maintained under [the Semantic Versioning guidelines](https://semver.org/). Sometimes we screw up, but we adhere to those rules whenever possible. - -See [the Releases section of our GitHub project](https://github.com/twbs/bootstrap/releases) for changelogs for each release version of Bootstrap. Release announcement posts on [the official Bootstrap blog](https://blog.getbootstrap.com/) contain summaries of the most noteworthy changes made in each release. - - -## Creators - -**Mark Otto** - -- -- - -**Jacob Thornton** - -- -- - - -## Thanks - - - BrowserStack Logo - - -Thanks to [BrowserStack](https://www.browserstack.com/) for providing the infrastructure that allows us to test in real browsers! - - -## Sponsors - -Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/bootstrap#sponsor)] - -[![](https://opencollective.com/bootstrap/sponsor/0/avatar.svg)](https://opencollective.com/bootstrap/sponsor/0/website) -[![](https://opencollective.com/bootstrap/sponsor/1/avatar.svg)](https://opencollective.com/bootstrap/sponsor/1/website) -[![](https://opencollective.com/bootstrap/sponsor/2/avatar.svg)](https://opencollective.com/bootstrap/sponsor/2/website) -[![](https://opencollective.com/bootstrap/sponsor/3/avatar.svg)](https://opencollective.com/bootstrap/sponsor/3/website) -[![](https://opencollective.com/bootstrap/sponsor/4/avatar.svg)](https://opencollective.com/bootstrap/sponsor/4/website) -[![](https://opencollective.com/bootstrap/sponsor/5/avatar.svg)](https://opencollective.com/bootstrap/sponsor/5/website) -[![](https://opencollective.com/bootstrap/sponsor/6/avatar.svg)](https://opencollective.com/bootstrap/sponsor/6/website) -[![](https://opencollective.com/bootstrap/sponsor/7/avatar.svg)](https://opencollective.com/bootstrap/sponsor/7/website) -[![](https://opencollective.com/bootstrap/sponsor/8/avatar.svg)](https://opencollective.com/bootstrap/sponsor/8/website) -[![](https://opencollective.com/bootstrap/sponsor/9/avatar.svg)](https://opencollective.com/bootstrap/sponsor/9/website) - - -## Backers - -Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/bootstrap#backer)] - -[![Backers](https://opencollective.com/bootstrap/backers.svg?width=890)](https://opencollective.com/bootstrap#backers) - - -## Copyright and license - -Code and documentation copyright 2011-2020 the [Bootstrap Authors](https://github.com/twbs/bootstrap/graphs/contributors) and [Twitter, Inc.](https://twitter.com) Code released under the [MIT License](https://github.com/twbs/bootstrap/blob/main/LICENSE). Docs released under [Creative Commons](https://creativecommons.org/licenses/by/3.0/). diff --git a/archive/SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css b/archive/SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css deleted file mode 100644 index 9cfa07ac..00000000 --- a/archive/SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css +++ /dev/null @@ -1,3872 +0,0 @@ -/*! - * Bootstrap Grid v4.5.3 (https://getbootstrap.com/) - * Copyright 2011-2020 The Bootstrap Authors - * Copyright 2011-2020 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - */ -html { - box-sizing: border-box; - -ms-overflow-style: scrollbar; -} - -*, -*::before, -*::after { - box-sizing: inherit; -} - -.container, -.container-fluid, -.container-sm, -.container-md, -.container-lg, -.container-xl { - width: 100%; - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} - -@media (min-width: 576px) { - .container, .container-sm { - max-width: 540px; - } -} - -@media (min-width: 768px) { - .container, .container-sm, .container-md { - max-width: 720px; - } -} - -@media (min-width: 992px) { - .container, .container-sm, .container-md, .container-lg { - max-width: 960px; - } -} - -@media (min-width: 1200px) { - .container, .container-sm, .container-md, .container-lg, .container-xl { - max-width: 1140px; - } -} - -.row { - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - margin-right: -15px; - margin-left: -15px; -} - -.no-gutters { - margin-right: 0; - margin-left: 0; -} - -.no-gutters > .col, -.no-gutters > [class*="col-"] { - padding-right: 0; - padding-left: 0; -} - -.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, -.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, -.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, -.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, -.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl, -.col-xl-auto { - position: relative; - width: 100%; - padding-right: 15px; - padding-left: 15px; -} - -.col { - -ms-flex-preferred-size: 0; - flex-basis: 0; - -ms-flex-positive: 1; - flex-grow: 1; - max-width: 100%; -} - -.row-cols-1 > * { - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100%; -} - -.row-cols-2 > * { - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50%; -} - -.row-cols-3 > * { - -ms-flex: 0 0 33.333333%; - flex: 0 0 33.333333%; - max-width: 33.333333%; -} - -.row-cols-4 > * { - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25%; -} - -.row-cols-5 > * { - -ms-flex: 0 0 20%; - flex: 0 0 20%; - max-width: 20%; -} - -.row-cols-6 > * { - -ms-flex: 0 0 16.666667%; - flex: 0 0 16.666667%; - max-width: 16.666667%; -} - -.col-auto { - -ms-flex: 0 0 auto; - flex: 0 0 auto; - width: auto; - max-width: 100%; -} - -.col-1 { - -ms-flex: 0 0 8.333333%; - flex: 0 0 8.333333%; - max-width: 8.333333%; -} - -.col-2 { - -ms-flex: 0 0 16.666667%; - flex: 0 0 16.666667%; - max-width: 16.666667%; -} - -.col-3 { - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25%; -} - -.col-4 { - -ms-flex: 0 0 33.333333%; - flex: 0 0 33.333333%; - max-width: 33.333333%; -} - -.col-5 { - -ms-flex: 0 0 41.666667%; - flex: 0 0 41.666667%; - max-width: 41.666667%; -} - -.col-6 { - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50%; -} - -.col-7 { - -ms-flex: 0 0 58.333333%; - flex: 0 0 58.333333%; - max-width: 58.333333%; -} - -.col-8 { - -ms-flex: 0 0 66.666667%; - flex: 0 0 66.666667%; - max-width: 66.666667%; -} - -.col-9 { - -ms-flex: 0 0 75%; - flex: 0 0 75%; - max-width: 75%; -} - -.col-10 { - -ms-flex: 0 0 83.333333%; - flex: 0 0 83.333333%; - max-width: 83.333333%; -} - -.col-11 { - -ms-flex: 0 0 91.666667%; - flex: 0 0 91.666667%; - max-width: 91.666667%; -} - -.col-12 { - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100%; -} - -.order-first { - -ms-flex-order: -1; - order: -1; -} - -.order-last { - -ms-flex-order: 13; - order: 13; -} - -.order-0 { - -ms-flex-order: 0; - order: 0; -} - -.order-1 { - -ms-flex-order: 1; - order: 1; -} - -.order-2 { - -ms-flex-order: 2; - order: 2; -} - -.order-3 { - -ms-flex-order: 3; - order: 3; -} - -.order-4 { - -ms-flex-order: 4; - order: 4; -} - -.order-5 { - -ms-flex-order: 5; - order: 5; -} - -.order-6 { - -ms-flex-order: 6; - order: 6; -} - -.order-7 { - -ms-flex-order: 7; - order: 7; -} - -.order-8 { - -ms-flex-order: 8; - order: 8; -} - -.order-9 { - -ms-flex-order: 9; - order: 9; -} - -.order-10 { - -ms-flex-order: 10; - order: 10; -} - -.order-11 { - -ms-flex-order: 11; - order: 11; -} - -.order-12 { - -ms-flex-order: 12; - order: 12; -} - -.offset-1 { - margin-left: 8.333333%; -} - -.offset-2 { - margin-left: 16.666667%; -} - -.offset-3 { - margin-left: 25%; -} - -.offset-4 { - margin-left: 33.333333%; -} - -.offset-5 { - margin-left: 41.666667%; -} - -.offset-6 { - margin-left: 50%; -} - -.offset-7 { - margin-left: 58.333333%; -} - -.offset-8 { - margin-left: 66.666667%; -} - -.offset-9 { - margin-left: 75%; -} - -.offset-10 { - margin-left: 83.333333%; -} - -.offset-11 { - margin-left: 91.666667%; -} - -@media (min-width: 576px) { - .col-sm { - -ms-flex-preferred-size: 0; - flex-basis: 0; - -ms-flex-positive: 1; - flex-grow: 1; - max-width: 100%; - } - .row-cols-sm-1 > * { - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100%; - } - .row-cols-sm-2 > * { - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50%; - } - .row-cols-sm-3 > * { - -ms-flex: 0 0 33.333333%; - flex: 0 0 33.333333%; - max-width: 33.333333%; - } - .row-cols-sm-4 > * { - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25%; - } - .row-cols-sm-5 > * { - -ms-flex: 0 0 20%; - flex: 0 0 20%; - max-width: 20%; - } - .row-cols-sm-6 > * { - -ms-flex: 0 0 16.666667%; - flex: 0 0 16.666667%; - max-width: 16.666667%; - } - .col-sm-auto { - -ms-flex: 0 0 auto; - flex: 0 0 auto; - width: auto; - max-width: 100%; - } - .col-sm-1 { - -ms-flex: 0 0 8.333333%; - flex: 0 0 8.333333%; - max-width: 8.333333%; - } - .col-sm-2 { - -ms-flex: 0 0 16.666667%; - flex: 0 0 16.666667%; - max-width: 16.666667%; - } - .col-sm-3 { - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25%; - } - .col-sm-4 { - -ms-flex: 0 0 33.333333%; - flex: 0 0 33.333333%; - max-width: 33.333333%; - } - .col-sm-5 { - -ms-flex: 0 0 41.666667%; - flex: 0 0 41.666667%; - max-width: 41.666667%; - } - .col-sm-6 { - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50%; - } - .col-sm-7 { - -ms-flex: 0 0 58.333333%; - flex: 0 0 58.333333%; - max-width: 58.333333%; - } - .col-sm-8 { - -ms-flex: 0 0 66.666667%; - flex: 0 0 66.666667%; - max-width: 66.666667%; - } - .col-sm-9 { - -ms-flex: 0 0 75%; - flex: 0 0 75%; - max-width: 75%; - } - .col-sm-10 { - -ms-flex: 0 0 83.333333%; - flex: 0 0 83.333333%; - max-width: 83.333333%; - } - .col-sm-11 { - -ms-flex: 0 0 91.666667%; - flex: 0 0 91.666667%; - max-width: 91.666667%; - } - .col-sm-12 { - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100%; - } - .order-sm-first { - -ms-flex-order: -1; - order: -1; - } - .order-sm-last { - -ms-flex-order: 13; - order: 13; - } - .order-sm-0 { - -ms-flex-order: 0; - order: 0; - } - .order-sm-1 { - -ms-flex-order: 1; - order: 1; - } - .order-sm-2 { - -ms-flex-order: 2; - order: 2; - } - .order-sm-3 { - -ms-flex-order: 3; - order: 3; - } - .order-sm-4 { - -ms-flex-order: 4; - order: 4; - } - .order-sm-5 { - -ms-flex-order: 5; - order: 5; - } - .order-sm-6 { - -ms-flex-order: 6; - order: 6; - } - .order-sm-7 { - -ms-flex-order: 7; - order: 7; - } - .order-sm-8 { - -ms-flex-order: 8; - order: 8; - } - .order-sm-9 { - -ms-flex-order: 9; - order: 9; - } - .order-sm-10 { - -ms-flex-order: 10; - order: 10; - } - .order-sm-11 { - -ms-flex-order: 11; - order: 11; - } - .order-sm-12 { - -ms-flex-order: 12; - order: 12; - } - .offset-sm-0 { - margin-left: 0; - } - .offset-sm-1 { - margin-left: 8.333333%; - } - .offset-sm-2 { - margin-left: 16.666667%; - } - .offset-sm-3 { - margin-left: 25%; - } - .offset-sm-4 { - margin-left: 33.333333%; - } - .offset-sm-5 { - margin-left: 41.666667%; - } - .offset-sm-6 { - margin-left: 50%; - } - .offset-sm-7 { - margin-left: 58.333333%; - } - .offset-sm-8 { - margin-left: 66.666667%; - } - .offset-sm-9 { - margin-left: 75%; - } - .offset-sm-10 { - margin-left: 83.333333%; - } - .offset-sm-11 { - margin-left: 91.666667%; - } -} - -@media (min-width: 768px) { - .col-md { - -ms-flex-preferred-size: 0; - flex-basis: 0; - -ms-flex-positive: 1; - flex-grow: 1; - max-width: 100%; - } - .row-cols-md-1 > * { - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100%; - } - .row-cols-md-2 > * { - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50%; - } - .row-cols-md-3 > * { - -ms-flex: 0 0 33.333333%; - flex: 0 0 33.333333%; - max-width: 33.333333%; - } - .row-cols-md-4 > * { - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25%; - } - .row-cols-md-5 > * { - -ms-flex: 0 0 20%; - flex: 0 0 20%; - max-width: 20%; - } - .row-cols-md-6 > * { - -ms-flex: 0 0 16.666667%; - flex: 0 0 16.666667%; - max-width: 16.666667%; - } - .col-md-auto { - -ms-flex: 0 0 auto; - flex: 0 0 auto; - width: auto; - max-width: 100%; - } - .col-md-1 { - -ms-flex: 0 0 8.333333%; - flex: 0 0 8.333333%; - max-width: 8.333333%; - } - .col-md-2 { - -ms-flex: 0 0 16.666667%; - flex: 0 0 16.666667%; - max-width: 16.666667%; - } - .col-md-3 { - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25%; - } - .col-md-4 { - -ms-flex: 0 0 33.333333%; - flex: 0 0 33.333333%; - max-width: 33.333333%; - } - .col-md-5 { - -ms-flex: 0 0 41.666667%; - flex: 0 0 41.666667%; - max-width: 41.666667%; - } - .col-md-6 { - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50%; - } - .col-md-7 { - -ms-flex: 0 0 58.333333%; - flex: 0 0 58.333333%; - max-width: 58.333333%; - } - .col-md-8 { - -ms-flex: 0 0 66.666667%; - flex: 0 0 66.666667%; - max-width: 66.666667%; - } - .col-md-9 { - -ms-flex: 0 0 75%; - flex: 0 0 75%; - max-width: 75%; - } - .col-md-10 { - -ms-flex: 0 0 83.333333%; - flex: 0 0 83.333333%; - max-width: 83.333333%; - } - .col-md-11 { - -ms-flex: 0 0 91.666667%; - flex: 0 0 91.666667%; - max-width: 91.666667%; - } - .col-md-12 { - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100%; - } - .order-md-first { - -ms-flex-order: -1; - order: -1; - } - .order-md-last { - -ms-flex-order: 13; - order: 13; - } - .order-md-0 { - -ms-flex-order: 0; - order: 0; - } - .order-md-1 { - -ms-flex-order: 1; - order: 1; - } - .order-md-2 { - -ms-flex-order: 2; - order: 2; - } - .order-md-3 { - -ms-flex-order: 3; - order: 3; - } - .order-md-4 { - -ms-flex-order: 4; - order: 4; - } - .order-md-5 { - -ms-flex-order: 5; - order: 5; - } - .order-md-6 { - -ms-flex-order: 6; - order: 6; - } - .order-md-7 { - -ms-flex-order: 7; - order: 7; - } - .order-md-8 { - -ms-flex-order: 8; - order: 8; - } - .order-md-9 { - -ms-flex-order: 9; - order: 9; - } - .order-md-10 { - -ms-flex-order: 10; - order: 10; - } - .order-md-11 { - -ms-flex-order: 11; - order: 11; - } - .order-md-12 { - -ms-flex-order: 12; - order: 12; - } - .offset-md-0 { - margin-left: 0; - } - .offset-md-1 { - margin-left: 8.333333%; - } - .offset-md-2 { - margin-left: 16.666667%; - } - .offset-md-3 { - margin-left: 25%; - } - .offset-md-4 { - margin-left: 33.333333%; - } - .offset-md-5 { - margin-left: 41.666667%; - } - .offset-md-6 { - margin-left: 50%; - } - .offset-md-7 { - margin-left: 58.333333%; - } - .offset-md-8 { - margin-left: 66.666667%; - } - .offset-md-9 { - margin-left: 75%; - } - .offset-md-10 { - margin-left: 83.333333%; - } - .offset-md-11 { - margin-left: 91.666667%; - } -} - -@media (min-width: 992px) { - .col-lg { - -ms-flex-preferred-size: 0; - flex-basis: 0; - -ms-flex-positive: 1; - flex-grow: 1; - max-width: 100%; - } - .row-cols-lg-1 > * { - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100%; - } - .row-cols-lg-2 > * { - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50%; - } - .row-cols-lg-3 > * { - -ms-flex: 0 0 33.333333%; - flex: 0 0 33.333333%; - max-width: 33.333333%; - } - .row-cols-lg-4 > * { - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25%; - } - .row-cols-lg-5 > * { - -ms-flex: 0 0 20%; - flex: 0 0 20%; - max-width: 20%; - } - .row-cols-lg-6 > * { - -ms-flex: 0 0 16.666667%; - flex: 0 0 16.666667%; - max-width: 16.666667%; - } - .col-lg-auto { - -ms-flex: 0 0 auto; - flex: 0 0 auto; - width: auto; - max-width: 100%; - } - .col-lg-1 { - -ms-flex: 0 0 8.333333%; - flex: 0 0 8.333333%; - max-width: 8.333333%; - } - .col-lg-2 { - -ms-flex: 0 0 16.666667%; - flex: 0 0 16.666667%; - max-width: 16.666667%; - } - .col-lg-3 { - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25%; - } - .col-lg-4 { - -ms-flex: 0 0 33.333333%; - flex: 0 0 33.333333%; - max-width: 33.333333%; - } - .col-lg-5 { - -ms-flex: 0 0 41.666667%; - flex: 0 0 41.666667%; - max-width: 41.666667%; - } - .col-lg-6 { - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50%; - } - .col-lg-7 { - -ms-flex: 0 0 58.333333%; - flex: 0 0 58.333333%; - max-width: 58.333333%; - } - .col-lg-8 { - -ms-flex: 0 0 66.666667%; - flex: 0 0 66.666667%; - max-width: 66.666667%; - } - .col-lg-9 { - -ms-flex: 0 0 75%; - flex: 0 0 75%; - max-width: 75%; - } - .col-lg-10 { - -ms-flex: 0 0 83.333333%; - flex: 0 0 83.333333%; - max-width: 83.333333%; - } - .col-lg-11 { - -ms-flex: 0 0 91.666667%; - flex: 0 0 91.666667%; - max-width: 91.666667%; - } - .col-lg-12 { - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100%; - } - .order-lg-first { - -ms-flex-order: -1; - order: -1; - } - .order-lg-last { - -ms-flex-order: 13; - order: 13; - } - .order-lg-0 { - -ms-flex-order: 0; - order: 0; - } - .order-lg-1 { - -ms-flex-order: 1; - order: 1; - } - .order-lg-2 { - -ms-flex-order: 2; - order: 2; - } - .order-lg-3 { - -ms-flex-order: 3; - order: 3; - } - .order-lg-4 { - -ms-flex-order: 4; - order: 4; - } - .order-lg-5 { - -ms-flex-order: 5; - order: 5; - } - .order-lg-6 { - -ms-flex-order: 6; - order: 6; - } - .order-lg-7 { - -ms-flex-order: 7; - order: 7; - } - .order-lg-8 { - -ms-flex-order: 8; - order: 8; - } - .order-lg-9 { - -ms-flex-order: 9; - order: 9; - } - .order-lg-10 { - -ms-flex-order: 10; - order: 10; - } - .order-lg-11 { - -ms-flex-order: 11; - order: 11; - } - .order-lg-12 { - -ms-flex-order: 12; - order: 12; - } - .offset-lg-0 { - margin-left: 0; - } - .offset-lg-1 { - margin-left: 8.333333%; - } - .offset-lg-2 { - margin-left: 16.666667%; - } - .offset-lg-3 { - margin-left: 25%; - } - .offset-lg-4 { - margin-left: 33.333333%; - } - .offset-lg-5 { - margin-left: 41.666667%; - } - .offset-lg-6 { - margin-left: 50%; - } - .offset-lg-7 { - margin-left: 58.333333%; - } - .offset-lg-8 { - margin-left: 66.666667%; - } - .offset-lg-9 { - margin-left: 75%; - } - .offset-lg-10 { - margin-left: 83.333333%; - } - .offset-lg-11 { - margin-left: 91.666667%; - } -} - -@media (min-width: 1200px) { - .col-xl { - -ms-flex-preferred-size: 0; - flex-basis: 0; - -ms-flex-positive: 1; - flex-grow: 1; - max-width: 100%; - } - .row-cols-xl-1 > * { - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100%; - } - .row-cols-xl-2 > * { - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50%; - } - .row-cols-xl-3 > * { - -ms-flex: 0 0 33.333333%; - flex: 0 0 33.333333%; - max-width: 33.333333%; - } - .row-cols-xl-4 > * { - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25%; - } - .row-cols-xl-5 > * { - -ms-flex: 0 0 20%; - flex: 0 0 20%; - max-width: 20%; - } - .row-cols-xl-6 > * { - -ms-flex: 0 0 16.666667%; - flex: 0 0 16.666667%; - max-width: 16.666667%; - } - .col-xl-auto { - -ms-flex: 0 0 auto; - flex: 0 0 auto; - width: auto; - max-width: 100%; - } - .col-xl-1 { - -ms-flex: 0 0 8.333333%; - flex: 0 0 8.333333%; - max-width: 8.333333%; - } - .col-xl-2 { - -ms-flex: 0 0 16.666667%; - flex: 0 0 16.666667%; - max-width: 16.666667%; - } - .col-xl-3 { - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25%; - } - .col-xl-4 { - -ms-flex: 0 0 33.333333%; - flex: 0 0 33.333333%; - max-width: 33.333333%; - } - .col-xl-5 { - -ms-flex: 0 0 41.666667%; - flex: 0 0 41.666667%; - max-width: 41.666667%; - } - .col-xl-6 { - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50%; - } - .col-xl-7 { - -ms-flex: 0 0 58.333333%; - flex: 0 0 58.333333%; - max-width: 58.333333%; - } - .col-xl-8 { - -ms-flex: 0 0 66.666667%; - flex: 0 0 66.666667%; - max-width: 66.666667%; - } - .col-xl-9 { - -ms-flex: 0 0 75%; - flex: 0 0 75%; - max-width: 75%; - } - .col-xl-10 { - -ms-flex: 0 0 83.333333%; - flex: 0 0 83.333333%; - max-width: 83.333333%; - } - .col-xl-11 { - -ms-flex: 0 0 91.666667%; - flex: 0 0 91.666667%; - max-width: 91.666667%; - } - .col-xl-12 { - -ms-flex: 0 0 100%; - flex: 0 0 100%; - max-width: 100%; - } - .order-xl-first { - -ms-flex-order: -1; - order: -1; - } - .order-xl-last { - -ms-flex-order: 13; - order: 13; - } - .order-xl-0 { - -ms-flex-order: 0; - order: 0; - } - .order-xl-1 { - -ms-flex-order: 1; - order: 1; - } - .order-xl-2 { - -ms-flex-order: 2; - order: 2; - } - .order-xl-3 { - -ms-flex-order: 3; - order: 3; - } - .order-xl-4 { - -ms-flex-order: 4; - order: 4; - } - .order-xl-5 { - -ms-flex-order: 5; - order: 5; - } - .order-xl-6 { - -ms-flex-order: 6; - order: 6; - } - .order-xl-7 { - -ms-flex-order: 7; - order: 7; - } - .order-xl-8 { - -ms-flex-order: 8; - order: 8; - } - .order-xl-9 { - -ms-flex-order: 9; - order: 9; - } - .order-xl-10 { - -ms-flex-order: 10; - order: 10; - } - .order-xl-11 { - -ms-flex-order: 11; - order: 11; - } - .order-xl-12 { - -ms-flex-order: 12; - order: 12; - } - .offset-xl-0 { - margin-left: 0; - } - .offset-xl-1 { - margin-left: 8.333333%; - } - .offset-xl-2 { - margin-left: 16.666667%; - } - .offset-xl-3 { - margin-left: 25%; - } - .offset-xl-4 { - margin-left: 33.333333%; - } - .offset-xl-5 { - margin-left: 41.666667%; - } - .offset-xl-6 { - margin-left: 50%; - } - .offset-xl-7 { - margin-left: 58.333333%; - } - .offset-xl-8 { - margin-left: 66.666667%; - } - .offset-xl-9 { - margin-left: 75%; - } - .offset-xl-10 { - margin-left: 83.333333%; - } - .offset-xl-11 { - margin-left: 91.666667%; - } -} - -.d-none { - display: none !important; -} - -.d-inline { - display: inline !important; -} - -.d-inline-block { - display: inline-block !important; -} - -.d-block { - display: block !important; -} - -.d-table { - display: table !important; -} - -.d-table-row { - display: table-row !important; -} - -.d-table-cell { - display: table-cell !important; -} - -.d-flex { - display: -ms-flexbox !important; - display: flex !important; -} - -.d-inline-flex { - display: -ms-inline-flexbox !important; - display: inline-flex !important; -} - -@media (min-width: 576px) { - .d-sm-none { - display: none !important; - } - .d-sm-inline { - display: inline !important; - } - .d-sm-inline-block { - display: inline-block !important; - } - .d-sm-block { - display: block !important; - } - .d-sm-table { - display: table !important; - } - .d-sm-table-row { - display: table-row !important; - } - .d-sm-table-cell { - display: table-cell !important; - } - .d-sm-flex { - display: -ms-flexbox !important; - display: flex !important; - } - .d-sm-inline-flex { - display: -ms-inline-flexbox !important; - display: inline-flex !important; - } -} - -@media (min-width: 768px) { - .d-md-none { - display: none !important; - } - .d-md-inline { - display: inline !important; - } - .d-md-inline-block { - display: inline-block !important; - } - .d-md-block { - display: block !important; - } - .d-md-table { - display: table !important; - } - .d-md-table-row { - display: table-row !important; - } - .d-md-table-cell { - display: table-cell !important; - } - .d-md-flex { - display: -ms-flexbox !important; - display: flex !important; - } - .d-md-inline-flex { - display: -ms-inline-flexbox !important; - display: inline-flex !important; - } -} - -@media (min-width: 992px) { - .d-lg-none { - display: none !important; - } - .d-lg-inline { - display: inline !important; - } - .d-lg-inline-block { - display: inline-block !important; - } - .d-lg-block { - display: block !important; - } - .d-lg-table { - display: table !important; - } - .d-lg-table-row { - display: table-row !important; - } - .d-lg-table-cell { - display: table-cell !important; - } - .d-lg-flex { - display: -ms-flexbox !important; - display: flex !important; - } - .d-lg-inline-flex { - display: -ms-inline-flexbox !important; - display: inline-flex !important; - } -} - -@media (min-width: 1200px) { - .d-xl-none { - display: none !important; - } - .d-xl-inline { - display: inline !important; - } - .d-xl-inline-block { - display: inline-block !important; - } - .d-xl-block { - display: block !important; - } - .d-xl-table { - display: table !important; - } - .d-xl-table-row { - display: table-row !important; - } - .d-xl-table-cell { - display: table-cell !important; - } - .d-xl-flex { - display: -ms-flexbox !important; - display: flex !important; - } - .d-xl-inline-flex { - display: -ms-inline-flexbox !important; - display: inline-flex !important; - } -} - -@media print { - .d-print-none { - display: none !important; - } - .d-print-inline { - display: inline !important; - } - .d-print-inline-block { - display: inline-block !important; - } - .d-print-block { - display: block !important; - } - .d-print-table { - display: table !important; - } - .d-print-table-row { - display: table-row !important; - } - .d-print-table-cell { - display: table-cell !important; - } - .d-print-flex { - display: -ms-flexbox !important; - display: flex !important; - } - .d-print-inline-flex { - display: -ms-inline-flexbox !important; - display: inline-flex !important; - } -} - -.flex-row { - -ms-flex-direction: row !important; - flex-direction: row !important; -} - -.flex-column { - -ms-flex-direction: column !important; - flex-direction: column !important; -} - -.flex-row-reverse { - -ms-flex-direction: row-reverse !important; - flex-direction: row-reverse !important; -} - -.flex-column-reverse { - -ms-flex-direction: column-reverse !important; - flex-direction: column-reverse !important; -} - -.flex-wrap { - -ms-flex-wrap: wrap !important; - flex-wrap: wrap !important; -} - -.flex-nowrap { - -ms-flex-wrap: nowrap !important; - flex-wrap: nowrap !important; -} - -.flex-wrap-reverse { - -ms-flex-wrap: wrap-reverse !important; - flex-wrap: wrap-reverse !important; -} - -.flex-fill { - -ms-flex: 1 1 auto !important; - flex: 1 1 auto !important; -} - -.flex-grow-0 { - -ms-flex-positive: 0 !important; - flex-grow: 0 !important; -} - -.flex-grow-1 { - -ms-flex-positive: 1 !important; - flex-grow: 1 !important; -} - -.flex-shrink-0 { - -ms-flex-negative: 0 !important; - flex-shrink: 0 !important; -} - -.flex-shrink-1 { - -ms-flex-negative: 1 !important; - flex-shrink: 1 !important; -} - -.justify-content-start { - -ms-flex-pack: start !important; - justify-content: flex-start !important; -} - -.justify-content-end { - -ms-flex-pack: end !important; - justify-content: flex-end !important; -} - -.justify-content-center { - -ms-flex-pack: center !important; - justify-content: center !important; -} - -.justify-content-between { - -ms-flex-pack: justify !important; - justify-content: space-between !important; -} - -.justify-content-around { - -ms-flex-pack: distribute !important; - justify-content: space-around !important; -} - -.align-items-start { - -ms-flex-align: start !important; - align-items: flex-start !important; -} - -.align-items-end { - -ms-flex-align: end !important; - align-items: flex-end !important; -} - -.align-items-center { - -ms-flex-align: center !important; - align-items: center !important; -} - -.align-items-baseline { - -ms-flex-align: baseline !important; - align-items: baseline !important; -} - -.align-items-stretch { - -ms-flex-align: stretch !important; - align-items: stretch !important; -} - -.align-content-start { - -ms-flex-line-pack: start !important; - align-content: flex-start !important; -} - -.align-content-end { - -ms-flex-line-pack: end !important; - align-content: flex-end !important; -} - -.align-content-center { - -ms-flex-line-pack: center !important; - align-content: center !important; -} - -.align-content-between { - -ms-flex-line-pack: justify !important; - align-content: space-between !important; -} - -.align-content-around { - -ms-flex-line-pack: distribute !important; - align-content: space-around !important; -} - -.align-content-stretch { - -ms-flex-line-pack: stretch !important; - align-content: stretch !important; -} - -.align-self-auto { - -ms-flex-item-align: auto !important; - align-self: auto !important; -} - -.align-self-start { - -ms-flex-item-align: start !important; - align-self: flex-start !important; -} - -.align-self-end { - -ms-flex-item-align: end !important; - align-self: flex-end !important; -} - -.align-self-center { - -ms-flex-item-align: center !important; - align-self: center !important; -} - -.align-self-baseline { - -ms-flex-item-align: baseline !important; - align-self: baseline !important; -} - -.align-self-stretch { - -ms-flex-item-align: stretch !important; - align-self: stretch !important; -} - -@media (min-width: 576px) { - .flex-sm-row { - -ms-flex-direction: row !important; - flex-direction: row !important; - } - .flex-sm-column { - -ms-flex-direction: column !important; - flex-direction: column !important; - } - .flex-sm-row-reverse { - -ms-flex-direction: row-reverse !important; - flex-direction: row-reverse !important; - } - .flex-sm-column-reverse { - -ms-flex-direction: column-reverse !important; - flex-direction: column-reverse !important; - } - .flex-sm-wrap { - -ms-flex-wrap: wrap !important; - flex-wrap: wrap !important; - } - .flex-sm-nowrap { - -ms-flex-wrap: nowrap !important; - flex-wrap: nowrap !important; - } - .flex-sm-wrap-reverse { - -ms-flex-wrap: wrap-reverse !important; - flex-wrap: wrap-reverse !important; - } - .flex-sm-fill { - -ms-flex: 1 1 auto !important; - flex: 1 1 auto !important; - } - .flex-sm-grow-0 { - -ms-flex-positive: 0 !important; - flex-grow: 0 !important; - } - .flex-sm-grow-1 { - -ms-flex-positive: 1 !important; - flex-grow: 1 !important; - } - .flex-sm-shrink-0 { - -ms-flex-negative: 0 !important; - flex-shrink: 0 !important; - } - .flex-sm-shrink-1 { - -ms-flex-negative: 1 !important; - flex-shrink: 1 !important; - } - .justify-content-sm-start { - -ms-flex-pack: start !important; - justify-content: flex-start !important; - } - .justify-content-sm-end { - -ms-flex-pack: end !important; - justify-content: flex-end !important; - } - .justify-content-sm-center { - -ms-flex-pack: center !important; - justify-content: center !important; - } - .justify-content-sm-between { - -ms-flex-pack: justify !important; - justify-content: space-between !important; - } - .justify-content-sm-around { - -ms-flex-pack: distribute !important; - justify-content: space-around !important; - } - .align-items-sm-start { - -ms-flex-align: start !important; - align-items: flex-start !important; - } - .align-items-sm-end { - -ms-flex-align: end !important; - align-items: flex-end !important; - } - .align-items-sm-center { - -ms-flex-align: center !important; - align-items: center !important; - } - .align-items-sm-baseline { - -ms-flex-align: baseline !important; - align-items: baseline !important; - } - .align-items-sm-stretch { - -ms-flex-align: stretch !important; - align-items: stretch !important; - } - .align-content-sm-start { - -ms-flex-line-pack: start !important; - align-content: flex-start !important; - } - .align-content-sm-end { - -ms-flex-line-pack: end !important; - align-content: flex-end !important; - } - .align-content-sm-center { - -ms-flex-line-pack: center !important; - align-content: center !important; - } - .align-content-sm-between { - -ms-flex-line-pack: justify !important; - align-content: space-between !important; - } - .align-content-sm-around { - -ms-flex-line-pack: distribute !important; - align-content: space-around !important; - } - .align-content-sm-stretch { - -ms-flex-line-pack: stretch !important; - align-content: stretch !important; - } - .align-self-sm-auto { - -ms-flex-item-align: auto !important; - align-self: auto !important; - } - .align-self-sm-start { - -ms-flex-item-align: start !important; - align-self: flex-start !important; - } - .align-self-sm-end { - -ms-flex-item-align: end !important; - align-self: flex-end !important; - } - .align-self-sm-center { - -ms-flex-item-align: center !important; - align-self: center !important; - } - .align-self-sm-baseline { - -ms-flex-item-align: baseline !important; - align-self: baseline !important; - } - .align-self-sm-stretch { - -ms-flex-item-align: stretch !important; - align-self: stretch !important; - } -} - -@media (min-width: 768px) { - .flex-md-row { - -ms-flex-direction: row !important; - flex-direction: row !important; - } - .flex-md-column { - -ms-flex-direction: column !important; - flex-direction: column !important; - } - .flex-md-row-reverse { - -ms-flex-direction: row-reverse !important; - flex-direction: row-reverse !important; - } - .flex-md-column-reverse { - -ms-flex-direction: column-reverse !important; - flex-direction: column-reverse !important; - } - .flex-md-wrap { - -ms-flex-wrap: wrap !important; - flex-wrap: wrap !important; - } - .flex-md-nowrap { - -ms-flex-wrap: nowrap !important; - flex-wrap: nowrap !important; - } - .flex-md-wrap-reverse { - -ms-flex-wrap: wrap-reverse !important; - flex-wrap: wrap-reverse !important; - } - .flex-md-fill { - -ms-flex: 1 1 auto !important; - flex: 1 1 auto !important; - } - .flex-md-grow-0 { - -ms-flex-positive: 0 !important; - flex-grow: 0 !important; - } - .flex-md-grow-1 { - -ms-flex-positive: 1 !important; - flex-grow: 1 !important; - } - .flex-md-shrink-0 { - -ms-flex-negative: 0 !important; - flex-shrink: 0 !important; - } - .flex-md-shrink-1 { - -ms-flex-negative: 1 !important; - flex-shrink: 1 !important; - } - .justify-content-md-start { - -ms-flex-pack: start !important; - justify-content: flex-start !important; - } - .justify-content-md-end { - -ms-flex-pack: end !important; - justify-content: flex-end !important; - } - .justify-content-md-center { - -ms-flex-pack: center !important; - justify-content: center !important; - } - .justify-content-md-between { - -ms-flex-pack: justify !important; - justify-content: space-between !important; - } - .justify-content-md-around { - -ms-flex-pack: distribute !important; - justify-content: space-around !important; - } - .align-items-md-start { - -ms-flex-align: start !important; - align-items: flex-start !important; - } - .align-items-md-end { - -ms-flex-align: end !important; - align-items: flex-end !important; - } - .align-items-md-center { - -ms-flex-align: center !important; - align-items: center !important; - } - .align-items-md-baseline { - -ms-flex-align: baseline !important; - align-items: baseline !important; - } - .align-items-md-stretch { - -ms-flex-align: stretch !important; - align-items: stretch !important; - } - .align-content-md-start { - -ms-flex-line-pack: start !important; - align-content: flex-start !important; - } - .align-content-md-end { - -ms-flex-line-pack: end !important; - align-content: flex-end !important; - } - .align-content-md-center { - -ms-flex-line-pack: center !important; - align-content: center !important; - } - .align-content-md-between { - -ms-flex-line-pack: justify !important; - align-content: space-between !important; - } - .align-content-md-around { - -ms-flex-line-pack: distribute !important; - align-content: space-around !important; - } - .align-content-md-stretch { - -ms-flex-line-pack: stretch !important; - align-content: stretch !important; - } - .align-self-md-auto { - -ms-flex-item-align: auto !important; - align-self: auto !important; - } - .align-self-md-start { - -ms-flex-item-align: start !important; - align-self: flex-start !important; - } - .align-self-md-end { - -ms-flex-item-align: end !important; - align-self: flex-end !important; - } - .align-self-md-center { - -ms-flex-item-align: center !important; - align-self: center !important; - } - .align-self-md-baseline { - -ms-flex-item-align: baseline !important; - align-self: baseline !important; - } - .align-self-md-stretch { - -ms-flex-item-align: stretch !important; - align-self: stretch !important; - } -} - -@media (min-width: 992px) { - .flex-lg-row { - -ms-flex-direction: row !important; - flex-direction: row !important; - } - .flex-lg-column { - -ms-flex-direction: column !important; - flex-direction: column !important; - } - .flex-lg-row-reverse { - -ms-flex-direction: row-reverse !important; - flex-direction: row-reverse !important; - } - .flex-lg-column-reverse { - -ms-flex-direction: column-reverse !important; - flex-direction: column-reverse !important; - } - .flex-lg-wrap { - -ms-flex-wrap: wrap !important; - flex-wrap: wrap !important; - } - .flex-lg-nowrap { - -ms-flex-wrap: nowrap !important; - flex-wrap: nowrap !important; - } - .flex-lg-wrap-reverse { - -ms-flex-wrap: wrap-reverse !important; - flex-wrap: wrap-reverse !important; - } - .flex-lg-fill { - -ms-flex: 1 1 auto !important; - flex: 1 1 auto !important; - } - .flex-lg-grow-0 { - -ms-flex-positive: 0 !important; - flex-grow: 0 !important; - } - .flex-lg-grow-1 { - -ms-flex-positive: 1 !important; - flex-grow: 1 !important; - } - .flex-lg-shrink-0 { - -ms-flex-negative: 0 !important; - flex-shrink: 0 !important; - } - .flex-lg-shrink-1 { - -ms-flex-negative: 1 !important; - flex-shrink: 1 !important; - } - .justify-content-lg-start { - -ms-flex-pack: start !important; - justify-content: flex-start !important; - } - .justify-content-lg-end { - -ms-flex-pack: end !important; - justify-content: flex-end !important; - } - .justify-content-lg-center { - -ms-flex-pack: center !important; - justify-content: center !important; - } - .justify-content-lg-between { - -ms-flex-pack: justify !important; - justify-content: space-between !important; - } - .justify-content-lg-around { - -ms-flex-pack: distribute !important; - justify-content: space-around !important; - } - .align-items-lg-start { - -ms-flex-align: start !important; - align-items: flex-start !important; - } - .align-items-lg-end { - -ms-flex-align: end !important; - align-items: flex-end !important; - } - .align-items-lg-center { - -ms-flex-align: center !important; - align-items: center !important; - } - .align-items-lg-baseline { - -ms-flex-align: baseline !important; - align-items: baseline !important; - } - .align-items-lg-stretch { - -ms-flex-align: stretch !important; - align-items: stretch !important; - } - .align-content-lg-start { - -ms-flex-line-pack: start !important; - align-content: flex-start !important; - } - .align-content-lg-end { - -ms-flex-line-pack: end !important; - align-content: flex-end !important; - } - .align-content-lg-center { - -ms-flex-line-pack: center !important; - align-content: center !important; - } - .align-content-lg-between { - -ms-flex-line-pack: justify !important; - align-content: space-between !important; - } - .align-content-lg-around { - -ms-flex-line-pack: distribute !important; - align-content: space-around !important; - } - .align-content-lg-stretch { - -ms-flex-line-pack: stretch !important; - align-content: stretch !important; - } - .align-self-lg-auto { - -ms-flex-item-align: auto !important; - align-self: auto !important; - } - .align-self-lg-start { - -ms-flex-item-align: start !important; - align-self: flex-start !important; - } - .align-self-lg-end { - -ms-flex-item-align: end !important; - align-self: flex-end !important; - } - .align-self-lg-center { - -ms-flex-item-align: center !important; - align-self: center !important; - } - .align-self-lg-baseline { - -ms-flex-item-align: baseline !important; - align-self: baseline !important; - } - .align-self-lg-stretch { - -ms-flex-item-align: stretch !important; - align-self: stretch !important; - } -} - -@media (min-width: 1200px) { - .flex-xl-row { - -ms-flex-direction: row !important; - flex-direction: row !important; - } - .flex-xl-column { - -ms-flex-direction: column !important; - flex-direction: column !important; - } - .flex-xl-row-reverse { - -ms-flex-direction: row-reverse !important; - flex-direction: row-reverse !important; - } - .flex-xl-column-reverse { - -ms-flex-direction: column-reverse !important; - flex-direction: column-reverse !important; - } - .flex-xl-wrap { - -ms-flex-wrap: wrap !important; - flex-wrap: wrap !important; - } - .flex-xl-nowrap { - -ms-flex-wrap: nowrap !important; - flex-wrap: nowrap !important; - } - .flex-xl-wrap-reverse { - -ms-flex-wrap: wrap-reverse !important; - flex-wrap: wrap-reverse !important; - } - .flex-xl-fill { - -ms-flex: 1 1 auto !important; - flex: 1 1 auto !important; - } - .flex-xl-grow-0 { - -ms-flex-positive: 0 !important; - flex-grow: 0 !important; - } - .flex-xl-grow-1 { - -ms-flex-positive: 1 !important; - flex-grow: 1 !important; - } - .flex-xl-shrink-0 { - -ms-flex-negative: 0 !important; - flex-shrink: 0 !important; - } - .flex-xl-shrink-1 { - -ms-flex-negative: 1 !important; - flex-shrink: 1 !important; - } - .justify-content-xl-start { - -ms-flex-pack: start !important; - justify-content: flex-start !important; - } - .justify-content-xl-end { - -ms-flex-pack: end !important; - justify-content: flex-end !important; - } - .justify-content-xl-center { - -ms-flex-pack: center !important; - justify-content: center !important; - } - .justify-content-xl-between { - -ms-flex-pack: justify !important; - justify-content: space-between !important; - } - .justify-content-xl-around { - -ms-flex-pack: distribute !important; - justify-content: space-around !important; - } - .align-items-xl-start { - -ms-flex-align: start !important; - align-items: flex-start !important; - } - .align-items-xl-end { - -ms-flex-align: end !important; - align-items: flex-end !important; - } - .align-items-xl-center { - -ms-flex-align: center !important; - align-items: center !important; - } - .align-items-xl-baseline { - -ms-flex-align: baseline !important; - align-items: baseline !important; - } - .align-items-xl-stretch { - -ms-flex-align: stretch !important; - align-items: stretch !important; - } - .align-content-xl-start { - -ms-flex-line-pack: start !important; - align-content: flex-start !important; - } - .align-content-xl-end { - -ms-flex-line-pack: end !important; - align-content: flex-end !important; - } - .align-content-xl-center { - -ms-flex-line-pack: center !important; - align-content: center !important; - } - .align-content-xl-between { - -ms-flex-line-pack: justify !important; - align-content: space-between !important; - } - .align-content-xl-around { - -ms-flex-line-pack: distribute !important; - align-content: space-around !important; - } - .align-content-xl-stretch { - -ms-flex-line-pack: stretch !important; - align-content: stretch !important; - } - .align-self-xl-auto { - -ms-flex-item-align: auto !important; - align-self: auto !important; - } - .align-self-xl-start { - -ms-flex-item-align: start !important; - align-self: flex-start !important; - } - .align-self-xl-end { - -ms-flex-item-align: end !important; - align-self: flex-end !important; - } - .align-self-xl-center { - -ms-flex-item-align: center !important; - align-self: center !important; - } - .align-self-xl-baseline { - -ms-flex-item-align: baseline !important; - align-self: baseline !important; - } - .align-self-xl-stretch { - -ms-flex-item-align: stretch !important; - align-self: stretch !important; - } -} - -.m-0 { - margin: 0 !important; -} - -.mt-0, -.my-0 { - margin-top: 0 !important; -} - -.mr-0, -.mx-0 { - margin-right: 0 !important; -} - -.mb-0, -.my-0 { - margin-bottom: 0 !important; -} - -.ml-0, -.mx-0 { - margin-left: 0 !important; -} - -.m-1 { - margin: 0.25rem !important; -} - -.mt-1, -.my-1 { - margin-top: 0.25rem !important; -} - -.mr-1, -.mx-1 { - margin-right: 0.25rem !important; -} - -.mb-1, -.my-1 { - margin-bottom: 0.25rem !important; -} - -.ml-1, -.mx-1 { - margin-left: 0.25rem !important; -} - -.m-2 { - margin: 0.5rem !important; -} - -.mt-2, -.my-2 { - margin-top: 0.5rem !important; -} - -.mr-2, -.mx-2 { - margin-right: 0.5rem !important; -} - -.mb-2, -.my-2 { - margin-bottom: 0.5rem !important; -} - -.ml-2, -.mx-2 { - margin-left: 0.5rem !important; -} - -.m-3 { - margin: 1rem !important; -} - -.mt-3, -.my-3 { - margin-top: 1rem !important; -} - -.mr-3, -.mx-3 { - margin-right: 1rem !important; -} - -.mb-3, -.my-3 { - margin-bottom: 1rem !important; -} - -.ml-3, -.mx-3 { - margin-left: 1rem !important; -} - -.m-4 { - margin: 1.5rem !important; -} - -.mt-4, -.my-4 { - margin-top: 1.5rem !important; -} - -.mr-4, -.mx-4 { - margin-right: 1.5rem !important; -} - -.mb-4, -.my-4 { - margin-bottom: 1.5rem !important; -} - -.ml-4, -.mx-4 { - margin-left: 1.5rem !important; -} - -.m-5 { - margin: 3rem !important; -} - -.mt-5, -.my-5 { - margin-top: 3rem !important; -} - -.mr-5, -.mx-5 { - margin-right: 3rem !important; -} - -.mb-5, -.my-5 { - margin-bottom: 3rem !important; -} - -.ml-5, -.mx-5 { - margin-left: 3rem !important; -} - -.p-0 { - padding: 0 !important; -} - -.pt-0, -.py-0 { - padding-top: 0 !important; -} - -.pr-0, -.px-0 { - padding-right: 0 !important; -} - -.pb-0, -.py-0 { - padding-bottom: 0 !important; -} - -.pl-0, -.px-0 { - padding-left: 0 !important; -} - -.p-1 { - padding: 0.25rem !important; -} - -.pt-1, -.py-1 { - padding-top: 0.25rem !important; -} - -.pr-1, -.px-1 { - padding-right: 0.25rem !important; -} - -.pb-1, -.py-1 { - padding-bottom: 0.25rem !important; -} - -.pl-1, -.px-1 { - padding-left: 0.25rem !important; -} - -.p-2 { - padding: 0.5rem !important; -} - -.pt-2, -.py-2 { - padding-top: 0.5rem !important; -} - -.pr-2, -.px-2 { - padding-right: 0.5rem !important; -} - -.pb-2, -.py-2 { - padding-bottom: 0.5rem !important; -} - -.pl-2, -.px-2 { - padding-left: 0.5rem !important; -} - -.p-3 { - padding: 1rem !important; -} - -.pt-3, -.py-3 { - padding-top: 1rem !important; -} - -.pr-3, -.px-3 { - padding-right: 1rem !important; -} - -.pb-3, -.py-3 { - padding-bottom: 1rem !important; -} - -.pl-3, -.px-3 { - padding-left: 1rem !important; -} - -.p-4 { - padding: 1.5rem !important; -} - -.pt-4, -.py-4 { - padding-top: 1.5rem !important; -} - -.pr-4, -.px-4 { - padding-right: 1.5rem !important; -} - -.pb-4, -.py-4 { - padding-bottom: 1.5rem !important; -} - -.pl-4, -.px-4 { - padding-left: 1.5rem !important; -} - -.p-5 { - padding: 3rem !important; -} - -.pt-5, -.py-5 { - padding-top: 3rem !important; -} - -.pr-5, -.px-5 { - padding-right: 3rem !important; -} - -.pb-5, -.py-5 { - padding-bottom: 3rem !important; -} - -.pl-5, -.px-5 { - padding-left: 3rem !important; -} - -.m-n1 { - margin: -0.25rem !important; -} - -.mt-n1, -.my-n1 { - margin-top: -0.25rem !important; -} - -.mr-n1, -.mx-n1 { - margin-right: -0.25rem !important; -} - -.mb-n1, -.my-n1 { - margin-bottom: -0.25rem !important; -} - -.ml-n1, -.mx-n1 { - margin-left: -0.25rem !important; -} - -.m-n2 { - margin: -0.5rem !important; -} - -.mt-n2, -.my-n2 { - margin-top: -0.5rem !important; -} - -.mr-n2, -.mx-n2 { - margin-right: -0.5rem !important; -} - -.mb-n2, -.my-n2 { - margin-bottom: -0.5rem !important; -} - -.ml-n2, -.mx-n2 { - margin-left: -0.5rem !important; -} - -.m-n3 { - margin: -1rem !important; -} - -.mt-n3, -.my-n3 { - margin-top: -1rem !important; -} - -.mr-n3, -.mx-n3 { - margin-right: -1rem !important; -} - -.mb-n3, -.my-n3 { - margin-bottom: -1rem !important; -} - -.ml-n3, -.mx-n3 { - margin-left: -1rem !important; -} - -.m-n4 { - margin: -1.5rem !important; -} - -.mt-n4, -.my-n4 { - margin-top: -1.5rem !important; -} - -.mr-n4, -.mx-n4 { - margin-right: -1.5rem !important; -} - -.mb-n4, -.my-n4 { - margin-bottom: -1.5rem !important; -} - -.ml-n4, -.mx-n4 { - margin-left: -1.5rem !important; -} - -.m-n5 { - margin: -3rem !important; -} - -.mt-n5, -.my-n5 { - margin-top: -3rem !important; -} - -.mr-n5, -.mx-n5 { - margin-right: -3rem !important; -} - -.mb-n5, -.my-n5 { - margin-bottom: -3rem !important; -} - -.ml-n5, -.mx-n5 { - margin-left: -3rem !important; -} - -.m-auto { - margin: auto !important; -} - -.mt-auto, -.my-auto { - margin-top: auto !important; -} - -.mr-auto, -.mx-auto { - margin-right: auto !important; -} - -.mb-auto, -.my-auto { - margin-bottom: auto !important; -} - -.ml-auto, -.mx-auto { - margin-left: auto !important; -} - -@media (min-width: 576px) { - .m-sm-0 { - margin: 0 !important; - } - .mt-sm-0, - .my-sm-0 { - margin-top: 0 !important; - } - .mr-sm-0, - .mx-sm-0 { - margin-right: 0 !important; - } - .mb-sm-0, - .my-sm-0 { - margin-bottom: 0 !important; - } - .ml-sm-0, - .mx-sm-0 { - margin-left: 0 !important; - } - .m-sm-1 { - margin: 0.25rem !important; - } - .mt-sm-1, - .my-sm-1 { - margin-top: 0.25rem !important; - } - .mr-sm-1, - .mx-sm-1 { - margin-right: 0.25rem !important; - } - .mb-sm-1, - .my-sm-1 { - margin-bottom: 0.25rem !important; - } - .ml-sm-1, - .mx-sm-1 { - margin-left: 0.25rem !important; - } - .m-sm-2 { - margin: 0.5rem !important; - } - .mt-sm-2, - .my-sm-2 { - margin-top: 0.5rem !important; - } - .mr-sm-2, - .mx-sm-2 { - margin-right: 0.5rem !important; - } - .mb-sm-2, - .my-sm-2 { - margin-bottom: 0.5rem !important; - } - .ml-sm-2, - .mx-sm-2 { - margin-left: 0.5rem !important; - } - .m-sm-3 { - margin: 1rem !important; - } - .mt-sm-3, - .my-sm-3 { - margin-top: 1rem !important; - } - .mr-sm-3, - .mx-sm-3 { - margin-right: 1rem !important; - } - .mb-sm-3, - .my-sm-3 { - margin-bottom: 1rem !important; - } - .ml-sm-3, - .mx-sm-3 { - margin-left: 1rem !important; - } - .m-sm-4 { - margin: 1.5rem !important; - } - .mt-sm-4, - .my-sm-4 { - margin-top: 1.5rem !important; - } - .mr-sm-4, - .mx-sm-4 { - margin-right: 1.5rem !important; - } - .mb-sm-4, - .my-sm-4 { - margin-bottom: 1.5rem !important; - } - .ml-sm-4, - .mx-sm-4 { - margin-left: 1.5rem !important; - } - .m-sm-5 { - margin: 3rem !important; - } - .mt-sm-5, - .my-sm-5 { - margin-top: 3rem !important; - } - .mr-sm-5, - .mx-sm-5 { - margin-right: 3rem !important; - } - .mb-sm-5, - .my-sm-5 { - margin-bottom: 3rem !important; - } - .ml-sm-5, - .mx-sm-5 { - margin-left: 3rem !important; - } - .p-sm-0 { - padding: 0 !important; - } - .pt-sm-0, - .py-sm-0 { - padding-top: 0 !important; - } - .pr-sm-0, - .px-sm-0 { - padding-right: 0 !important; - } - .pb-sm-0, - .py-sm-0 { - padding-bottom: 0 !important; - } - .pl-sm-0, - .px-sm-0 { - padding-left: 0 !important; - } - .p-sm-1 { - padding: 0.25rem !important; - } - .pt-sm-1, - .py-sm-1 { - padding-top: 0.25rem !important; - } - .pr-sm-1, - .px-sm-1 { - padding-right: 0.25rem !important; - } - .pb-sm-1, - .py-sm-1 { - padding-bottom: 0.25rem !important; - } - .pl-sm-1, - .px-sm-1 { - padding-left: 0.25rem !important; - } - .p-sm-2 { - padding: 0.5rem !important; - } - .pt-sm-2, - .py-sm-2 { - padding-top: 0.5rem !important; - } - .pr-sm-2, - .px-sm-2 { - padding-right: 0.5rem !important; - } - .pb-sm-2, - .py-sm-2 { - padding-bottom: 0.5rem !important; - } - .pl-sm-2, - .px-sm-2 { - padding-left: 0.5rem !important; - } - .p-sm-3 { - padding: 1rem !important; - } - .pt-sm-3, - .py-sm-3 { - padding-top: 1rem !important; - } - .pr-sm-3, - .px-sm-3 { - padding-right: 1rem !important; - } - .pb-sm-3, - .py-sm-3 { - padding-bottom: 1rem !important; - } - .pl-sm-3, - .px-sm-3 { - padding-left: 1rem !important; - } - .p-sm-4 { - padding: 1.5rem !important; - } - .pt-sm-4, - .py-sm-4 { - padding-top: 1.5rem !important; - } - .pr-sm-4, - .px-sm-4 { - padding-right: 1.5rem !important; - } - .pb-sm-4, - .py-sm-4 { - padding-bottom: 1.5rem !important; - } - .pl-sm-4, - .px-sm-4 { - padding-left: 1.5rem !important; - } - .p-sm-5 { - padding: 3rem !important; - } - .pt-sm-5, - .py-sm-5 { - padding-top: 3rem !important; - } - .pr-sm-5, - .px-sm-5 { - padding-right: 3rem !important; - } - .pb-sm-5, - .py-sm-5 { - padding-bottom: 3rem !important; - } - .pl-sm-5, - .px-sm-5 { - padding-left: 3rem !important; - } - .m-sm-n1 { - margin: -0.25rem !important; - } - .mt-sm-n1, - .my-sm-n1 { - margin-top: -0.25rem !important; - } - .mr-sm-n1, - .mx-sm-n1 { - margin-right: -0.25rem !important; - } - .mb-sm-n1, - .my-sm-n1 { - margin-bottom: -0.25rem !important; - } - .ml-sm-n1, - .mx-sm-n1 { - margin-left: -0.25rem !important; - } - .m-sm-n2 { - margin: -0.5rem !important; - } - .mt-sm-n2, - .my-sm-n2 { - margin-top: -0.5rem !important; - } - .mr-sm-n2, - .mx-sm-n2 { - margin-right: -0.5rem !important; - } - .mb-sm-n2, - .my-sm-n2 { - margin-bottom: -0.5rem !important; - } - .ml-sm-n2, - .mx-sm-n2 { - margin-left: -0.5rem !important; - } - .m-sm-n3 { - margin: -1rem !important; - } - .mt-sm-n3, - .my-sm-n3 { - margin-top: -1rem !important; - } - .mr-sm-n3, - .mx-sm-n3 { - margin-right: -1rem !important; - } - .mb-sm-n3, - .my-sm-n3 { - margin-bottom: -1rem !important; - } - .ml-sm-n3, - .mx-sm-n3 { - margin-left: -1rem !important; - } - .m-sm-n4 { - margin: -1.5rem !important; - } - .mt-sm-n4, - .my-sm-n4 { - margin-top: -1.5rem !important; - } - .mr-sm-n4, - .mx-sm-n4 { - margin-right: -1.5rem !important; - } - .mb-sm-n4, - .my-sm-n4 { - margin-bottom: -1.5rem !important; - } - .ml-sm-n4, - .mx-sm-n4 { - margin-left: -1.5rem !important; - } - .m-sm-n5 { - margin: -3rem !important; - } - .mt-sm-n5, - .my-sm-n5 { - margin-top: -3rem !important; - } - .mr-sm-n5, - .mx-sm-n5 { - margin-right: -3rem !important; - } - .mb-sm-n5, - .my-sm-n5 { - margin-bottom: -3rem !important; - } - .ml-sm-n5, - .mx-sm-n5 { - margin-left: -3rem !important; - } - .m-sm-auto { - margin: auto !important; - } - .mt-sm-auto, - .my-sm-auto { - margin-top: auto !important; - } - .mr-sm-auto, - .mx-sm-auto { - margin-right: auto !important; - } - .mb-sm-auto, - .my-sm-auto { - margin-bottom: auto !important; - } - .ml-sm-auto, - .mx-sm-auto { - margin-left: auto !important; - } -} - -@media (min-width: 768px) { - .m-md-0 { - margin: 0 !important; - } - .mt-md-0, - .my-md-0 { - margin-top: 0 !important; - } - .mr-md-0, - .mx-md-0 { - margin-right: 0 !important; - } - .mb-md-0, - .my-md-0 { - margin-bottom: 0 !important; - } - .ml-md-0, - .mx-md-0 { - margin-left: 0 !important; - } - .m-md-1 { - margin: 0.25rem !important; - } - .mt-md-1, - .my-md-1 { - margin-top: 0.25rem !important; - } - .mr-md-1, - .mx-md-1 { - margin-right: 0.25rem !important; - } - .mb-md-1, - .my-md-1 { - margin-bottom: 0.25rem !important; - } - .ml-md-1, - .mx-md-1 { - margin-left: 0.25rem !important; - } - .m-md-2 { - margin: 0.5rem !important; - } - .mt-md-2, - .my-md-2 { - margin-top: 0.5rem !important; - } - .mr-md-2, - .mx-md-2 { - margin-right: 0.5rem !important; - } - .mb-md-2, - .my-md-2 { - margin-bottom: 0.5rem !important; - } - .ml-md-2, - .mx-md-2 { - margin-left: 0.5rem !important; - } - .m-md-3 { - margin: 1rem !important; - } - .mt-md-3, - .my-md-3 { - margin-top: 1rem !important; - } - .mr-md-3, - .mx-md-3 { - margin-right: 1rem !important; - } - .mb-md-3, - .my-md-3 { - margin-bottom: 1rem !important; - } - .ml-md-3, - .mx-md-3 { - margin-left: 1rem !important; - } - .m-md-4 { - margin: 1.5rem !important; - } - .mt-md-4, - .my-md-4 { - margin-top: 1.5rem !important; - } - .mr-md-4, - .mx-md-4 { - margin-right: 1.5rem !important; - } - .mb-md-4, - .my-md-4 { - margin-bottom: 1.5rem !important; - } - .ml-md-4, - .mx-md-4 { - margin-left: 1.5rem !important; - } - .m-md-5 { - margin: 3rem !important; - } - .mt-md-5, - .my-md-5 { - margin-top: 3rem !important; - } - .mr-md-5, - .mx-md-5 { - margin-right: 3rem !important; - } - .mb-md-5, - .my-md-5 { - margin-bottom: 3rem !important; - } - .ml-md-5, - .mx-md-5 { - margin-left: 3rem !important; - } - .p-md-0 { - padding: 0 !important; - } - .pt-md-0, - .py-md-0 { - padding-top: 0 !important; - } - .pr-md-0, - .px-md-0 { - padding-right: 0 !important; - } - .pb-md-0, - .py-md-0 { - padding-bottom: 0 !important; - } - .pl-md-0, - .px-md-0 { - padding-left: 0 !important; - } - .p-md-1 { - padding: 0.25rem !important; - } - .pt-md-1, - .py-md-1 { - padding-top: 0.25rem !important; - } - .pr-md-1, - .px-md-1 { - padding-right: 0.25rem !important; - } - .pb-md-1, - .py-md-1 { - padding-bottom: 0.25rem !important; - } - .pl-md-1, - .px-md-1 { - padding-left: 0.25rem !important; - } - .p-md-2 { - padding: 0.5rem !important; - } - .pt-md-2, - .py-md-2 { - padding-top: 0.5rem !important; - } - .pr-md-2, - .px-md-2 { - padding-right: 0.5rem !important; - } - .pb-md-2, - .py-md-2 { - padding-bottom: 0.5rem !important; - } - .pl-md-2, - .px-md-2 { - padding-left: 0.5rem !important; - } - .p-md-3 { - padding: 1rem !important; - } - .pt-md-3, - .py-md-3 { - padding-top: 1rem !important; - } - .pr-md-3, - .px-md-3 { - padding-right: 1rem !important; - } - .pb-md-3, - .py-md-3 { - padding-bottom: 1rem !important; - } - .pl-md-3, - .px-md-3 { - padding-left: 1rem !important; - } - .p-md-4 { - padding: 1.5rem !important; - } - .pt-md-4, - .py-md-4 { - padding-top: 1.5rem !important; - } - .pr-md-4, - .px-md-4 { - padding-right: 1.5rem !important; - } - .pb-md-4, - .py-md-4 { - padding-bottom: 1.5rem !important; - } - .pl-md-4, - .px-md-4 { - padding-left: 1.5rem !important; - } - .p-md-5 { - padding: 3rem !important; - } - .pt-md-5, - .py-md-5 { - padding-top: 3rem !important; - } - .pr-md-5, - .px-md-5 { - padding-right: 3rem !important; - } - .pb-md-5, - .py-md-5 { - padding-bottom: 3rem !important; - } - .pl-md-5, - .px-md-5 { - padding-left: 3rem !important; - } - .m-md-n1 { - margin: -0.25rem !important; - } - .mt-md-n1, - .my-md-n1 { - margin-top: -0.25rem !important; - } - .mr-md-n1, - .mx-md-n1 { - margin-right: -0.25rem !important; - } - .mb-md-n1, - .my-md-n1 { - margin-bottom: -0.25rem !important; - } - .ml-md-n1, - .mx-md-n1 { - margin-left: -0.25rem !important; - } - .m-md-n2 { - margin: -0.5rem !important; - } - .mt-md-n2, - .my-md-n2 { - margin-top: -0.5rem !important; - } - .mr-md-n2, - .mx-md-n2 { - margin-right: -0.5rem !important; - } - .mb-md-n2, - .my-md-n2 { - margin-bottom: -0.5rem !important; - } - .ml-md-n2, - .mx-md-n2 { - margin-left: -0.5rem !important; - } - .m-md-n3 { - margin: -1rem !important; - } - .mt-md-n3, - .my-md-n3 { - margin-top: -1rem !important; - } - .mr-md-n3, - .mx-md-n3 { - margin-right: -1rem !important; - } - .mb-md-n3, - .my-md-n3 { - margin-bottom: -1rem !important; - } - .ml-md-n3, - .mx-md-n3 { - margin-left: -1rem !important; - } - .m-md-n4 { - margin: -1.5rem !important; - } - .mt-md-n4, - .my-md-n4 { - margin-top: -1.5rem !important; - } - .mr-md-n4, - .mx-md-n4 { - margin-right: -1.5rem !important; - } - .mb-md-n4, - .my-md-n4 { - margin-bottom: -1.5rem !important; - } - .ml-md-n4, - .mx-md-n4 { - margin-left: -1.5rem !important; - } - .m-md-n5 { - margin: -3rem !important; - } - .mt-md-n5, - .my-md-n5 { - margin-top: -3rem !important; - } - .mr-md-n5, - .mx-md-n5 { - margin-right: -3rem !important; - } - .mb-md-n5, - .my-md-n5 { - margin-bottom: -3rem !important; - } - .ml-md-n5, - .mx-md-n5 { - margin-left: -3rem !important; - } - .m-md-auto { - margin: auto !important; - } - .mt-md-auto, - .my-md-auto { - margin-top: auto !important; - } - .mr-md-auto, - .mx-md-auto { - margin-right: auto !important; - } - .mb-md-auto, - .my-md-auto { - margin-bottom: auto !important; - } - .ml-md-auto, - .mx-md-auto { - margin-left: auto !important; - } -} - -@media (min-width: 992px) { - .m-lg-0 { - margin: 0 !important; - } - .mt-lg-0, - .my-lg-0 { - margin-top: 0 !important; - } - .mr-lg-0, - .mx-lg-0 { - margin-right: 0 !important; - } - .mb-lg-0, - .my-lg-0 { - margin-bottom: 0 !important; - } - .ml-lg-0, - .mx-lg-0 { - margin-left: 0 !important; - } - .m-lg-1 { - margin: 0.25rem !important; - } - .mt-lg-1, - .my-lg-1 { - margin-top: 0.25rem !important; - } - .mr-lg-1, - .mx-lg-1 { - margin-right: 0.25rem !important; - } - .mb-lg-1, - .my-lg-1 { - margin-bottom: 0.25rem !important; - } - .ml-lg-1, - .mx-lg-1 { - margin-left: 0.25rem !important; - } - .m-lg-2 { - margin: 0.5rem !important; - } - .mt-lg-2, - .my-lg-2 { - margin-top: 0.5rem !important; - } - .mr-lg-2, - .mx-lg-2 { - margin-right: 0.5rem !important; - } - .mb-lg-2, - .my-lg-2 { - margin-bottom: 0.5rem !important; - } - .ml-lg-2, - .mx-lg-2 { - margin-left: 0.5rem !important; - } - .m-lg-3 { - margin: 1rem !important; - } - .mt-lg-3, - .my-lg-3 { - margin-top: 1rem !important; - } - .mr-lg-3, - .mx-lg-3 { - margin-right: 1rem !important; - } - .mb-lg-3, - .my-lg-3 { - margin-bottom: 1rem !important; - } - .ml-lg-3, - .mx-lg-3 { - margin-left: 1rem !important; - } - .m-lg-4 { - margin: 1.5rem !important; - } - .mt-lg-4, - .my-lg-4 { - margin-top: 1.5rem !important; - } - .mr-lg-4, - .mx-lg-4 { - margin-right: 1.5rem !important; - } - .mb-lg-4, - .my-lg-4 { - margin-bottom: 1.5rem !important; - } - .ml-lg-4, - .mx-lg-4 { - margin-left: 1.5rem !important; - } - .m-lg-5 { - margin: 3rem !important; - } - .mt-lg-5, - .my-lg-5 { - margin-top: 3rem !important; - } - .mr-lg-5, - .mx-lg-5 { - margin-right: 3rem !important; - } - .mb-lg-5, - .my-lg-5 { - margin-bottom: 3rem !important; - } - .ml-lg-5, - .mx-lg-5 { - margin-left: 3rem !important; - } - .p-lg-0 { - padding: 0 !important; - } - .pt-lg-0, - .py-lg-0 { - padding-top: 0 !important; - } - .pr-lg-0, - .px-lg-0 { - padding-right: 0 !important; - } - .pb-lg-0, - .py-lg-0 { - padding-bottom: 0 !important; - } - .pl-lg-0, - .px-lg-0 { - padding-left: 0 !important; - } - .p-lg-1 { - padding: 0.25rem !important; - } - .pt-lg-1, - .py-lg-1 { - padding-top: 0.25rem !important; - } - .pr-lg-1, - .px-lg-1 { - padding-right: 0.25rem !important; - } - .pb-lg-1, - .py-lg-1 { - padding-bottom: 0.25rem !important; - } - .pl-lg-1, - .px-lg-1 { - padding-left: 0.25rem !important; - } - .p-lg-2 { - padding: 0.5rem !important; - } - .pt-lg-2, - .py-lg-2 { - padding-top: 0.5rem !important; - } - .pr-lg-2, - .px-lg-2 { - padding-right: 0.5rem !important; - } - .pb-lg-2, - .py-lg-2 { - padding-bottom: 0.5rem !important; - } - .pl-lg-2, - .px-lg-2 { - padding-left: 0.5rem !important; - } - .p-lg-3 { - padding: 1rem !important; - } - .pt-lg-3, - .py-lg-3 { - padding-top: 1rem !important; - } - .pr-lg-3, - .px-lg-3 { - padding-right: 1rem !important; - } - .pb-lg-3, - .py-lg-3 { - padding-bottom: 1rem !important; - } - .pl-lg-3, - .px-lg-3 { - padding-left: 1rem !important; - } - .p-lg-4 { - padding: 1.5rem !important; - } - .pt-lg-4, - .py-lg-4 { - padding-top: 1.5rem !important; - } - .pr-lg-4, - .px-lg-4 { - padding-right: 1.5rem !important; - } - .pb-lg-4, - .py-lg-4 { - padding-bottom: 1.5rem !important; - } - .pl-lg-4, - .px-lg-4 { - padding-left: 1.5rem !important; - } - .p-lg-5 { - padding: 3rem !important; - } - .pt-lg-5, - .py-lg-5 { - padding-top: 3rem !important; - } - .pr-lg-5, - .px-lg-5 { - padding-right: 3rem !important; - } - .pb-lg-5, - .py-lg-5 { - padding-bottom: 3rem !important; - } - .pl-lg-5, - .px-lg-5 { - padding-left: 3rem !important; - } - .m-lg-n1 { - margin: -0.25rem !important; - } - .mt-lg-n1, - .my-lg-n1 { - margin-top: -0.25rem !important; - } - .mr-lg-n1, - .mx-lg-n1 { - margin-right: -0.25rem !important; - } - .mb-lg-n1, - .my-lg-n1 { - margin-bottom: -0.25rem !important; - } - .ml-lg-n1, - .mx-lg-n1 { - margin-left: -0.25rem !important; - } - .m-lg-n2 { - margin: -0.5rem !important; - } - .mt-lg-n2, - .my-lg-n2 { - margin-top: -0.5rem !important; - } - .mr-lg-n2, - .mx-lg-n2 { - margin-right: -0.5rem !important; - } - .mb-lg-n2, - .my-lg-n2 { - margin-bottom: -0.5rem !important; - } - .ml-lg-n2, - .mx-lg-n2 { - margin-left: -0.5rem !important; - } - .m-lg-n3 { - margin: -1rem !important; - } - .mt-lg-n3, - .my-lg-n3 { - margin-top: -1rem !important; - } - .mr-lg-n3, - .mx-lg-n3 { - margin-right: -1rem !important; - } - .mb-lg-n3, - .my-lg-n3 { - margin-bottom: -1rem !important; - } - .ml-lg-n3, - .mx-lg-n3 { - margin-left: -1rem !important; - } - .m-lg-n4 { - margin: -1.5rem !important; - } - .mt-lg-n4, - .my-lg-n4 { - margin-top: -1.5rem !important; - } - .mr-lg-n4, - .mx-lg-n4 { - margin-right: -1.5rem !important; - } - .mb-lg-n4, - .my-lg-n4 { - margin-bottom: -1.5rem !important; - } - .ml-lg-n4, - .mx-lg-n4 { - margin-left: -1.5rem !important; - } - .m-lg-n5 { - margin: -3rem !important; - } - .mt-lg-n5, - .my-lg-n5 { - margin-top: -3rem !important; - } - .mr-lg-n5, - .mx-lg-n5 { - margin-right: -3rem !important; - } - .mb-lg-n5, - .my-lg-n5 { - margin-bottom: -3rem !important; - } - .ml-lg-n5, - .mx-lg-n5 { - margin-left: -3rem !important; - } - .m-lg-auto { - margin: auto !important; - } - .mt-lg-auto, - .my-lg-auto { - margin-top: auto !important; - } - .mr-lg-auto, - .mx-lg-auto { - margin-right: auto !important; - } - .mb-lg-auto, - .my-lg-auto { - margin-bottom: auto !important; - } - .ml-lg-auto, - .mx-lg-auto { - margin-left: auto !important; - } -} - -@media (min-width: 1200px) { - .m-xl-0 { - margin: 0 !important; - } - .mt-xl-0, - .my-xl-0 { - margin-top: 0 !important; - } - .mr-xl-0, - .mx-xl-0 { - margin-right: 0 !important; - } - .mb-xl-0, - .my-xl-0 { - margin-bottom: 0 !important; - } - .ml-xl-0, - .mx-xl-0 { - margin-left: 0 !important; - } - .m-xl-1 { - margin: 0.25rem !important; - } - .mt-xl-1, - .my-xl-1 { - margin-top: 0.25rem !important; - } - .mr-xl-1, - .mx-xl-1 { - margin-right: 0.25rem !important; - } - .mb-xl-1, - .my-xl-1 { - margin-bottom: 0.25rem !important; - } - .ml-xl-1, - .mx-xl-1 { - margin-left: 0.25rem !important; - } - .m-xl-2 { - margin: 0.5rem !important; - } - .mt-xl-2, - .my-xl-2 { - margin-top: 0.5rem !important; - } - .mr-xl-2, - .mx-xl-2 { - margin-right: 0.5rem !important; - } - .mb-xl-2, - .my-xl-2 { - margin-bottom: 0.5rem !important; - } - .ml-xl-2, - .mx-xl-2 { - margin-left: 0.5rem !important; - } - .m-xl-3 { - margin: 1rem !important; - } - .mt-xl-3, - .my-xl-3 { - margin-top: 1rem !important; - } - .mr-xl-3, - .mx-xl-3 { - margin-right: 1rem !important; - } - .mb-xl-3, - .my-xl-3 { - margin-bottom: 1rem !important; - } - .ml-xl-3, - .mx-xl-3 { - margin-left: 1rem !important; - } - .m-xl-4 { - margin: 1.5rem !important; - } - .mt-xl-4, - .my-xl-4 { - margin-top: 1.5rem !important; - } - .mr-xl-4, - .mx-xl-4 { - margin-right: 1.5rem !important; - } - .mb-xl-4, - .my-xl-4 { - margin-bottom: 1.5rem !important; - } - .ml-xl-4, - .mx-xl-4 { - margin-left: 1.5rem !important; - } - .m-xl-5 { - margin: 3rem !important; - } - .mt-xl-5, - .my-xl-5 { - margin-top: 3rem !important; - } - .mr-xl-5, - .mx-xl-5 { - margin-right: 3rem !important; - } - .mb-xl-5, - .my-xl-5 { - margin-bottom: 3rem !important; - } - .ml-xl-5, - .mx-xl-5 { - margin-left: 3rem !important; - } - .p-xl-0 { - padding: 0 !important; - } - .pt-xl-0, - .py-xl-0 { - padding-top: 0 !important; - } - .pr-xl-0, - .px-xl-0 { - padding-right: 0 !important; - } - .pb-xl-0, - .py-xl-0 { - padding-bottom: 0 !important; - } - .pl-xl-0, - .px-xl-0 { - padding-left: 0 !important; - } - .p-xl-1 { - padding: 0.25rem !important; - } - .pt-xl-1, - .py-xl-1 { - padding-top: 0.25rem !important; - } - .pr-xl-1, - .px-xl-1 { - padding-right: 0.25rem !important; - } - .pb-xl-1, - .py-xl-1 { - padding-bottom: 0.25rem !important; - } - .pl-xl-1, - .px-xl-1 { - padding-left: 0.25rem !important; - } - .p-xl-2 { - padding: 0.5rem !important; - } - .pt-xl-2, - .py-xl-2 { - padding-top: 0.5rem !important; - } - .pr-xl-2, - .px-xl-2 { - padding-right: 0.5rem !important; - } - .pb-xl-2, - .py-xl-2 { - padding-bottom: 0.5rem !important; - } - .pl-xl-2, - .px-xl-2 { - padding-left: 0.5rem !important; - } - .p-xl-3 { - padding: 1rem !important; - } - .pt-xl-3, - .py-xl-3 { - padding-top: 1rem !important; - } - .pr-xl-3, - .px-xl-3 { - padding-right: 1rem !important; - } - .pb-xl-3, - .py-xl-3 { - padding-bottom: 1rem !important; - } - .pl-xl-3, - .px-xl-3 { - padding-left: 1rem !important; - } - .p-xl-4 { - padding: 1.5rem !important; - } - .pt-xl-4, - .py-xl-4 { - padding-top: 1.5rem !important; - } - .pr-xl-4, - .px-xl-4 { - padding-right: 1.5rem !important; - } - .pb-xl-4, - .py-xl-4 { - padding-bottom: 1.5rem !important; - } - .pl-xl-4, - .px-xl-4 { - padding-left: 1.5rem !important; - } - .p-xl-5 { - padding: 3rem !important; - } - .pt-xl-5, - .py-xl-5 { - padding-top: 3rem !important; - } - .pr-xl-5, - .px-xl-5 { - padding-right: 3rem !important; - } - .pb-xl-5, - .py-xl-5 { - padding-bottom: 3rem !important; - } - .pl-xl-5, - .px-xl-5 { - padding-left: 3rem !important; - } - .m-xl-n1 { - margin: -0.25rem !important; - } - .mt-xl-n1, - .my-xl-n1 { - margin-top: -0.25rem !important; - } - .mr-xl-n1, - .mx-xl-n1 { - margin-right: -0.25rem !important; - } - .mb-xl-n1, - .my-xl-n1 { - margin-bottom: -0.25rem !important; - } - .ml-xl-n1, - .mx-xl-n1 { - margin-left: -0.25rem !important; - } - .m-xl-n2 { - margin: -0.5rem !important; - } - .mt-xl-n2, - .my-xl-n2 { - margin-top: -0.5rem !important; - } - .mr-xl-n2, - .mx-xl-n2 { - margin-right: -0.5rem !important; - } - .mb-xl-n2, - .my-xl-n2 { - margin-bottom: -0.5rem !important; - } - .ml-xl-n2, - .mx-xl-n2 { - margin-left: -0.5rem !important; - } - .m-xl-n3 { - margin: -1rem !important; - } - .mt-xl-n3, - .my-xl-n3 { - margin-top: -1rem !important; - } - .mr-xl-n3, - .mx-xl-n3 { - margin-right: -1rem !important; - } - .mb-xl-n3, - .my-xl-n3 { - margin-bottom: -1rem !important; - } - .ml-xl-n3, - .mx-xl-n3 { - margin-left: -1rem !important; - } - .m-xl-n4 { - margin: -1.5rem !important; - } - .mt-xl-n4, - .my-xl-n4 { - margin-top: -1.5rem !important; - } - .mr-xl-n4, - .mx-xl-n4 { - margin-right: -1.5rem !important; - } - .mb-xl-n4, - .my-xl-n4 { - margin-bottom: -1.5rem !important; - } - .ml-xl-n4, - .mx-xl-n4 { - margin-left: -1.5rem !important; - } - .m-xl-n5 { - margin: -3rem !important; - } - .mt-xl-n5, - .my-xl-n5 { - margin-top: -3rem !important; - } - .mr-xl-n5, - .mx-xl-n5 { - margin-right: -3rem !important; - } - .mb-xl-n5, - .my-xl-n5 { - margin-bottom: -3rem !important; - } - .ml-xl-n5, - .mx-xl-n5 { - margin-left: -3rem !important; - } - .m-xl-auto { - margin: auto !important; - } - .mt-xl-auto, - .my-xl-auto { - margin-top: auto !important; - } - .mr-xl-auto, - .mx-xl-auto { - margin-right: auto !important; - } - .mb-xl-auto, - .my-xl-auto { - margin-bottom: auto !important; - } - .ml-xl-auto, - .mx-xl-auto { - margin-left: auto !important; - } -} -/*# sourceMappingURL=bootstrap-grid.css.map */ \ No newline at end of file diff --git a/archive/SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map b/archive/SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map deleted file mode 100644 index a664f980..00000000 --- a/archive/SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["../../scss/bootstrap-grid.scss","bootstrap-grid.css","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_breakpoints.scss","../../scss/_variables.scss","../../scss/mixins/_grid-framework.scss","../../scss/utilities/_display.scss","../../scss/utilities/_flex.scss","../../scss/utilities/_spacing.scss"],"names":[],"mappings":"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EKp0BM;IAAwB,iBADZ;IACY,QADZ;ELw0BlB;EKv0BM;IAAwB,iBADZ;IACY,QADZ;EL20BlB;EK10BM;IAAwB,kBADZ;IACY,SADZ;EL80BlB;EK70BM;IAAwB,kBADZ;IACY,SADZ;ELi1BlB;EKh1BM;IAAwB,kBADZ;IACY,SADZ;ELo1BlB;EK50BU;IHhBV,cAA4B;EF+1B5B;EK/0BU;IHhBV,sBAA8C;EFk2B9C;EKl1BU;IHhBV,uBAA8C;EFq2B9C;EKr1BU;IHhBV,gBAA8C;EFw2B9C;EKx1BU;IHhBV,uBAA8C;EF22B9C;EK31BU;IHhBV,uBAA8C;EF82B9C;EK91BU;IHhBV,gBAA8C;EFi3B9C;EKj2BU;IHhBV,uBAA8C;EFo3B9C;EKp2BU;IHhBV,uBAA8C;EFu3B9C;EKv2BU;IHhBV,gBAA8C;EF03B9C;EK12BU;IHhBV,uBAA8C;EF63B9C;EK72BU;IHhBV,uBAA8C;EFg4B9C;AACF;;AM76BM;EAAwB,wBAA0B;ANi7BxD;;AMj7BM;EAAwB,0BAA0B;ANq7BxD;;AMr7BM;EAAwB,gCAA0B;ANy7BxD;;AMz7BM;EAAwB,yBAA0B;AN67BxD;;AM77BM;EAAwB,yBAA0B;ANi8BxD;;AMj8BM;EAAwB,6BAA0B;ANq8BxD;;AMr8BM;EAAwB,8BAA0B;ANy8BxD;;AMz8BM;EAAwB,+BAA0B;EAA1B,wBAA0B;AN68BxD;;AM78BM;EAAwB,sCAA0B;EAA1B,+BAA0B;ANi9BxD;;AGh6BI;EGjDE;IAAwB,wBAA0B;ENs9BtD;EMt9BI;IAAwB,0BAA0B;ENy9BtD;EMz9BI;IAAwB,gCAA0B;EN49BtD;EM59BI;IAAwB,yBAA0B;EN+9BtD;EM/9BI;IAAwB,yBAA0B;ENk+BtD;EMl+BI;IAAwB,6BAA0B;ENq+BtD;EMr+BI;IAAwB,8BAA0B;ENw+BtD;EMx+BI;IAAwB,+BAA0B;IAA1B,wBAA0B;EN2+BtD;EM3+BI;IAAwB,sCAA0B;IAA1B,+BAA0B;EN8+BtD;AACF;;AG97BI;EGjDE;IAAwB,wBAA0B;ENo/BtD;EMp/BI;IAAwB,0BAA0B;ENu/BtD;EMv/BI;IAAwB,gCAA0B;EN0/BtD;EM1/BI;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hD;;AQpsDQ;EAAgC,yBAA4B;ARwsDpE;;AQvsDQ;;EAEE,6BAAoC;AR0sD9C;;AQxsDQ;;EAEE,+BAAwC;AR2sDlD;;AQzsDQ;;EAEE,gCAA0C;AR4sDpD;;AQ1sDQ;;EAEE,8BAAsC;AR6sDhD;;AQ5tDQ;EAAgC,uBAA4B;ARguDpE;;AQ/tDQ;;EAEE,2BAAoC;ARkuD9C;;AQhuDQ;;EAEE,6BAAwC;ARmuDlD;;AQjuDQ;;EAEE,8BAA0C;ARouDpD;;AQluDQ;;EAEE,4BAAsC;ARquDhD;;AQpvDQ;EAAgC,yBAA4B;ARwvDpE;;AQvvDQ;;EAEE,6BAAoC;AR0vD9C;;AQxvDQ;;EAEE,+BAAwC;AR2vDlD;;AQzvDQ;;EAEE,gCAA0C;AR4vDpD;;AQ1vDQ;;EAEE,8BAAsC;AR6vDhD;;AQ5wDQ;EAAgC,uBAA4B;ARgxDpE;;AQ/wDQ;;EAEE,2BAAoC;ARkxD9C;;AQhxDQ;;EAEE,6BAAwC;ARmxDlD;;AQjxDQ;;EAEE,8BAA0C;ARoxDpD;;AQlxDQ;;EAEE,4BAAsC;ARqxDhD;;AQpyDQ;EAAgC,qBAA4B;ARwyDpE;;AQvyDQ;;EAEE,yBAAoC;AR0yD9C;;AQxyDQ;;EAEE,2BAAwC;AR2yDlD;;AQzyDQ;;EAEE,4BAA0C;AR4yDpD;;AQ1yDQ;;EAEE,0BAAsC;AR6yDhD;;AQ5zDQ;EAAgC,2BAA4B;ARg0DpE;;AQ/zDQ;;EAEE,+BAAoC;ARk0D9C;;AQh0DQ;;EAEE,iCAAwC;ARm0DlD;;AQj0DQ;;EAEE,kCAA0C;ARo0DpD;;AQl0DQ;;EAEE,gCAAsC;ARq0DhD;;AQp1DQ;EAAgC,0BAA4B;ARw1DpE;;AQv1DQ;;EAEE,8BAAoC;AR01D9C;;AQx1DQ;;EAEE,gCAAwC;AR21DlD;;AQz1DQ;;EAEE,iCAA0C;AR41DpD;;AQ11DQ;;EAEE,+BAAsC;AR61DhD;;AQ52DQ;EAAgC,wBAA4B;ARg3DpE;;AQ/2DQ;;EAEE,4BAAoC;ARk3D9C;;AQh3DQ;;EAEE,8BAAwC;ARm3DlD;;AQj3DQ;;EAEE,+BAA0C;ARo3DpD;;AQl3DQ;;EAEE,6BAAsC;ARq3DhD;;AQp4DQ;EAAgC,0BAA4B;ARw4DpE;;AQv4DQ;;EAEE,8BAAoC;AR04D9C;;AQx4DQ;;EAEE,gCAAwC;AR24DlD;;AQz4DQ;;EAEE,iCAA0C;AR44DpD;;AQ14DQ;;EAEE,+BAAsC;AR64DhD;;AQ55DQ;EAAgC,wBAA4B;ARg6DpE;;AQ/5DQ;;EAEE,4BAAoC;ARk6D9C;;AQh6DQ;;EAEE,8BAAwC;ARm6DlD;;AQj6DQ;;EAEE,+BAA0C;ARo6DpD;;AQl6DQ;;EAEE,6BAAsC;ARq6DhD;;AQ75DQ;EAAwB,2BAA2B;ARi6D3D;;AQh6DQ;;EAEE,+BAA+B;ARm6DzC;;AQj6DQ;;EAEE,iCAAiC;ARo6D3C;;AQl6DQ;;EAEE,kCAAkC;ARq6D5C;;AQn6DQ;;EAEE,gCAAgC;ARs6D1C;;AQr7DQ;EAAwB,0BAA2B;ARy7D3D;;AQx7DQ;;EAEE,8BAA+B;AR27DzC;;AQz7DQ;;EAEE,gCAAiC;AR47D3C;;AQ17DQ;;EAEE,iCAAkC;AR67D5C;;AQ37DQ;;EAEE,+BAAgC;AR87D1C;;AQ78DQ;EAAwB,wBAA2B;ARi9D3D;;AQh9DQ;;EAEE,4BAA+B;ARm9DzC;;AQj9DQ;;EAEE,8BAAiC;ARo9D3C;;AQl9DQ;;EAEE,+BAAkC;ARq9D5C;;AQn9DQ;;EAEE,6BAAgC;ARs9D1C;;AQr+DQ;EAAwB,0BAA2B;ARy+D3D;;AQx+DQ;;EAEE,8BAA+B;AR2+DzC;;AQz+DQ;;EAEE,gCAAiC;AR4+D3C;;AQ1+DQ;;EAEE,iCAAkC;AR6+D5C;;AQ3+DQ;;EAEE,+BAAgC;AR8+D1C;;AQ7/DQ;EAAwB,wBAA2B;ARigE3D;;AQhgEQ;;EAEE,4BAA+B;ARmgEzC;;AQjgEQ;;EAEE,8BAAiC;ARogE3C;;AQlgEQ;;EAEE,+BAAkC;ARqgE5C;;AQngEQ;;EAEE,6BAAgC;ARsgE1C;;AQhgEI;EAAmB,uBAAuB;ARogE9C;;AQngEI;;EAEE,2BAA2B;ARsgEjC;;AQpgEI;;EAEE,6BAA6B;ARugEnC;;AQrgEI;;EAEE,8BAA8B;ARwgEpC;;AQtgEI;;EAEE,4BAA4B;ARygElC;;AGlhEI;EKlDI;IAAgC,oBAA4B;ERykElE;EQxkEM;;IAEE,wBAAoC;ER0kE5C;EQxkEM;;IAEE,0BAAwC;ER0kEhD;EQxkEM;;IAEE,2BAA0C;ER0kElD;EQxkEM;;IAEE,yBAAsC;ER0kE9C;EQzlEM;IAAgC,0BAA4B;ER4lElE;EQ3lEM;;IAEE,8BAAoC;ER6lE5C;EQ3lEM;;IAEE,gCAAwC;ER6lEhD;EQ3lEM;;IAEE,iCAA0C;ER6lElD;EQ3lEM;;IAEE,+BAAsC;ER6lE9C;EQ5mEM;IAAgC,yBAA4B;ER+mElE;EQ9mEM;;IAEE,6BAAoC;ERgnE5C;EQ9mEM;;IAEE,+BAAwC;ERgnEhD;EQ9mEM;;IAEE,gCAA0C;ERgnElD;EQ9mEM;;IAEE,8BAAsC;ERgnE9C;EQ/nEM;IAAgC,uBAA4B;ERkoElE;EQjoEM;;IAEE,2BAAoC;ERmoE5C;EQjoEM;;IAEE,6BAAwC;ERmoEhD;EQjoEM;;IAEE,8BAA0C;ERmoElD;EQjoEM;;IAEE,4BAAsC;ERmoE9C;EQlpEM;IAAgC,yBAA4B;ERqpElE;EQppEM;;IAEE,6BAAoC;ERspE5C;EQppEM;;IAEE,+BAAwC;ERspEhD;EQppEM;;IAEE,gCAA0C;ERspElD;EQppEM;;IAEE,8BAAsC;ERspE9C;EQrqEM;IAAgC,uBAA4B;ERwqElE;EQvqEM;;IAEE,2BAAoC;ERyqE5C;EQvqEM;;IAEE,6BAAwC;ERyqEhD;EQvqEM;;IAEE,8BAA0C;ERyqElD;EQvqEM;;IAEE,4BAAsC;ERyqE9C;EQxrEM;IAAgC,qBAA4B;ER2rElE;EQ1rEM;;IAEE,yBAAoC;ER4rE5C;EQ1rEM;;IAEE,2BAAwC;ER4rEhD;EQ1rEM;;IAEE,4BAA0C;ER4rElD;EQ1rEM;;IAEE,0BAAsC;ER4rE9C;EQ3sEM;IAAgC,2BAA4B;ER8sElE;EQ7sEM;;IAEE,+BAAoC;ER+sE5C;EQ7sEM;;IAEE,iCAAwC;ER+sEhD;EQ7sEM;;IAEE,kCAA0C;ER+sElD;EQ7sEM;;IAEE,gCAAsC;ER+sE9C;EQ9tEM;IAAgC,0BAA4B;ERiuElE;EQhuEM;;IAEE,8BAAoC;ERkuE5C;EQhuEM;;IAEE,gCAAwC;ERkuEhD;EQhuEM;;IAEE,iCAA0C;ERkuElD;EQhuEM;;IAEE,+BAAsC;ERkuE9C;EQjvEM;IAAgC,wBAA4B;ERovElE;EQnvEM;;IAEE,4BAAoC;ERqvE5C;EQnvEM;;IAEE,8BAAwC;ERqvEhD;EQnvEM;;IAEE,+BAA0C;ERqvElD;EQnvEM;;IAEE,6BAAsC;ERqvE9C;EQpwEM;IAAgC,0BAA4B;ERuwElE;EQtwEM;;IAEE,8BAAoC;ERwwE5C;EQtwEM;;IAEE,gCAAwC;ERwwEhD;EQtwEM;;IAEE,iCAA0C;ERwwElD;EQtwEM;;IAEE,+BAAsC;ERwwE9C;EQvxEM;IAAgC,wBAA4B;ER0xElE;EQzxEM;;IAEE,4BAAoC;ER2xE5C;EQzxEM;;IAEE,8BAAwC;ER2xEhD;EQzxEM;;IAEE,+BAA0C;ER2xElD;EQzxEM;;IAEE,6BAAsC;ER2xE9C;EQnxEM;IAAwB,2BAA2B;ERsxEzD;EQrxEM;;IAEE,+BAA+B;ERuxEvC;EQrxEM;;IAEE,iCAAiC;ERuxEzC;EQrxEM;;IAEE,kCAAkC;ERuxE1C;EQrxEM;;IAEE,gCAAgC;ERuxExC;EQtyEM;IAAwB,0BAA2B;ERyyEzD;EQxyEM;;IAEE,8BAA+B;ER0yEvC;EQxyEM;;IAEE,gCAAiC;ER0yEzC;EQxyEM;;IAEE,iCAAkC;ER0yE1C;EQxyEM;;IAEE,+BAAgC;ER0yExC;EQzzEM;IAAwB,wBAA2B;ER4zEzD;EQ3zEM;;IAEE,4BAA+B;ER6zEvC;EQ3zEM;;IAEE,8BAAiC;ER6zEzC;EQ3zEM;;IAEE,+BAAkC;ER6zE1C;EQ3zEM;;IAEE,6BAAgC;ER6zExC;EQ50EM;IAAwB,0BAA2B;ER+0EzD;EQ90EM;;IAEE,8BAA+B;ERg1EvC;EQ90EM;;IAEE,gCAAiC;ERg1EzC;EQ90EM;;IAEE,iCAAkC;ERg1E1C;EQ90EM;;IAEE,+BAAgC;ERg1ExC;EQ/1EM;IAAwB,wBAA2B;ERk2EzD;EQj2EM;;IAEE,4BAA+B;ERm2EvC;EQj2EM;;IAEE,8BAAiC;ERm2EzC;EQj2EM;;IAEE,+BAAkC;ERm2E1C;EQj2EM;;IAEE,6BAAgC;ERm2ExC;EQ71EE;IAAmB,uBAAuB;ERg2E5C;EQ/1EE;;IAEE,2BAA2B;ERi2E/B;EQ/1EE;;IAEE,6BAA6B;ERi2EjC;EQ/1EE;;IAEE,8BAA8B;ERi2ElC;EQ/1EE;;IAEE,4BAA4B;ERi2EhC;AACF;;AG32EI;EKlDI;IAAgC,oBAA4B;ERk6ElE;EQj6EM;;IAEE,wBAAoC;ERm6E5C;EQj6EM;;IAEE,0BAAwC;ERm6EhD;EQj6EM;;IAEE,2BAA0C;ERm6ElD;EQj6EM;;IAEE,yBAAsC;ERm6E9C;EQl7EM;IAAgC,0BAA4B;ERq7ElE;EQp7EM;;IAEE,8BAAoC;ERs7E5C;EQp7EM;;IAEE,gCAAwC;ERs7EhD;EQp7EM;;IAEE,iCAA0C;ERs7ElD;EQp7EM;;IAEE,+BAAsC;ERs7E9C;EQr8EM;IAAgC,yBAA4B;ERw8ElE;EQv8EM;;IAEE,6BAAoC;ERy8E5C;EQv8EM;;IAEE,+BAAwC;ERy8EhD;EQv8EM;;IAEE,gCAA0C;ERy8ElD;EQv8EM;;IAEE,8BAAsC;ERy8E9C;EQx9EM;IAAgC,uBAA4B;ER29ElE;EQ19EM;;IAEE,2BAAoC;ER49E5C;EQ19EM;;IAEE,6BAAwC;ER49EhD;EQ19EM;;IAEE,8BAA0C;ER49ElD;EQ19EM;;IAEE,4BAAsC;ER49E9C;EQ3+EM;IAAgC,yBAA4B;ER8+ElE;EQ7+EM;;IAEE,6BAAoC;ER++E5C;EQ7+EM;;IAEE,+BAAwC;ER++EhD;EQ7+EM;;IAEE,gCAA0C;ER++ElD;EQ7+EM;;IAEE,8BAAsC;ER++E9C;EQ9/EM;IAAgC,uBAA4B;ERigFlE;EQhgFM;;IAEE,2BAAoC;ERkgF5C;EQhgFM;;IAEE,6BAAwC;ERkgFhD;EQhgFM;;IAEE,8BAA0C;ERkgFlD;EQhgFM;;IAEE,4BAAsC;ERkgF9C;EQjhFM;IAAgC,qBAA4B;ERohFlE;EQnhFM;;IAEE,yBAAoC;ERqhF5C;EQnhFM;;IAEE,2BAAwC;ERqhFhD;EQnhFM;;IAEE,4BAA0C;ERqhFlD;EQnhFM;;IAEE,0BAAsC;ERqhF9C;EQpiFM;IAAgC,2BAA4B;ERuiFlE;EQtiFM;;IAEE,+BAAoC;ERwiF5C;EQtiFM;;IAEE,iCAAwC;ERwiFhD;EQtiFM;;IAEE,kCAA0C;ERwiFlD;EQtiFM;;IAEE,gCAAsC;ERwiF9C;EQvjFM;IAAgC,0BAA4B;ER0jFlE;EQzjFM;;IAEE,8BAAoC;ER2jF5C;EQzjFM;;IAEE,gCAAwC;ER2jFhD;EQzjFM;;IAEE,iCAA0C;ER2jFlD;EQzjFM;;IAEE,+BAAsC;ER2jF9C;EQ1kFM;IAAgC,wBAA4B;ER6kFlE;EQ5kFM;;IAEE,4BAAoC;ER8kF5C;EQ5kFM;;IAEE,8BAAwC;ER8kFhD;EQ5kFM;;IAEE,+BAA0C;ER8kFlD;EQ5kFM;;IAEE,6BAAsC;ER8kF9C;EQ7lFM;IAAgC,0BAA4B;ERgmFlE;EQ/lFM;;IAEE,8BAAoC;ERimF5C;EQ/lFM;;IAEE,gCAAwC;ERimFhD;EQ/lFM;;IAEE,iCAA0C;ERimFlD;EQ/lFM;;IAEE,+BAAsC;ERimF9C;EQhnFM;IAAgC,wBAA4B;ERmnFlE;EQlnFM;;IAEE,4BAAoC;ERonF5C;EQlnFM;;IAEE,8BAAwC;ERonFhD;EQlnFM;;IAEE,+BAA0C;ERonFlD;EQlnFM;;IAEE,6BAAsC;ERonF9C;EQ5mFM;IAAwB,2BAA2B;ER+mFzD;EQ9mFM;;IAEE,+BAA+B;ERgnFvC;EQ9mFM;;IAEE,iCAAiC;ERgnFzC;EQ9mFM;;IAEE,kCAAkC;ERgnF1C;EQ9mFM;;IAEE,gCAAgC;ERgnFxC;EQ/nFM;IAAwB,0BAA2B;ERkoFzD;EQjoFM;;IAEE,8BAA+B;ERmoFvC;EQjoFM;;IAEE,gCAAiC;ERmoFzC;EQjoFM;;IAEE,iCAAkC;ERmoF1C;EQjoFM;;IAEE,+BAAgC;ERmoFxC;EQlpFM;IAAwB,wBAA2B;ERqpFzD;EQppFM;;IAEE,4BAA+B;ERspFvC;EQppFM;;IAEE,8BAAiC;ERspFzC;EQppFM;;IAEE,+BAAkC;ERspF1C;EQppFM;;IAEE,6BAAgC;ERspFxC;EQrqFM;IAAwB,0BAA2B;ERwqFzD;EQvqFM;;IAEE,8BAA+B;ERyqFvC;EQvqFM;;IAEE,gCAAiC;ERyqFzC;EQvqFM;;IAEE,iCAAkC;ERyqF1C;EQvqFM;;IAEE,+BAAgC;ERyqFxC;EQxrFM;IAAwB,wBAA2B;ER2rFzD;EQ1rFM;;IAEE,4BAA+B;ER4rFvC;EQ1rFM;;IAEE,8BAAiC;ER4rFzC;EQ1rFM;;IAEE,+BAAkC;ER4rF1C;EQ1rFM;;IAEE,6BAAgC;ER4rFxC;EQtrFE;IAAmB,uBAAuB;ERyrF5C;EQxrFE;;IAEE,2BAA2B;ER0rF/B;EQxrFE;;IAEE,6BAA6B;ER0rFjC;EQxrFE;;IAEE,8BAA8B;ER0rFlC;EQxrFE;;IAEE,4BAA4B;ER0rFhC;AACF;;AGpsFI;EKlDI;IAAgC,oBAA4B;ER2vFlE;EQ1vFM;;IAEE,wBAAoC;ER4vF5C;EQ1vFM;;IAEE,0BAAwC;ER4vFhD;EQ1vFM;;IAEE,2BAA0C;ER4vFlD;EQ1vFM;;IAEE,yBAAsC;ER4vF9C;EQ3wFM;IAAgC,0BAA4B;ER8wFlE;EQ7wFM;;IAEE,8BAAoC;ER+wF5C;EQ7wFM;;IAEE,gCAAwC;ER+wFhD;EQ7wFM;;IAEE,iCAA0C;ER+wFlD;EQ7wFM;;IAEE,+BAAsC;ER+wF9C;EQ9xFM;IAAgC,yBAA4B;ERiyFlE;EQhyFM;;IAEE,6BAAoC;ERkyF5C;EQhyFM;;IAEE,+BAAwC;ERkyFhD;EQhyFM;;IAEE,gCAA0C;ERkyFlD;EQhyFM;;IAEE,8BAAsC;ERkyF9C;EQjzFM;IAAgC,uBAA4B;ERozFlE;EQnzFM;;IAEE,2BAAoC;ERqzF5C;EQnzFM;;IAEE,6BAAwC;ERqzFhD;EQnzFM;;IAEE,8BAA0C;ERqzFlD;EQnzFM;;IAEE,4BAAsC;ERqzF9C;EQp0FM;IAAgC,yBAA4B;ERu0FlE;EQt0FM;;IAEE,6BAAoC;ERw0F5C;EQt0FM;;IAEE,+BAAwC;ERw0FhD;EQt0FM;;IAEE,gCAA0C;ERw0FlD;EQt0FM;;IAEE,8BAAsC;ERw0F9C;EQv1FM;IAAgC,uBAA4B;ER01FlE;EQz1FM;;IAEE,2BAAoC;ER21F5C;EQz1FM;;IAEE,6BAAwC;ER21FhD;EQz1FM;;IAEE,8BAA0C;ER21FlD;EQz1FM;;IAEE,4BAAsC;ER21F9C;EQ12FM;IAAgC,qBAA4B;ER62FlE;EQ52FM;;IAEE,yBAAoC;ER82F5C;EQ52FM;;IAEE,2BAAwC;ER82FhD;EQ52FM;;IAEE,4BAA0C;ER82FlD;EQ52FM;;IAEE,0BAAsC;ER82F9C;EQ73FM;IAAgC,2BAA4B;ERg4FlE;EQ/3FM;;IAEE,+BAAoC;ERi4F5C;EQ/3FM;;IAEE,iCAAwC;ERi4FhD;EQ/3FM;;IAEE,kCAA0C;ERi4FlD;EQ/3FM;;IAEE,gCAAsC;ERi4F9C;EQh5FM;IAAgC,0BAA4B;ERm5FlE;EQl5FM;;IAEE,8BAAoC;ERo5F5C;EQl5FM;;IAEE,gCAAwC;ERo5FhD;EQl5FM;;IAEE,iCAA0C;ERo5FlD;EQl5FM;;IAEE,+BAAsC;ERo5F9C;EQn6FM;IAAgC,wBAA4B;ERs6FlE;EQr6FM;;IAEE,4BAAoC;ERu6F5C;EQr6FM;;IAEE,8BAAwC;ERu6FhD;EQr6FM;;IAEE,+BAA0C;ERu6FlD;EQr6FM;;IAEE,6BAAsC;ERu6F9C;EQt7FM;IAAgC,0BAA4B;ERy7FlE;EQx7FM;;IAEE,8BAAoC;ER07F5C;EQx7FM;;IAEE,gCAAwC;ER07FhD;EQx7FM;;IAEE,iCAA0C;ER07FlD;EQx7FM;;IAEE,+BAAsC;ER07F9C;EQz8FM;IAAgC,wBAA4B;ER48FlE;EQ38FM;;IAEE,4BAAoC;ER68F5C;EQ38FM;;IAEE,8BAAwC;ER68FhD;EQ38FM;;IAEE,+BAA0C;ER68FlD;EQ38FM;;IAEE,6BAAsC;ER68F9C;EQr8FM;IAAwB,2BAA2B;ERw8FzD;EQv8FM;;IAEE,+BAA+B;ERy8FvC;EQv8FM;;IAEE,iCAAiC;ERy8FzC;EQv8FM;;IAEE,kCAAkC;ERy8F1C;EQv8FM;;IAEE,gCAAgC;ERy8FxC;EQx9FM;IAAwB,0BAA2B;ER29FzD;EQ19FM;;IAEE,8BAA+B;ER49FvC;EQ19FM;;IAEE,gCAAiC;ER49FzC;EQ19FM;;IAEE,iCAAkC;ER49F1C;EQ19FM;;IAEE,+BAAgC;ER49FxC;EQ3+FM;IAAwB,wBAA2B;ER8+FzD;EQ7+FM;;IAEE,4BAA+B;ER++FvC;EQ7+FM;;IAEE,8BAAiC;ER++FzC;EQ7+FM;;IAEE,+BAAkC;ER++F1C;EQ7+FM;;IAEE,6BAAgC;ER++FxC;EQ9/FM;IAAwB,0BAA2B;ERigGzD;EQhgGM;;IAEE,8BAA+B;ERkgGvC;EQhgGM;;IAEE,gCAAiC;ERkgGzC;EQhgGM;;IAEE,iCAAkC;ERkgG1C;EQhgGM;;IAEE,+BAAgC;ERkgGxC;EQjhGM;IAAwB,wBAA2B;ERohGzD;EQnhGM;;IAEE,4BAA+B;ERqhGvC;EQnhGM;;IAEE,8BAAiC;ERqhGzC;EQnhGM;;IAEE,+BAAkC;ERqhG1C;EQnhGM;;IAEE,6BAAgC;ERqhGxC;EQ/gGE;IAAmB,uBAAuB;ERkhG5C;EQjhGE;;IAEE,2BAA2B;ERmhG/B;EQjhGE;;IAEE,6BAA6B;ERmhGjC;EQjhGE;;IAEE,8BAA8B;ERmhGlC;EQjhGE;;IAEE,4BAA4B;ERmhGhC;AACF;;AG7hGI;EKlDI;IAAgC,oBAA4B;ERolGlE;EQnlGM;;IAEE,wBAAoC;ERqlG5C;EQnlGM;;IAEE,0BAAwC;ERqlGhD;EQnlGM;;IAEE,2BAA0C;ERqlGlD;EQnlGM;;IAEE,yBAAsC;ERqlG9C;EQpmGM;IAAgC,0BAA4B;ERumGlE;EQtmGM;;IAEE,8BAAoC;ERwmG5C;EQtmGM;;IAEE,gCAAwC;ERwmGhD;EQtmGM;;IAEE,iCAA0C;ERwmGlD;EQtmGM;;IAEE,+BAAsC;ERwmG9C;EQvnGM;IAAgC,yBAA4B;ER0nGlE;EQznGM;;IAEE,6BAAoC;ER2nG5C;EQznGM;;IAEE,+BAAwC;ER2nGhD;EQznGM;;IAEE,gCAA0C;ER2nGlD;EQznGM;;IAEE,8BAAsC;ER2nG9C;EQ1oGM;IAAgC,uBAA4B;ER6oGlE;EQ5oGM;;IAEE,2BAAoC;ER8oG5C;EQ5oGM;;IAEE,6BAAwC;ER8oGhD;EQ5oGM;;IAEE,8BAA0C;ER8oGlD;EQ5oGM;;IAEE,4BAAsC;ER8oG9C;EQ7pGM;IAAgC,yBAA4B;ERgqGlE;EQ/pGM;;IAEE,6BAAoC;ERiqG5C;EQ/pGM;;IAEE,+BAAwC;ERiqGhD;EQ/pGM;;IAEE,gCAA0C;ERiqGlD;EQ/pGM;;IAEE,8BAAsC;ERiqG9C;EQhrGM;IAAgC,uBAA4B;ERmrGlE;EQlrGM;;IAEE,2BAAoC;ERorG5C;EQlrGM;;IAEE,6BAAwC;ERorGhD;EQlrGM;;IAEE,8BAA0C;ERorGlD;EQlrGM;;IAEE,4BAAsC;ERorG9C;EQnsGM;IAAgC,qBAA4B;ERssGlE;EQrsGM;;IAEE,yBAAoC;ERusG5C;EQrsGM;;IAEE,2BAAwC;ERusGhD;EQrsGM;;IAEE,4BAA0C;ERusGlD;EQrsGM;;IAEE,0BAAsC;ERusG9C;EQttGM;IAAgC,2BAA4B;ERytGlE;EQxtGM;;IAEE,+BAAoC;ER0tG5C;EQxtGM;;IAEE,iCAAwC;ER0tGhD;EQxtGM;;IAEE,kCAA0C;ER0tGlD;EQxtGM;;IAEE,gCAAsC;ER0tG9C;EQzuGM;IAAgC,0BAA4B;ER4uGlE;EQ3uGM;;IAEE,8BAAoC;ER6uG5C;EQ3uGM;;IAEE,gCAAwC;ER6uGhD;EQ3uGM;;IAEE,iCAA0C;ER6uGlD;EQ3uGM;;IAEE,+BAAsC;ER6uG9C;EQ5vGM;IAAgC,wBAA4B;ER+vGlE;EQ9vGM;;IAEE,4BAAoC;ERgwG5C;EQ9vGM;;IAEE,8BAAwC;ERgwGhD;EQ9vGM;;IAEE,+BAA0C;ERgwGlD;EQ9vGM;;IAEE,6BAAsC;ERgwG9C;EQ/wGM;IAAgC,0BAA4B;ERkxGlE;EQjxGM;;IAEE,8BAAoC;ERmxG5C;EQjxGM;;IAEE,gCAAwC;ERmxGhD;EQjxGM;;IAEE,iCAA0C;ERmxGlD;EQjxGM;;IAEE,+BAAsC;ERmxG9C;EQlyGM;IAAgC,wBAA4B;ERqyGlE;EQpyGM;;IAEE,4BAAoC;ERsyG5C;EQpyGM;;IAEE,8BAAwC;ERsyGhD;EQpyGM;;IAEE,+BAA0C;ERsyGlD;EQpyGM;;IAEE,6BAAsC;ERsyG9C;EQ9xGM;IAAwB,2BAA2B;ERiyGzD;EQhyGM;;IAEE,+BAA+B;ERkyGvC;EQhyGM;;IAEE,iCAAiC;ERkyGzC;EQhyGM;;IAEE,kCAAkC;ERkyG1C;EQhyGM;;IAEE,gCAAgC;ERkyGxC;EQjzGM;IAAwB,0BAA2B;ERozGzD;EQnzGM;;IAEE,8BAA+B;ERqzGvC;EQnzGM;;IAEE,gCAAiC;ERqzGzC;EQnzGM;;IAEE,iCAAkC;ERqzG1C;EQnzGM;;IAEE,+BAAgC;ERqzGxC;EQp0GM;IAAwB,wBAA2B;ERu0GzD;EQt0GM;;IAEE,4BAA+B;ERw0GvC;EQt0GM;;IAEE,8BAAiC;ERw0GzC;EQt0GM;;IAEE,+BAAkC;ERw0G1C;EQt0GM;;IAEE,6BAAgC;ERw0GxC;EQv1GM;IAAwB,0BAA2B;ER01GzD;EQz1GM;;IAEE,8BAA+B;ER21GvC;EQz1GM;;IAEE,gCAAiC;ER21GzC;EQz1GM;;IAEE,iCAAkC;ER21G1C;EQz1GM;;IAEE,+BAAgC;ER21GxC;EQ12GM;IAAwB,wBAA2B;ER62GzD;EQ52GM;;IAEE,4BAA+B;ER82GvC;EQ52GM;;IAEE,8BAAiC;ER82GzC;EQ52GM;;IAEE,+BAAkC;ER82G1C;EQ52GM;;IAEE,6BAAgC;ER82GxC;EQx2GE;IAAmB,uBAAuB;ER22G5C;EQ12GE;;IAEE,2BAA2B;ER42G/B;EQ12GE;;IAEE,6BAA6B;ER42GjC;EQ12GE;;IAEE,8BAA8B;ER42GlC;EQ12GE;;IAEE,4BAA4B;ER42GhC;AACF","file":"bootstrap-grid.css","sourcesContent":["/*!\n * Bootstrap Grid v4.5.3 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors\n * Copyright 2011-2020 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\n\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n@import \"functions\";\n@import \"variables\";\n\n@import \"mixins/breakpoints\";\n@import \"mixins/grid-framework\";\n@import \"mixins/grid\";\n\n@import \"grid\";\n@import \"utilities/display\";\n@import \"utilities/flex\";\n@import \"utilities/spacing\";\n","/*!\n * Bootstrap Grid v4.5.3 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors\n * Copyright 2011-2020 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n.container,\n.container-fluid,\n.container-sm,\n.container-md,\n.container-lg,\n.container-xl {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n@media (min-width: 576px) {\n .container, .container-sm {\n max-width: 540px;\n }\n}\n\n@media (min-width: 768px) {\n .container, .container-sm, .container-md {\n max-width: 720px;\n }\n}\n\n@media (min-width: 992px) {\n .container, .container-sm, .container-md, .container-lg {\n max-width: 960px;\n }\n}\n\n@media (min-width: 1200px) {\n .container, .container-sm, .container-md, .container-lg, .container-xl {\n max-width: 1140px;\n }\n}\n\n.row {\n display: flex;\n flex-wrap: wrap;\n margin-right: -15px;\n margin-left: -15px;\n}\n\n.no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n\n.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n position: relative;\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n}\n\n.col {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n}\n\n.row-cols-1 > * {\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.row-cols-2 > * {\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.row-cols-3 > * {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.row-cols-4 > * {\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.row-cols-5 > * {\n flex: 0 0 20%;\n max-width: 20%;\n}\n\n.row-cols-6 > * {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n}\n\n.col-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n}\n\n.col-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-3 {\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.col-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.col-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n}\n\n.col-6 {\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.col-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n}\n\n.col-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n}\n\n.col-9 {\n flex: 0 0 75%;\n max-width: 75%;\n}\n\n.col-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n}\n\n.col-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n}\n\n.col-12 {\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.order-first {\n order: -1;\n}\n\n.order-last {\n order: 13;\n}\n\n.order-0 {\n order: 0;\n}\n\n.order-1 {\n order: 1;\n}\n\n.order-2 {\n order: 2;\n}\n\n.order-3 {\n order: 3;\n}\n\n.order-4 {\n order: 4;\n}\n\n.order-5 {\n order: 5;\n}\n\n.order-6 {\n order: 6;\n}\n\n.order-7 {\n order: 7;\n}\n\n.order-8 {\n order: 8;\n}\n\n.order-9 {\n order: 9;\n}\n\n.order-10 {\n order: 10;\n}\n\n.order-11 {\n order: 11;\n}\n\n.order-12 {\n order: 12;\n}\n\n.offset-1 {\n margin-left: 8.333333%;\n}\n\n.offset-2 {\n margin-left: 16.666667%;\n}\n\n.offset-3 {\n margin-left: 25%;\n}\n\n.offset-4 {\n margin-left: 33.333333%;\n}\n\n.offset-5 {\n margin-left: 41.666667%;\n}\n\n.offset-6 {\n margin-left: 50%;\n}\n\n.offset-7 {\n margin-left: 58.333333%;\n}\n\n.offset-8 {\n margin-left: 66.666667%;\n}\n\n.offset-9 {\n margin-left: 75%;\n}\n\n.offset-10 {\n margin-left: 83.333333%;\n}\n\n.offset-11 {\n margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n .col-sm {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .row-cols-sm-1 > * {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .row-cols-sm-2 > * {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .row-cols-sm-3 > * {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .row-cols-sm-4 > * {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .row-cols-sm-5 > * {\n flex: 0 0 20%;\n max-width: 20%;\n }\n .row-cols-sm-6 > * {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-sm-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-sm-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-sm-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-sm-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-sm-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-sm-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-sm-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-sm-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-sm-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-sm-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-sm-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-sm-first {\n order: -1;\n }\n .order-sm-last {\n order: 13;\n }\n .order-sm-0 {\n order: 0;\n }\n .order-sm-1 {\n order: 1;\n }\n .order-sm-2 {\n order: 2;\n }\n .order-sm-3 {\n order: 3;\n }\n .order-sm-4 {\n order: 4;\n }\n .order-sm-5 {\n order: 5;\n }\n .order-sm-6 {\n order: 6;\n }\n .order-sm-7 {\n order: 7;\n }\n .order-sm-8 {\n order: 8;\n }\n .order-sm-9 {\n order: 9;\n }\n .order-sm-10 {\n order: 10;\n }\n .order-sm-11 {\n order: 11;\n }\n .order-sm-12 {\n order: 12;\n }\n .offset-sm-0 {\n margin-left: 0;\n }\n .offset-sm-1 {\n margin-left: 8.333333%;\n }\n .offset-sm-2 {\n margin-left: 16.666667%;\n }\n .offset-sm-3 {\n margin-left: 25%;\n }\n .offset-sm-4 {\n margin-left: 33.333333%;\n }\n .offset-sm-5 {\n margin-left: 41.666667%;\n }\n .offset-sm-6 {\n margin-left: 50%;\n }\n .offset-sm-7 {\n margin-left: 58.333333%;\n }\n .offset-sm-8 {\n margin-left: 66.666667%;\n }\n .offset-sm-9 {\n margin-left: 75%;\n }\n .offset-sm-10 {\n margin-left: 83.333333%;\n }\n .offset-sm-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 768px) {\n .col-md {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .row-cols-md-1 > * {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .row-cols-md-2 > * {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .row-cols-md-3 > * {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .row-cols-md-4 > * {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .row-cols-md-5 > * {\n flex: 0 0 20%;\n max-width: 20%;\n }\n .row-cols-md-6 > * {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-md-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-md-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-md-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-md-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-md-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-md-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-md-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-md-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-md-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-md-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-md-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-md-first {\n order: -1;\n }\n .order-md-last {\n order: 13;\n }\n .order-md-0 {\n order: 0;\n }\n .order-md-1 {\n order: 1;\n }\n .order-md-2 {\n order: 2;\n }\n .order-md-3 {\n order: 3;\n }\n .order-md-4 {\n order: 4;\n }\n .order-md-5 {\n order: 5;\n }\n .order-md-6 {\n order: 6;\n }\n .order-md-7 {\n order: 7;\n }\n .order-md-8 {\n order: 8;\n }\n .order-md-9 {\n order: 9;\n }\n .order-md-10 {\n order: 10;\n }\n .order-md-11 {\n order: 11;\n }\n .order-md-12 {\n order: 12;\n }\n .offset-md-0 {\n margin-left: 0;\n }\n .offset-md-1 {\n margin-left: 8.333333%;\n }\n .offset-md-2 {\n margin-left: 16.666667%;\n }\n .offset-md-3 {\n margin-left: 25%;\n }\n .offset-md-4 {\n margin-left: 33.333333%;\n }\n .offset-md-5 {\n margin-left: 41.666667%;\n }\n .offset-md-6 {\n margin-left: 50%;\n }\n .offset-md-7 {\n margin-left: 58.333333%;\n }\n .offset-md-8 {\n margin-left: 66.666667%;\n }\n .offset-md-9 {\n margin-left: 75%;\n }\n .offset-md-10 {\n margin-left: 83.333333%;\n }\n .offset-md-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 992px) {\n .col-lg {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .row-cols-lg-1 > * {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .row-cols-lg-2 > * {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .row-cols-lg-3 > * {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .row-cols-lg-4 > * {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .row-cols-lg-5 > * {\n flex: 0 0 20%;\n max-width: 20%;\n }\n .row-cols-lg-6 > * {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-lg-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-lg-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-lg-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-lg-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-lg-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-lg-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-lg-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-lg-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-lg-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-lg-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-lg-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-lg-first {\n order: -1;\n }\n .order-lg-last {\n order: 13;\n }\n .order-lg-0 {\n order: 0;\n }\n .order-lg-1 {\n order: 1;\n }\n .order-lg-2 {\n order: 2;\n }\n .order-lg-3 {\n order: 3;\n }\n .order-lg-4 {\n order: 4;\n }\n .order-lg-5 {\n order: 5;\n }\n .order-lg-6 {\n order: 6;\n }\n .order-lg-7 {\n order: 7;\n }\n .order-lg-8 {\n order: 8;\n }\n .order-lg-9 {\n order: 9;\n }\n .order-lg-10 {\n order: 10;\n }\n .order-lg-11 {\n order: 11;\n }\n .order-lg-12 {\n order: 12;\n }\n .offset-lg-0 {\n margin-left: 0;\n }\n .offset-lg-1 {\n margin-left: 8.333333%;\n }\n .offset-lg-2 {\n margin-left: 16.666667%;\n }\n .offset-lg-3 {\n margin-left: 25%;\n }\n .offset-lg-4 {\n margin-left: 33.333333%;\n }\n .offset-lg-5 {\n margin-left: 41.666667%;\n }\n .offset-lg-6 {\n margin-left: 50%;\n }\n .offset-lg-7 {\n margin-left: 58.333333%;\n }\n .offset-lg-8 {\n margin-left: 66.666667%;\n }\n .offset-lg-9 {\n margin-left: 75%;\n }\n .offset-lg-10 {\n margin-left: 83.333333%;\n }\n .offset-lg-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 1200px) {\n .col-xl {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .row-cols-xl-1 > * {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .row-cols-xl-2 > * {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .row-cols-xl-3 > * {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .row-cols-xl-4 > * {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .row-cols-xl-5 > * {\n flex: 0 0 20%;\n max-width: 20%;\n }\n .row-cols-xl-6 > * {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-xl-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-xl-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-xl-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-xl-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-xl-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-xl-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-xl-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-xl-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-xl-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-xl-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-xl-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-xl-first {\n order: -1;\n }\n .order-xl-last {\n order: 13;\n }\n .order-xl-0 {\n order: 0;\n }\n .order-xl-1 {\n order: 1;\n }\n .order-xl-2 {\n order: 2;\n }\n .order-xl-3 {\n order: 3;\n }\n .order-xl-4 {\n order: 4;\n }\n .order-xl-5 {\n order: 5;\n }\n .order-xl-6 {\n order: 6;\n }\n .order-xl-7 {\n order: 7;\n }\n .order-xl-8 {\n order: 8;\n }\n .order-xl-9 {\n order: 9;\n }\n .order-xl-10 {\n order: 10;\n }\n .order-xl-11 {\n order: 11;\n }\n .order-xl-12 {\n order: 12;\n }\n .offset-xl-0 {\n margin-left: 0;\n }\n .offset-xl-1 {\n margin-left: 8.333333%;\n }\n .offset-xl-2 {\n margin-left: 16.666667%;\n }\n .offset-xl-3 {\n margin-left: 25%;\n }\n .offset-xl-4 {\n margin-left: 33.333333%;\n }\n .offset-xl-5 {\n margin-left: 41.666667%;\n }\n .offset-xl-6 {\n margin-left: 50%;\n }\n .offset-xl-7 {\n margin-left: 58.333333%;\n }\n .offset-xl-8 {\n margin-left: 66.666667%;\n }\n .offset-xl-9 {\n margin-left: 75%;\n }\n .offset-xl-10 {\n margin-left: 83.333333%;\n }\n .offset-xl-11 {\n margin-left: 91.666667%;\n }\n}\n\n.d-none {\n display: none !important;\n}\n\n.d-inline {\n display: inline !important;\n}\n\n.d-inline-block {\n display: inline-block !important;\n}\n\n.d-block {\n display: block !important;\n}\n\n.d-table {\n display: table !important;\n}\n\n.d-table-row {\n display: table-row !important;\n}\n\n.d-table-cell {\n display: table-cell !important;\n}\n\n.d-flex {\n display: flex !important;\n}\n\n.d-inline-flex {\n display: inline-flex !important;\n}\n\n@media (min-width: 576px) {\n .d-sm-none {\n display: none !important;\n }\n .d-sm-inline {\n display: inline !important;\n }\n .d-sm-inline-block {\n display: inline-block !important;\n }\n .d-sm-block {\n display: block !important;\n }\n .d-sm-table {\n display: table !important;\n }\n .d-sm-table-row {\n display: table-row !important;\n }\n .d-sm-table-cell {\n display: table-cell !important;\n }\n .d-sm-flex {\n display: flex !important;\n }\n .d-sm-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 768px) {\n .d-md-none {\n display: none !important;\n }\n .d-md-inline {\n display: inline !important;\n }\n .d-md-inline-block {\n display: inline-block !important;\n }\n .d-md-block {\n display: block !important;\n }\n .d-md-table {\n display: table !important;\n }\n .d-md-table-row {\n display: table-row !important;\n }\n .d-md-table-cell {\n display: table-cell !important;\n }\n .d-md-flex {\n display: flex !important;\n }\n .d-md-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 992px) {\n .d-lg-none {\n display: none !important;\n }\n .d-lg-inline {\n display: inline !important;\n }\n .d-lg-inline-block {\n display: inline-block !important;\n }\n .d-lg-block {\n display: block !important;\n }\n .d-lg-table {\n display: table !important;\n }\n .d-lg-table-row {\n display: table-row !important;\n }\n .d-lg-table-cell {\n display: table-cell !important;\n }\n .d-lg-flex {\n display: flex !important;\n }\n .d-lg-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 1200px) {\n .d-xl-none {\n display: none !important;\n }\n .d-xl-inline {\n display: inline !important;\n }\n .d-xl-inline-block {\n display: inline-block !important;\n }\n .d-xl-block {\n display: block !important;\n }\n .d-xl-table {\n display: table !important;\n }\n .d-xl-table-row {\n display: table-row !important;\n }\n .d-xl-table-cell {\n display: table-cell !important;\n }\n .d-xl-flex {\n display: flex !important;\n }\n .d-xl-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media print {\n .d-print-none {\n display: none !important;\n }\n .d-print-inline {\n display: inline !important;\n }\n .d-print-inline-block {\n display: inline-block !important;\n }\n .d-print-block {\n display: block !important;\n }\n .d-print-table {\n display: table !important;\n }\n .d-print-table-row {\n display: table-row !important;\n }\n .d-print-table-cell {\n display: table-cell !important;\n }\n .d-print-flex {\n display: flex !important;\n }\n .d-print-inline-flex {\n display: inline-flex !important;\n }\n}\n\n.flex-row {\n flex-direction: row !important;\n}\n\n.flex-column {\n flex-direction: column !important;\n}\n\n.flex-row-reverse {\n flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n}\n\n.flex-fill {\n flex: 1 1 auto !important;\n}\n\n.flex-grow-0 {\n flex-grow: 0 !important;\n}\n\n.flex-grow-1 {\n flex-grow: 1 !important;\n}\n\n.flex-shrink-0 {\n flex-shrink: 0 !important;\n}\n\n.flex-shrink-1 {\n flex-shrink: 1 !important;\n}\n\n.justify-content-start {\n justify-content: flex-start !important;\n}\n\n.justify-content-end {\n justify-content: flex-end !important;\n}\n\n.justify-content-center {\n justify-content: center !important;\n}\n\n.justify-content-between {\n justify-content: space-between !important;\n}\n\n.justify-content-around {\n justify-content: space-around !important;\n}\n\n.align-items-start {\n align-items: flex-start !important;\n}\n\n.align-items-end {\n align-items: flex-end !important;\n}\n\n.align-items-center {\n align-items: center !important;\n}\n\n.align-items-baseline {\n align-items: baseline !important;\n}\n\n.align-items-stretch {\n align-items: stretch !important;\n}\n\n.align-content-start {\n align-content: flex-start !important;\n}\n\n.align-content-end {\n align-content: flex-end !important;\n}\n\n.align-content-center {\n align-content: center !important;\n}\n\n.align-content-between {\n align-content: space-between !important;\n}\n\n.align-content-around {\n align-content: space-around !important;\n}\n\n.align-content-stretch {\n align-content: stretch !important;\n}\n\n.align-self-auto {\n align-self: auto !important;\n}\n\n.align-self-start {\n align-self: flex-start !important;\n}\n\n.align-self-end {\n align-self: flex-end !important;\n}\n\n.align-self-center {\n align-self: center !important;\n}\n\n.align-self-baseline {\n align-self: baseline !important;\n}\n\n.align-self-stretch {\n align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n .flex-sm-row {\n flex-direction: row !important;\n }\n .flex-sm-column {\n flex-direction: column !important;\n }\n .flex-sm-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-sm-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-sm-wrap {\n flex-wrap: wrap !important;\n }\n .flex-sm-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-sm-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-sm-fill {\n flex: 1 1 auto !important;\n }\n .flex-sm-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-sm-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-sm-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-sm-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-sm-start {\n justify-content: flex-start !important;\n }\n .justify-content-sm-end {\n justify-content: flex-end !important;\n }\n .justify-content-sm-center {\n justify-content: center !important;\n }\n .justify-content-sm-between {\n justify-content: space-between !important;\n }\n .justify-content-sm-around {\n justify-content: space-around !important;\n }\n .align-items-sm-start {\n align-items: flex-start !important;\n }\n .align-items-sm-end {\n align-items: flex-end !important;\n }\n .align-items-sm-center {\n align-items: center !important;\n }\n .align-items-sm-baseline {\n align-items: baseline !important;\n }\n .align-items-sm-stretch {\n align-items: stretch !important;\n }\n .align-content-sm-start {\n align-content: flex-start !important;\n }\n .align-content-sm-end {\n align-content: flex-end !important;\n }\n .align-content-sm-center {\n align-content: center !important;\n }\n .align-content-sm-between {\n align-content: space-between !important;\n }\n .align-content-sm-around {\n align-content: space-around !important;\n }\n .align-content-sm-stretch {\n align-content: stretch !important;\n }\n .align-self-sm-auto {\n align-self: auto !important;\n }\n .align-self-sm-start {\n align-self: flex-start !important;\n }\n .align-self-sm-end {\n align-self: flex-end !important;\n }\n .align-self-sm-center {\n align-self: center !important;\n }\n .align-self-sm-baseline {\n align-self: baseline !important;\n }\n .align-self-sm-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 768px) {\n .flex-md-row {\n flex-direction: row !important;\n }\n .flex-md-column {\n flex-direction: column !important;\n }\n .flex-md-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-md-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-md-wrap {\n flex-wrap: wrap !important;\n }\n .flex-md-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-md-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-md-fill {\n flex: 1 1 auto !important;\n }\n .flex-md-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-md-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-md-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-md-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-md-start {\n justify-content: flex-start !important;\n }\n .justify-content-md-end {\n justify-content: flex-end !important;\n }\n .justify-content-md-center {\n justify-content: center !important;\n }\n .justify-content-md-between {\n justify-content: space-between !important;\n }\n .justify-content-md-around {\n justify-content: space-around !important;\n }\n .align-items-md-start {\n align-items: flex-start !important;\n }\n .align-items-md-end {\n align-items: flex-end !important;\n }\n .align-items-md-center {\n align-items: center !important;\n }\n .align-items-md-baseline {\n align-items: baseline !important;\n }\n .align-items-md-stretch {\n align-items: stretch !important;\n }\n .align-content-md-start {\n align-content: flex-start !important;\n }\n .align-content-md-end {\n align-content: flex-end !important;\n }\n .align-content-md-center {\n align-content: center !important;\n }\n .align-content-md-between {\n align-content: space-between !important;\n }\n .align-content-md-around {\n align-content: space-around !important;\n }\n .align-content-md-stretch {\n align-content: stretch !important;\n }\n .align-self-md-auto {\n align-self: auto !important;\n }\n .align-self-md-start {\n align-self: flex-start !important;\n }\n .align-self-md-end {\n align-self: flex-end !important;\n }\n .align-self-md-center {\n align-self: center !important;\n }\n .align-self-md-baseline {\n align-self: baseline !important;\n }\n .align-self-md-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 992px) {\n .flex-lg-row {\n flex-direction: row !important;\n }\n .flex-lg-column {\n flex-direction: column !important;\n }\n .flex-lg-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-lg-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-lg-wrap {\n flex-wrap: wrap !important;\n }\n .flex-lg-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-lg-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-lg-fill {\n flex: 1 1 auto !important;\n }\n .flex-lg-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-lg-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-lg-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-lg-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-lg-start {\n justify-content: flex-start !important;\n }\n .justify-content-lg-end {\n justify-content: flex-end !important;\n }\n .justify-content-lg-center {\n justify-content: center !important;\n }\n .justify-content-lg-between {\n justify-content: space-between !important;\n }\n .justify-content-lg-around {\n justify-content: space-around !important;\n }\n .align-items-lg-start {\n align-items: flex-start !important;\n }\n .align-items-lg-end {\n align-items: flex-end !important;\n }\n .align-items-lg-center {\n align-items: center !important;\n }\n .align-items-lg-baseline {\n align-items: baseline !important;\n }\n .align-items-lg-stretch {\n align-items: stretch !important;\n }\n .align-content-lg-start {\n align-content: flex-start !important;\n }\n .align-content-lg-end {\n align-content: flex-end !important;\n }\n .align-content-lg-center {\n align-content: center !important;\n }\n .align-content-lg-between {\n align-content: space-between !important;\n }\n .align-content-lg-around {\n align-content: space-around !important;\n }\n .align-content-lg-stretch {\n align-content: stretch !important;\n }\n .align-self-lg-auto {\n align-self: auto !important;\n }\n .align-self-lg-start {\n align-self: flex-start !important;\n }\n .align-self-lg-end {\n align-self: flex-end !important;\n }\n .align-self-lg-center {\n align-self: center !important;\n }\n .align-self-lg-baseline {\n align-self: baseline !important;\n }\n .align-self-lg-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 1200px) {\n .flex-xl-row {\n flex-direction: row !important;\n }\n .flex-xl-column {\n flex-direction: column !important;\n }\n .flex-xl-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-xl-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-xl-wrap {\n flex-wrap: wrap !important;\n }\n .flex-xl-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-xl-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-xl-fill {\n flex: 1 1 auto !important;\n }\n .flex-xl-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-xl-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-xl-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-xl-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-xl-start {\n justify-content: flex-start !important;\n }\n .justify-content-xl-end {\n justify-content: flex-end !important;\n }\n .justify-content-xl-center {\n justify-content: center !important;\n }\n .justify-content-xl-between {\n justify-content: space-between !important;\n }\n .justify-content-xl-around {\n justify-content: space-around !important;\n }\n .align-items-xl-start {\n align-items: flex-start !important;\n }\n .align-items-xl-end {\n align-items: flex-end !important;\n }\n .align-items-xl-center {\n align-items: center !important;\n }\n .align-items-xl-baseline {\n align-items: baseline !important;\n }\n .align-items-xl-stretch {\n align-items: stretch !important;\n }\n .align-content-xl-start {\n align-content: flex-start !important;\n }\n .align-content-xl-end {\n align-content: flex-end !important;\n }\n .align-content-xl-center {\n align-content: center !important;\n }\n .align-content-xl-between {\n align-content: space-between !important;\n }\n .align-content-xl-around {\n align-content: space-around !important;\n }\n .align-content-xl-stretch {\n align-content: stretch !important;\n }\n .align-self-xl-auto {\n align-self: auto !important;\n }\n .align-self-xl-start {\n align-self: flex-start !important;\n }\n .align-self-xl-end {\n align-self: flex-end !important;\n }\n .align-self-xl-center {\n align-self: center !important;\n }\n .align-self-xl-baseline {\n align-self: baseline !important;\n }\n .align-self-xl-stretch {\n align-self: stretch !important;\n }\n}\n\n.m-0 {\n margin: 0 !important;\n}\n\n.mt-0,\n.my-0 {\n margin-top: 0 !important;\n}\n\n.mr-0,\n.mx-0 {\n margin-right: 0 !important;\n}\n\n.mb-0,\n.my-0 {\n margin-bottom: 0 !important;\n}\n\n.ml-0,\n.mx-0 {\n margin-left: 0 !important;\n}\n\n.m-1 {\n margin: 0.25rem !important;\n}\n\n.mt-1,\n.my-1 {\n margin-top: 0.25rem !important;\n}\n\n.mr-1,\n.mx-1 {\n margin-right: 0.25rem !important;\n}\n\n.mb-1,\n.my-1 {\n margin-bottom: 0.25rem !important;\n}\n\n.ml-1,\n.mx-1 {\n margin-left: 0.25rem !important;\n}\n\n.m-2 {\n margin: 0.5rem !important;\n}\n\n.mt-2,\n.my-2 {\n margin-top: 0.5rem !important;\n}\n\n.mr-2,\n.mx-2 {\n margin-right: 0.5rem !important;\n}\n\n.mb-2,\n.my-2 {\n margin-bottom: 0.5rem !important;\n}\n\n.ml-2,\n.mx-2 {\n margin-left: 0.5rem !important;\n}\n\n.m-3 {\n margin: 1rem !important;\n}\n\n.mt-3,\n.my-3 {\n margin-top: 1rem !important;\n}\n\n.mr-3,\n.mx-3 {\n margin-right: 1rem !important;\n}\n\n.mb-3,\n.my-3 {\n margin-bottom: 1rem !important;\n}\n\n.ml-3,\n.mx-3 {\n margin-left: 1rem !important;\n}\n\n.m-4 {\n margin: 1.5rem !important;\n}\n\n.mt-4,\n.my-4 {\n margin-top: 1.5rem !important;\n}\n\n.mr-4,\n.mx-4 {\n margin-right: 1.5rem !important;\n}\n\n.mb-4,\n.my-4 {\n margin-bottom: 1.5rem !important;\n}\n\n.ml-4,\n.mx-4 {\n margin-left: 1.5rem !important;\n}\n\n.m-5 {\n margin: 3rem !important;\n}\n\n.mt-5,\n.my-5 {\n margin-top: 3rem !important;\n}\n\n.mr-5,\n.mx-5 {\n margin-right: 3rem !important;\n}\n\n.mb-5,\n.my-5 {\n margin-bottom: 3rem !important;\n}\n\n.ml-5,\n.mx-5 {\n margin-left: 3rem !important;\n}\n\n.p-0 {\n padding: 0 !important;\n}\n\n.pt-0,\n.py-0 {\n padding-top: 0 !important;\n}\n\n.pr-0,\n.px-0 {\n padding-right: 0 !important;\n}\n\n.pb-0,\n.py-0 {\n padding-bottom: 0 !important;\n}\n\n.pl-0,\n.px-0 {\n padding-left: 0 !important;\n}\n\n.p-1 {\n padding: 0.25rem !important;\n}\n\n.pt-1,\n.py-1 {\n padding-top: 0.25rem !important;\n}\n\n.pr-1,\n.px-1 {\n padding-right: 0.25rem !important;\n}\n\n.pb-1,\n.py-1 {\n padding-bottom: 0.25rem !important;\n}\n\n.pl-1,\n.px-1 {\n padding-left: 0.25rem !important;\n}\n\n.p-2 {\n padding: 0.5rem !important;\n}\n\n.pt-2,\n.py-2 {\n padding-top: 0.5rem !important;\n}\n\n.pr-2,\n.px-2 {\n padding-right: 0.5rem !important;\n}\n\n.pb-2,\n.py-2 {\n padding-bottom: 0.5rem !important;\n}\n\n.pl-2,\n.px-2 {\n padding-left: 0.5rem !important;\n}\n\n.p-3 {\n padding: 1rem !important;\n}\n\n.pt-3,\n.py-3 {\n padding-top: 1rem !important;\n}\n\n.pr-3,\n.px-3 {\n padding-right: 1rem !important;\n}\n\n.pb-3,\n.py-3 {\n padding-bottom: 1rem !important;\n}\n\n.pl-3,\n.px-3 {\n padding-left: 1rem !important;\n}\n\n.p-4 {\n padding: 1.5rem !important;\n}\n\n.pt-4,\n.py-4 {\n padding-top: 1.5rem !important;\n}\n\n.pr-4,\n.px-4 {\n padding-right: 1.5rem !important;\n}\n\n.pb-4,\n.py-4 {\n padding-bottom: 1.5rem !important;\n}\n\n.pl-4,\n.px-4 {\n padding-left: 1.5rem !important;\n}\n\n.p-5 {\n padding: 3rem !important;\n}\n\n.pt-5,\n.py-5 {\n padding-top: 3rem !important;\n}\n\n.pr-5,\n.px-5 {\n padding-right: 3rem !important;\n}\n\n.pb-5,\n.py-5 {\n padding-bottom: 3rem !important;\n}\n\n.pl-5,\n.px-5 {\n padding-left: 3rem !important;\n}\n\n.m-n1 {\n margin: -0.25rem !important;\n}\n\n.mt-n1,\n.my-n1 {\n margin-top: -0.25rem !important;\n}\n\n.mr-n1,\n.mx-n1 {\n margin-right: -0.25rem !important;\n}\n\n.mb-n1,\n.my-n1 {\n margin-bottom: -0.25rem !important;\n}\n\n.ml-n1,\n.mx-n1 {\n margin-left: -0.25rem !important;\n}\n\n.m-n2 {\n margin: -0.5rem !important;\n}\n\n.mt-n2,\n.my-n2 {\n margin-top: -0.5rem !important;\n}\n\n.mr-n2,\n.mx-n2 {\n margin-right: -0.5rem !important;\n}\n\n.mb-n2,\n.my-n2 {\n margin-bottom: -0.5rem !important;\n}\n\n.ml-n2,\n.mx-n2 {\n margin-left: -0.5rem !important;\n}\n\n.m-n3 {\n margin: -1rem !important;\n}\n\n.mt-n3,\n.my-n3 {\n margin-top: -1rem !important;\n}\n\n.mr-n3,\n.mx-n3 {\n margin-right: -1rem !important;\n}\n\n.mb-n3,\n.my-n3 {\n margin-bottom: -1rem !important;\n}\n\n.ml-n3,\n.mx-n3 {\n margin-left: -1rem !important;\n}\n\n.m-n4 {\n margin: -1.5rem !important;\n}\n\n.mt-n4,\n.my-n4 {\n margin-top: -1.5rem !important;\n}\n\n.mr-n4,\n.mx-n4 {\n margin-right: -1.5rem !important;\n}\n\n.mb-n4,\n.my-n4 {\n margin-bottom: -1.5rem !important;\n}\n\n.ml-n4,\n.mx-n4 {\n margin-left: -1.5rem !important;\n}\n\n.m-n5 {\n margin: -3rem !important;\n}\n\n.mt-n5,\n.my-n5 {\n margin-top: -3rem !important;\n}\n\n.mr-n5,\n.mx-n5 {\n margin-right: -3rem !important;\n}\n\n.mb-n5,\n.my-n5 {\n margin-bottom: -3rem !important;\n}\n\n.ml-n5,\n.mx-n5 {\n margin-left: -3rem !important;\n}\n\n.m-auto {\n margin: auto !important;\n}\n\n.mt-auto,\n.my-auto {\n margin-top: auto !important;\n}\n\n.mr-auto,\n.mx-auto {\n margin-right: auto !important;\n}\n\n.mb-auto,\n.my-auto {\n margin-bottom: auto !important;\n}\n\n.ml-auto,\n.mx-auto {\n margin-left: auto !important;\n}\n\n@media (min-width: 576px) {\n .m-sm-0 {\n margin: 0 !important;\n }\n .mt-sm-0,\n .my-sm-0 {\n margin-top: 0 !important;\n }\n .mr-sm-0,\n .mx-sm-0 {\n margin-right: 0 !important;\n }\n .mb-sm-0,\n .my-sm-0 {\n margin-bottom: 0 !important;\n }\n .ml-sm-0,\n .mx-sm-0 {\n margin-left: 0 !important;\n }\n .m-sm-1 {\n margin: 0.25rem !important;\n }\n .mt-sm-1,\n .my-sm-1 {\n margin-top: 0.25rem !important;\n }\n .mr-sm-1,\n .mx-sm-1 {\n margin-right: 0.25rem !important;\n }\n .mb-sm-1,\n .my-sm-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-sm-1,\n .mx-sm-1 {\n margin-left: 0.25rem !important;\n }\n .m-sm-2 {\n margin: 0.5rem !important;\n }\n .mt-sm-2,\n .my-sm-2 {\n margin-top: 0.5rem !important;\n }\n .mr-sm-2,\n .mx-sm-2 {\n margin-right: 0.5rem !important;\n }\n .mb-sm-2,\n .my-sm-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-sm-2,\n .mx-sm-2 {\n margin-left: 0.5rem !important;\n }\n .m-sm-3 {\n margin: 1rem !important;\n }\n .mt-sm-3,\n .my-sm-3 {\n margin-top: 1rem !important;\n }\n .mr-sm-3,\n .mx-sm-3 {\n margin-right: 1rem !important;\n }\n .mb-sm-3,\n .my-sm-3 {\n margin-bottom: 1rem !important;\n }\n .ml-sm-3,\n .mx-sm-3 {\n margin-left: 1rem !important;\n }\n .m-sm-4 {\n margin: 1.5rem !important;\n }\n .mt-sm-4,\n .my-sm-4 {\n margin-top: 1.5rem !important;\n }\n .mr-sm-4,\n .mx-sm-4 {\n margin-right: 1.5rem !important;\n }\n .mb-sm-4,\n .my-sm-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-sm-4,\n .mx-sm-4 {\n margin-left: 1.5rem !important;\n }\n .m-sm-5 {\n margin: 3rem !important;\n }\n .mt-sm-5,\n .my-sm-5 {\n margin-top: 3rem !important;\n }\n .mr-sm-5,\n .mx-sm-5 {\n margin-right: 3rem !important;\n }\n .mb-sm-5,\n .my-sm-5 {\n margin-bottom: 3rem !important;\n }\n .ml-sm-5,\n .mx-sm-5 {\n margin-left: 3rem !important;\n }\n .p-sm-0 {\n padding: 0 !important;\n }\n .pt-sm-0,\n .py-sm-0 {\n padding-top: 0 !important;\n }\n .pr-sm-0,\n .px-sm-0 {\n padding-right: 0 !important;\n }\n .pb-sm-0,\n .py-sm-0 {\n padding-bottom: 0 !important;\n }\n .pl-sm-0,\n .px-sm-0 {\n padding-left: 0 !important;\n }\n .p-sm-1 {\n padding: 0.25rem !important;\n }\n .pt-sm-1,\n .py-sm-1 {\n padding-top: 0.25rem !important;\n }\n .pr-sm-1,\n .px-sm-1 {\n padding-right: 0.25rem !important;\n }\n .pb-sm-1,\n .py-sm-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-sm-1,\n .px-sm-1 {\n padding-left: 0.25rem !important;\n }\n .p-sm-2 {\n padding: 0.5rem !important;\n }\n .pt-sm-2,\n .py-sm-2 {\n padding-top: 0.5rem !important;\n }\n .pr-sm-2,\n .px-sm-2 {\n padding-right: 0.5rem !important;\n }\n .pb-sm-2,\n .py-sm-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-sm-2,\n .px-sm-2 {\n padding-left: 0.5rem !important;\n }\n .p-sm-3 {\n padding: 1rem !important;\n }\n .pt-sm-3,\n .py-sm-3 {\n padding-top: 1rem !important;\n }\n .pr-sm-3,\n .px-sm-3 {\n padding-right: 1rem !important;\n }\n .pb-sm-3,\n .py-sm-3 {\n padding-bottom: 1rem !important;\n }\n .pl-sm-3,\n .px-sm-3 {\n padding-left: 1rem !important;\n }\n .p-sm-4 {\n padding: 1.5rem !important;\n }\n .pt-sm-4,\n .py-sm-4 {\n padding-top: 1.5rem !important;\n }\n .pr-sm-4,\n .px-sm-4 {\n padding-right: 1.5rem !important;\n }\n .pb-sm-4,\n .py-sm-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-sm-4,\n .px-sm-4 {\n padding-left: 1.5rem !important;\n }\n .p-sm-5 {\n padding: 3rem !important;\n }\n .pt-sm-5,\n .py-sm-5 {\n padding-top: 3rem !important;\n }\n .pr-sm-5,\n .px-sm-5 {\n padding-right: 3rem !important;\n }\n .pb-sm-5,\n .py-sm-5 {\n padding-bottom: 3rem !important;\n }\n .pl-sm-5,\n .px-sm-5 {\n padding-left: 3rem !important;\n }\n .m-sm-n1 {\n margin: -0.25rem !important;\n }\n .mt-sm-n1,\n .my-sm-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-sm-n1,\n .mx-sm-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-sm-n1,\n .my-sm-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-sm-n1,\n .mx-sm-n1 {\n margin-left: -0.25rem !important;\n }\n .m-sm-n2 {\n margin: -0.5rem !important;\n }\n .mt-sm-n2,\n .my-sm-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-sm-n2,\n .mx-sm-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-sm-n2,\n .my-sm-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-sm-n2,\n .mx-sm-n2 {\n margin-left: -0.5rem !important;\n }\n .m-sm-n3 {\n margin: -1rem !important;\n }\n .mt-sm-n3,\n .my-sm-n3 {\n margin-top: -1rem !important;\n }\n .mr-sm-n3,\n .mx-sm-n3 {\n margin-right: -1rem !important;\n }\n .mb-sm-n3,\n .my-sm-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-sm-n3,\n .mx-sm-n3 {\n margin-left: -1rem !important;\n }\n .m-sm-n4 {\n margin: -1.5rem !important;\n }\n .mt-sm-n4,\n .my-sm-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-sm-n4,\n .mx-sm-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-sm-n4,\n .my-sm-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-sm-n4,\n .mx-sm-n4 {\n margin-left: -1.5rem !important;\n }\n .m-sm-n5 {\n margin: -3rem !important;\n }\n .mt-sm-n5,\n .my-sm-n5 {\n margin-top: -3rem !important;\n }\n .mr-sm-n5,\n .mx-sm-n5 {\n margin-right: -3rem !important;\n }\n .mb-sm-n5,\n .my-sm-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-sm-n5,\n .mx-sm-n5 {\n margin-left: -3rem !important;\n }\n .m-sm-auto {\n margin: auto !important;\n }\n .mt-sm-auto,\n .my-sm-auto {\n margin-top: auto !important;\n }\n .mr-sm-auto,\n .mx-sm-auto {\n margin-right: auto !important;\n }\n .mb-sm-auto,\n .my-sm-auto {\n margin-bottom: auto !important;\n }\n .ml-sm-auto,\n .mx-sm-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 768px) {\n .m-md-0 {\n margin: 0 !important;\n }\n .mt-md-0,\n .my-md-0 {\n margin-top: 0 !important;\n }\n .mr-md-0,\n .mx-md-0 {\n margin-right: 0 !important;\n }\n .mb-md-0,\n .my-md-0 {\n margin-bottom: 0 !important;\n }\n .ml-md-0,\n .mx-md-0 {\n margin-left: 0 !important;\n }\n .m-md-1 {\n margin: 0.25rem !important;\n }\n .mt-md-1,\n .my-md-1 {\n margin-top: 0.25rem !important;\n }\n .mr-md-1,\n .mx-md-1 {\n margin-right: 0.25rem !important;\n }\n .mb-md-1,\n .my-md-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-md-1,\n .mx-md-1 {\n margin-left: 0.25rem !important;\n }\n .m-md-2 {\n margin: 0.5rem !important;\n }\n .mt-md-2,\n .my-md-2 {\n margin-top: 0.5rem !important;\n }\n .mr-md-2,\n .mx-md-2 {\n margin-right: 0.5rem !important;\n }\n .mb-md-2,\n .my-md-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-md-2,\n .mx-md-2 {\n margin-left: 0.5rem !important;\n }\n .m-md-3 {\n margin: 1rem !important;\n }\n .mt-md-3,\n .my-md-3 {\n margin-top: 1rem !important;\n }\n .mr-md-3,\n .mx-md-3 {\n margin-right: 1rem !important;\n }\n .mb-md-3,\n .my-md-3 {\n margin-bottom: 1rem !important;\n }\n .ml-md-3,\n .mx-md-3 {\n margin-left: 1rem !important;\n }\n .m-md-4 {\n margin: 1.5rem !important;\n }\n .mt-md-4,\n .my-md-4 {\n margin-top: 1.5rem !important;\n }\n .mr-md-4,\n .mx-md-4 {\n margin-right: 1.5rem !important;\n }\n .mb-md-4,\n .my-md-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-md-4,\n .mx-md-4 {\n margin-left: 1.5rem !important;\n }\n .m-md-5 {\n margin: 3rem !important;\n }\n .mt-md-5,\n .my-md-5 {\n margin-top: 3rem !important;\n }\n .mr-md-5,\n .mx-md-5 {\n margin-right: 3rem !important;\n }\n .mb-md-5,\n .my-md-5 {\n margin-bottom: 3rem !important;\n }\n .ml-md-5,\n .mx-md-5 {\n margin-left: 3rem !important;\n }\n .p-md-0 {\n padding: 0 !important;\n }\n .pt-md-0,\n .py-md-0 {\n padding-top: 0 !important;\n }\n .pr-md-0,\n .px-md-0 {\n padding-right: 0 !important;\n }\n .pb-md-0,\n .py-md-0 {\n padding-bottom: 0 !important;\n }\n .pl-md-0,\n .px-md-0 {\n padding-left: 0 !important;\n }\n .p-md-1 {\n padding: 0.25rem !important;\n }\n .pt-md-1,\n .py-md-1 {\n padding-top: 0.25rem !important;\n }\n .pr-md-1,\n .px-md-1 {\n padding-right: 0.25rem !important;\n }\n .pb-md-1,\n .py-md-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-md-1,\n .px-md-1 {\n padding-left: 0.25rem !important;\n }\n .p-md-2 {\n padding: 0.5rem !important;\n }\n .pt-md-2,\n .py-md-2 {\n padding-top: 0.5rem !important;\n }\n .pr-md-2,\n .px-md-2 {\n padding-right: 0.5rem !important;\n }\n .pb-md-2,\n .py-md-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-md-2,\n .px-md-2 {\n padding-left: 0.5rem !important;\n }\n .p-md-3 {\n padding: 1rem !important;\n }\n .pt-md-3,\n .py-md-3 {\n padding-top: 1rem !important;\n }\n .pr-md-3,\n .px-md-3 {\n padding-right: 1rem !important;\n }\n .pb-md-3,\n .py-md-3 {\n padding-bottom: 1rem !important;\n }\n .pl-md-3,\n .px-md-3 {\n padding-left: 1rem !important;\n }\n .p-md-4 {\n padding: 1.5rem !important;\n }\n .pt-md-4,\n .py-md-4 {\n padding-top: 1.5rem !important;\n }\n .pr-md-4,\n .px-md-4 {\n padding-right: 1.5rem !important;\n }\n .pb-md-4,\n .py-md-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-md-4,\n .px-md-4 {\n padding-left: 1.5rem !important;\n }\n .p-md-5 {\n padding: 3rem !important;\n }\n .pt-md-5,\n .py-md-5 {\n padding-top: 3rem !important;\n }\n .pr-md-5,\n .px-md-5 {\n padding-right: 3rem !important;\n }\n .pb-md-5,\n .py-md-5 {\n padding-bottom: 3rem !important;\n }\n .pl-md-5,\n .px-md-5 {\n padding-left: 3rem !important;\n }\n .m-md-n1 {\n margin: -0.25rem !important;\n }\n .mt-md-n1,\n .my-md-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-md-n1,\n .mx-md-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-md-n1,\n .my-md-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-md-n1,\n .mx-md-n1 {\n margin-left: -0.25rem !important;\n }\n .m-md-n2 {\n margin: -0.5rem !important;\n }\n .mt-md-n2,\n .my-md-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-md-n2,\n .mx-md-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-md-n2,\n .my-md-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-md-n2,\n .mx-md-n2 {\n margin-left: -0.5rem !important;\n }\n .m-md-n3 {\n margin: -1rem !important;\n }\n .mt-md-n3,\n .my-md-n3 {\n margin-top: -1rem !important;\n }\n .mr-md-n3,\n .mx-md-n3 {\n margin-right: -1rem !important;\n }\n .mb-md-n3,\n .my-md-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-md-n3,\n .mx-md-n3 {\n margin-left: -1rem !important;\n }\n .m-md-n4 {\n margin: -1.5rem !important;\n }\n .mt-md-n4,\n .my-md-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-md-n4,\n .mx-md-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-md-n4,\n .my-md-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-md-n4,\n .mx-md-n4 {\n margin-left: -1.5rem !important;\n }\n .m-md-n5 {\n margin: -3rem !important;\n }\n .mt-md-n5,\n .my-md-n5 {\n margin-top: -3rem !important;\n }\n .mr-md-n5,\n .mx-md-n5 {\n margin-right: -3rem !important;\n }\n .mb-md-n5,\n .my-md-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-md-n5,\n .mx-md-n5 {\n margin-left: -3rem !important;\n }\n .m-md-auto {\n margin: auto !important;\n }\n .mt-md-auto,\n .my-md-auto {\n margin-top: auto !important;\n }\n .mr-md-auto,\n .mx-md-auto {\n margin-right: auto !important;\n }\n .mb-md-auto,\n .my-md-auto {\n margin-bottom: auto !important;\n }\n .ml-md-auto,\n .mx-md-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 992px) {\n .m-lg-0 {\n margin: 0 !important;\n }\n .mt-lg-0,\n .my-lg-0 {\n margin-top: 0 !important;\n }\n .mr-lg-0,\n .mx-lg-0 {\n margin-right: 0 !important;\n }\n .mb-lg-0,\n .my-lg-0 {\n margin-bottom: 0 !important;\n }\n .ml-lg-0,\n .mx-lg-0 {\n margin-left: 0 !important;\n }\n .m-lg-1 {\n margin: 0.25rem !important;\n }\n .mt-lg-1,\n .my-lg-1 {\n margin-top: 0.25rem !important;\n }\n .mr-lg-1,\n .mx-lg-1 {\n margin-right: 0.25rem !important;\n }\n .mb-lg-1,\n .my-lg-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-lg-1,\n .mx-lg-1 {\n margin-left: 0.25rem !important;\n }\n .m-lg-2 {\n margin: 0.5rem !important;\n }\n .mt-lg-2,\n .my-lg-2 {\n margin-top: 0.5rem !important;\n }\n .mr-lg-2,\n .mx-lg-2 {\n margin-right: 0.5rem !important;\n }\n .mb-lg-2,\n .my-lg-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-lg-2,\n .mx-lg-2 {\n margin-left: 0.5rem !important;\n }\n .m-lg-3 {\n margin: 1rem !important;\n }\n .mt-lg-3,\n .my-lg-3 {\n margin-top: 1rem !important;\n }\n .mr-lg-3,\n .mx-lg-3 {\n margin-right: 1rem !important;\n }\n .mb-lg-3,\n .my-lg-3 {\n margin-bottom: 1rem !important;\n }\n .ml-lg-3,\n .mx-lg-3 {\n margin-left: 1rem !important;\n }\n .m-lg-4 {\n margin: 1.5rem !important;\n }\n .mt-lg-4,\n .my-lg-4 {\n margin-top: 1.5rem !important;\n }\n .mr-lg-4,\n .mx-lg-4 {\n margin-right: 1.5rem !important;\n }\n .mb-lg-4,\n .my-lg-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-lg-4,\n .mx-lg-4 {\n margin-left: 1.5rem !important;\n }\n .m-lg-5 {\n margin: 3rem !important;\n }\n .mt-lg-5,\n .my-lg-5 {\n margin-top: 3rem !important;\n }\n .mr-lg-5,\n .mx-lg-5 {\n margin-right: 3rem !important;\n }\n .mb-lg-5,\n .my-lg-5 {\n margin-bottom: 3rem !important;\n }\n .ml-lg-5,\n .mx-lg-5 {\n margin-left: 3rem !important;\n }\n .p-lg-0 {\n padding: 0 !important;\n }\n .pt-lg-0,\n .py-lg-0 {\n padding-top: 0 !important;\n }\n .pr-lg-0,\n .px-lg-0 {\n padding-right: 0 !important;\n }\n .pb-lg-0,\n .py-lg-0 {\n padding-bottom: 0 !important;\n }\n .pl-lg-0,\n .px-lg-0 {\n padding-left: 0 !important;\n }\n .p-lg-1 {\n padding: 0.25rem !important;\n }\n .pt-lg-1,\n .py-lg-1 {\n padding-top: 0.25rem !important;\n }\n .pr-lg-1,\n .px-lg-1 {\n padding-right: 0.25rem !important;\n }\n .pb-lg-1,\n .py-lg-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-lg-1,\n .px-lg-1 {\n padding-left: 0.25rem !important;\n }\n .p-lg-2 {\n padding: 0.5rem !important;\n }\n .pt-lg-2,\n .py-lg-2 {\n padding-top: 0.5rem !important;\n }\n .pr-lg-2,\n .px-lg-2 {\n padding-right: 0.5rem !important;\n }\n .pb-lg-2,\n .py-lg-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-lg-2,\n .px-lg-2 {\n padding-left: 0.5rem !important;\n }\n .p-lg-3 {\n padding: 1rem !important;\n }\n .pt-lg-3,\n .py-lg-3 {\n padding-top: 1rem !important;\n }\n .pr-lg-3,\n .px-lg-3 {\n padding-right: 1rem !important;\n }\n .pb-lg-3,\n .py-lg-3 {\n padding-bottom: 1rem !important;\n }\n .pl-lg-3,\n .px-lg-3 {\n padding-left: 1rem !important;\n }\n .p-lg-4 {\n padding: 1.5rem !important;\n }\n .pt-lg-4,\n .py-lg-4 {\n padding-top: 1.5rem !important;\n }\n .pr-lg-4,\n .px-lg-4 {\n padding-right: 1.5rem !important;\n }\n .pb-lg-4,\n .py-lg-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-lg-4,\n .px-lg-4 {\n padding-left: 1.5rem !important;\n }\n .p-lg-5 {\n padding: 3rem !important;\n }\n .pt-lg-5,\n .py-lg-5 {\n padding-top: 3rem !important;\n }\n .pr-lg-5,\n .px-lg-5 {\n padding-right: 3rem !important;\n }\n .pb-lg-5,\n .py-lg-5 {\n padding-bottom: 3rem !important;\n }\n .pl-lg-5,\n .px-lg-5 {\n padding-left: 3rem !important;\n }\n .m-lg-n1 {\n margin: -0.25rem !important;\n }\n .mt-lg-n1,\n .my-lg-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-lg-n1,\n .mx-lg-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-lg-n1,\n .my-lg-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-lg-n1,\n .mx-lg-n1 {\n margin-left: -0.25rem !important;\n }\n .m-lg-n2 {\n margin: -0.5rem !important;\n }\n .mt-lg-n2,\n .my-lg-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-lg-n2,\n .mx-lg-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-lg-n2,\n .my-lg-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-lg-n2,\n .mx-lg-n2 {\n margin-left: -0.5rem !important;\n }\n .m-lg-n3 {\n margin: -1rem !important;\n }\n .mt-lg-n3,\n .my-lg-n3 {\n margin-top: -1rem !important;\n }\n .mr-lg-n3,\n .mx-lg-n3 {\n margin-right: -1rem !important;\n }\n .mb-lg-n3,\n .my-lg-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-lg-n3,\n .mx-lg-n3 {\n margin-left: -1rem !important;\n }\n .m-lg-n4 {\n margin: -1.5rem !important;\n }\n .mt-lg-n4,\n .my-lg-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-lg-n4,\n .mx-lg-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-lg-n4,\n .my-lg-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-lg-n4,\n .mx-lg-n4 {\n margin-left: -1.5rem !important;\n }\n .m-lg-n5 {\n margin: -3rem !important;\n }\n .mt-lg-n5,\n .my-lg-n5 {\n margin-top: -3rem !important;\n }\n .mr-lg-n5,\n .mx-lg-n5 {\n margin-right: -3rem !important;\n }\n .mb-lg-n5,\n .my-lg-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-lg-n5,\n .mx-lg-n5 {\n margin-left: -3rem !important;\n }\n .m-lg-auto {\n margin: auto !important;\n }\n .mt-lg-auto,\n .my-lg-auto {\n margin-top: auto !important;\n }\n .mr-lg-auto,\n .mx-lg-auto {\n margin-right: auto !important;\n }\n .mb-lg-auto,\n .my-lg-auto {\n margin-bottom: auto !important;\n }\n .ml-lg-auto,\n .mx-lg-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 1200px) {\n .m-xl-0 {\n margin: 0 !important;\n }\n .mt-xl-0,\n .my-xl-0 {\n margin-top: 0 !important;\n }\n .mr-xl-0,\n .mx-xl-0 {\n margin-right: 0 !important;\n }\n .mb-xl-0,\n .my-xl-0 {\n margin-bottom: 0 !important;\n }\n .ml-xl-0,\n .mx-xl-0 {\n margin-left: 0 !important;\n }\n .m-xl-1 {\n margin: 0.25rem !important;\n }\n .mt-xl-1,\n .my-xl-1 {\n margin-top: 0.25rem !important;\n }\n .mr-xl-1,\n .mx-xl-1 {\n margin-right: 0.25rem !important;\n }\n .mb-xl-1,\n .my-xl-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-xl-1,\n .mx-xl-1 {\n margin-left: 0.25rem !important;\n }\n .m-xl-2 {\n margin: 0.5rem !important;\n }\n .mt-xl-2,\n .my-xl-2 {\n margin-top: 0.5rem !important;\n }\n .mr-xl-2,\n .mx-xl-2 {\n margin-right: 0.5rem !important;\n }\n .mb-xl-2,\n .my-xl-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-xl-2,\n .mx-xl-2 {\n margin-left: 0.5rem !important;\n }\n .m-xl-3 {\n margin: 1rem !important;\n }\n .mt-xl-3,\n .my-xl-3 {\n margin-top: 1rem !important;\n }\n .mr-xl-3,\n .mx-xl-3 {\n margin-right: 1rem !important;\n }\n .mb-xl-3,\n .my-xl-3 {\n margin-bottom: 1rem !important;\n }\n .ml-xl-3,\n .mx-xl-3 {\n margin-left: 1rem !important;\n }\n .m-xl-4 {\n margin: 1.5rem !important;\n }\n .mt-xl-4,\n .my-xl-4 {\n margin-top: 1.5rem !important;\n }\n .mr-xl-4,\n .mx-xl-4 {\n margin-right: 1.5rem !important;\n }\n .mb-xl-4,\n .my-xl-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-xl-4,\n .mx-xl-4 {\n margin-left: 1.5rem !important;\n }\n .m-xl-5 {\n margin: 3rem !important;\n }\n .mt-xl-5,\n .my-xl-5 {\n margin-top: 3rem !important;\n }\n .mr-xl-5,\n .mx-xl-5 {\n margin-right: 3rem !important;\n }\n .mb-xl-5,\n .my-xl-5 {\n margin-bottom: 3rem !important;\n }\n .ml-xl-5,\n .mx-xl-5 {\n margin-left: 3rem !important;\n }\n .p-xl-0 {\n padding: 0 !important;\n }\n .pt-xl-0,\n .py-xl-0 {\n padding-top: 0 !important;\n }\n .pr-xl-0,\n .px-xl-0 {\n padding-right: 0 !important;\n }\n .pb-xl-0,\n .py-xl-0 {\n padding-bottom: 0 !important;\n }\n .pl-xl-0,\n .px-xl-0 {\n padding-left: 0 !important;\n }\n .p-xl-1 {\n padding: 0.25rem !important;\n }\n .pt-xl-1,\n .py-xl-1 {\n padding-top: 0.25rem !important;\n }\n .pr-xl-1,\n .px-xl-1 {\n padding-right: 0.25rem !important;\n }\n .pb-xl-1,\n .py-xl-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-xl-1,\n .px-xl-1 {\n padding-left: 0.25rem !important;\n }\n .p-xl-2 {\n padding: 0.5rem !important;\n }\n .pt-xl-2,\n .py-xl-2 {\n padding-top: 0.5rem !important;\n }\n .pr-xl-2,\n .px-xl-2 {\n padding-right: 0.5rem !important;\n }\n .pb-xl-2,\n .py-xl-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-xl-2,\n .px-xl-2 {\n padding-left: 0.5rem !important;\n }\n .p-xl-3 {\n padding: 1rem !important;\n }\n .pt-xl-3,\n .py-xl-3 {\n padding-top: 1rem !important;\n }\n .pr-xl-3,\n .px-xl-3 {\n padding-right: 1rem !important;\n }\n .pb-xl-3,\n .py-xl-3 {\n padding-bottom: 1rem !important;\n }\n .pl-xl-3,\n .px-xl-3 {\n padding-left: 1rem !important;\n }\n .p-xl-4 {\n padding: 1.5rem !important;\n }\n .pt-xl-4,\n .py-xl-4 {\n padding-top: 1.5rem !important;\n }\n .pr-xl-4,\n .px-xl-4 {\n padding-right: 1.5rem !important;\n }\n .pb-xl-4,\n .py-xl-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-xl-4,\n .px-xl-4 {\n padding-left: 1.5rem !important;\n }\n .p-xl-5 {\n padding: 3rem !important;\n }\n .pt-xl-5,\n .py-xl-5 {\n padding-top: 3rem !important;\n }\n .pr-xl-5,\n .px-xl-5 {\n padding-right: 3rem !important;\n }\n .pb-xl-5,\n .py-xl-5 {\n padding-bottom: 3rem !important;\n }\n .pl-xl-5,\n .px-xl-5 {\n padding-left: 3rem !important;\n }\n .m-xl-n1 {\n margin: -0.25rem !important;\n }\n .mt-xl-n1,\n .my-xl-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-xl-n1,\n .mx-xl-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-xl-n1,\n .my-xl-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-xl-n1,\n .mx-xl-n1 {\n margin-left: -0.25rem !important;\n }\n .m-xl-n2 {\n margin: -0.5rem !important;\n }\n .mt-xl-n2,\n .my-xl-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-xl-n2,\n .mx-xl-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-xl-n2,\n .my-xl-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-xl-n2,\n .mx-xl-n2 {\n margin-left: -0.5rem !important;\n }\n .m-xl-n3 {\n margin: -1rem !important;\n }\n .mt-xl-n3,\n .my-xl-n3 {\n margin-top: -1rem !important;\n }\n .mr-xl-n3,\n .mx-xl-n3 {\n margin-right: -1rem !important;\n }\n .mb-xl-n3,\n .my-xl-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-xl-n3,\n .mx-xl-n3 {\n margin-left: -1rem !important;\n }\n .m-xl-n4 {\n margin: -1.5rem !important;\n }\n .mt-xl-n4,\n .my-xl-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-xl-n4,\n .mx-xl-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-xl-n4,\n .my-xl-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-xl-n4,\n .mx-xl-n4 {\n margin-left: -1.5rem !important;\n }\n .m-xl-n5 {\n margin: -3rem !important;\n }\n .mt-xl-n5,\n .my-xl-n5 {\n margin-top: -3rem !important;\n }\n .mr-xl-n5,\n .mx-xl-n5 {\n margin-right: -3rem !important;\n }\n .mb-xl-n5,\n .my-xl-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-xl-n5,\n .mx-xl-n5 {\n margin-left: -3rem !important;\n }\n .m-xl-auto {\n margin: auto !important;\n }\n .mt-xl-auto,\n .my-xl-auto {\n margin-top: auto !important;\n }\n .mr-xl-auto,\n .mx-xl-auto {\n margin-right: auto !important;\n }\n .mb-xl-auto,\n .my-xl-auto {\n margin-bottom: auto !important;\n }\n .ml-xl-auto,\n .mx-xl-auto {\n margin-left: auto !important;\n }\n}\n\n/*# sourceMappingURL=bootstrap-grid.css.map */","// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n@if $enable-grid-classes {\n // Single container class with breakpoint max-widths\n .container,\n // 100% wide container at all breakpoints\n .container-fluid {\n @include make-container();\n }\n\n // Responsive containers that are 100% wide until a breakpoint\n @each $breakpoint, $container-max-width in $container-max-widths {\n .container-#{$breakpoint} {\n @extend .container-fluid;\n }\n\n @include media-breakpoint-up($breakpoint, $grid-breakpoints) {\n %responsive-container-#{$breakpoint} {\n max-width: $container-max-width;\n }\n\n // Extend each breakpoint which is smaller or equal to the current breakpoint\n $extend-breakpoint: true;\n\n @each $name, $width in $grid-breakpoints {\n @if ($extend-breakpoint) {\n .container#{breakpoint-infix($name, $grid-breakpoints)} {\n @extend %responsive-container-#{$breakpoint};\n }\n\n // Once the current breakpoint is reached, stop extending\n @if ($breakpoint == $name) {\n $extend-breakpoint: false;\n }\n }\n }\n }\n }\n}\n\n\n// Row\n//\n// Rows contain your columns.\n\n@if $enable-grid-classes {\n .row {\n @include make-row();\n }\n\n // Remove the negative margin from default .row, then the horizontal padding\n // from all immediate children columns (to prevent runaway style inheritance).\n .no-gutters {\n margin-right: 0;\n margin-left: 0;\n\n > .col,\n > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n }\n }\n}\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n@if $enable-grid-classes {\n @include make-grid-columns();\n}\n","/// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n@mixin make-container($gutter: $grid-gutter-width) {\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n margin-right: auto;\n margin-left: auto;\n}\n\n@mixin make-row($gutter: $grid-gutter-width) {\n display: flex;\n flex-wrap: wrap;\n margin-right: -$gutter / 2;\n margin-left: -$gutter / 2;\n}\n\n// For each breakpoint, define the maximum width of the container in a media query\n@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {\n @each $breakpoint, $container-max-width in $max-widths {\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n max-width: $container-max-width;\n }\n }\n @include deprecate(\"The `make-container-max-widths` mixin\", \"v4.5.2\", \"v5\");\n}\n\n@mixin make-col-ready($gutter: $grid-gutter-width) {\n position: relative;\n // Prevent columns from becoming too narrow when at smaller grid tiers by\n // always setting `width: 100%;`. This works because we use `flex` values\n // later on to override this initial width.\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n}\n\n@mixin make-col($size, $columns: $grid-columns) {\n flex: 0 0 percentage($size / $columns);\n // Add a `max-width` to ensure content within each column does not blow out\n // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari\n // do not appear to require this.\n max-width: percentage($size / $columns);\n}\n\n@mixin make-col-auto() {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%; // Reset earlier grid tiers\n}\n\n@mixin make-col-offset($size, $columns: $grid-columns) {\n $num: $size / $columns;\n margin-left: if($num == 0, 0, percentage($num));\n}\n\n// Row columns\n//\n// Specify on a parent element(e.g., .row) to force immediate children into NN\n// numberof columns. Supports wrapping to new lines, but does not do a Masonry\n// style grid.\n@mixin row-cols($count) {\n > * {\n flex: 0 0 100% / $count;\n max-width: 100% / $count;\n }\n}\n","// Breakpoint viewport sizes and media queries.\n//\n// Breakpoints are defined as a map of (name: minimum width), order from small to large:\n//\n// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)\n//\n// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.\n\n// Name of the next breakpoint, or null for the last breakpoint.\n//\n// >> breakpoint-next(sm)\n// md\n// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// md\n// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))\n// md\n@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {\n $n: index($breakpoint-names, $name);\n @return if($n != null and $n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);\n}\n\n// Minimum breakpoint width. Null for the smallest (first) breakpoint.\n//\n// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 576px\n@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {\n $min: map-get($breakpoints, $name);\n @return if($min != 0, $min, null);\n}\n\n// Maximum breakpoint width. Null for the largest (last) breakpoint.\n// The maximum value is calculated as the minimum of the next one less 0.02px\n// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.\n// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max\n// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.\n// See https://bugs.webkit.org/show_bug.cgi?id=178261\n//\n// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 767.98px\n@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {\n $next: breakpoint-next($name, $breakpoints);\n @return if($next, breakpoint-min($next, $breakpoints) - .02, null);\n}\n\n// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.\n// Useful for making responsive utilities.\n//\n// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"\" (Returns a blank string)\n// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"-sm\"\n@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {\n @return if(breakpoint-min($name, $breakpoints) == null, \"\", \"-#{$name}\");\n}\n\n// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.\n// Makes the @content apply to the given breakpoint and wider.\n@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n @if $min {\n @media (min-width: $min) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media of at most the maximum breakpoint width. No query for the largest breakpoint.\n// Makes the @content apply to the given breakpoint and narrower.\n@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {\n $max: breakpoint-max($name, $breakpoints);\n @if $max {\n @media (max-width: $max) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media that spans multiple breakpoint widths.\n// Makes the @content apply between the min and max breakpoints\n@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($lower, $breakpoints);\n $max: breakpoint-max($upper, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($lower, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($upper, $breakpoints) {\n @content;\n }\n }\n}\n\n// Media between the breakpoint's minimum and maximum widths.\n// No minimum for the smallest breakpoint, and no maximum for the largest one.\n// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.\n@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n $max: breakpoint-max($name, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($name, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($name, $breakpoints) {\n @content;\n }\n }\n}\n","// Variables\n//\n// Variables should follow the `$component-state-property-size` formula for\n// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.\n\n// Color system\n\n$white: #fff !default;\n$gray-100: #f8f9fa !default;\n$gray-200: #e9ecef !default;\n$gray-300: #dee2e6 !default;\n$gray-400: #ced4da !default;\n$gray-500: #adb5bd !default;\n$gray-600: #6c757d !default;\n$gray-700: #495057 !default;\n$gray-800: #343a40 !default;\n$gray-900: #212529 !default;\n$black: #000 !default;\n\n$grays: () !default;\n$grays: map-merge(\n (\n \"100\": $gray-100,\n \"200\": $gray-200,\n \"300\": $gray-300,\n \"400\": $gray-400,\n \"500\": $gray-500,\n \"600\": $gray-600,\n \"700\": $gray-700,\n \"800\": $gray-800,\n \"900\": $gray-900\n ),\n $grays\n);\n\n$blue: #007bff !default;\n$indigo: #6610f2 !default;\n$purple: #6f42c1 !default;\n$pink: #e83e8c !default;\n$red: #dc3545 !default;\n$orange: #fd7e14 !default;\n$yellow: #ffc107 !default;\n$green: #28a745 !default;\n$teal: #20c997 !default;\n$cyan: #17a2b8 !default;\n\n$colors: () !default;\n$colors: map-merge(\n (\n \"blue\": $blue,\n \"indigo\": $indigo,\n \"purple\": $purple,\n \"pink\": $pink,\n \"red\": $red,\n \"orange\": $orange,\n \"yellow\": $yellow,\n \"green\": $green,\n \"teal\": $teal,\n \"cyan\": $cyan,\n \"white\": $white,\n \"gray\": $gray-600,\n \"gray-dark\": $gray-800\n ),\n $colors\n);\n\n$primary: $blue !default;\n$secondary: $gray-600 !default;\n$success: $green !default;\n$info: $cyan !default;\n$warning: $yellow !default;\n$danger: $red !default;\n$light: $gray-100 !default;\n$dark: $gray-800 !default;\n\n$theme-colors: () !default;\n$theme-colors: map-merge(\n (\n \"primary\": $primary,\n \"secondary\": $secondary,\n \"success\": $success,\n \"info\": $info,\n \"warning\": $warning,\n \"danger\": $danger,\n \"light\": $light,\n \"dark\": $dark\n ),\n $theme-colors\n);\n\n// Set a specific jump point for requesting color jumps\n$theme-color-interval: 8% !default;\n\n// The yiq lightness value that determines when the lightness of color changes from \"dark\" to \"light\". Acceptable values are between 0 and 255.\n$yiq-contrasted-threshold: 150 !default;\n\n// Customize the light and dark text colors for use in our YIQ color contrast function.\n$yiq-text-dark: $gray-900 !default;\n$yiq-text-light: $white !default;\n\n// Characters which are escaped by the escape-svg function\n$escaped-characters: (\n (\"<\", \"%3c\"),\n (\">\", \"%3e\"),\n (\"#\", \"%23\"),\n (\"(\", \"%28\"),\n (\")\", \"%29\"),\n) !default;\n\n\n// Options\n//\n// Quickly modify global styling by enabling or disabling optional features.\n\n$enable-caret: true !default;\n$enable-rounded: true !default;\n$enable-shadows: false !default;\n$enable-gradients: false !default;\n$enable-transitions: true !default;\n$enable-prefers-reduced-motion-media-query: true !default;\n$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS\n$enable-grid-classes: true !default;\n$enable-pointer-cursor-for-buttons: true !default;\n$enable-print-styles: true !default;\n$enable-responsive-font-sizes: false !default;\n$enable-validation-icons: true !default;\n$enable-deprecation-messages: true !default;\n\n\n// Spacing\n//\n// Control the default styling of most Bootstrap elements by modifying these\n// variables. Mostly focused on spacing.\n// You can add more entries to the $spacers map, should you need more variation.\n\n$spacer: 1rem !default;\n$spacers: () !default;\n$spacers: map-merge(\n (\n 0: 0,\n 1: ($spacer * .25),\n 2: ($spacer * .5),\n 3: $spacer,\n 4: ($spacer * 1.5),\n 5: ($spacer * 3)\n ),\n $spacers\n);\n\n// This variable affects the `.h-*` and `.w-*` classes.\n$sizes: () !default;\n$sizes: map-merge(\n (\n 25: 25%,\n 50: 50%,\n 75: 75%,\n 100: 100%,\n auto: auto\n ),\n $sizes\n);\n\n\n// Body\n//\n// Settings for the `` element.\n\n$body-bg: $white !default;\n$body-color: $gray-900 !default;\n\n\n// Links\n//\n// Style anchor elements.\n\n$link-color: theme-color(\"primary\") !default;\n$link-decoration: none !default;\n$link-hover-color: darken($link-color, 15%) !default;\n$link-hover-decoration: underline !default;\n// Darken percentage for links with `.text-*` class (e.g. `.text-success`)\n$emphasized-link-hover-darken-percentage: 15% !default;\n\n// Paragraphs\n//\n// Style p element.\n\n$paragraph-margin-bottom: 1rem !default;\n\n\n// Grid breakpoints\n//\n// Define the minimum dimensions at which your layout will change,\n// adapting to different screen sizes, for use in media queries.\n\n$grid-breakpoints: (\n xs: 0,\n sm: 576px,\n md: 768px,\n lg: 992px,\n xl: 1200px\n) !default;\n\n@include _assert-ascending($grid-breakpoints, \"$grid-breakpoints\");\n@include _assert-starts-at-zero($grid-breakpoints, \"$grid-breakpoints\");\n\n\n// Grid containers\n//\n// Define the maximum width of `.container` for different screen sizes.\n\n$container-max-widths: (\n sm: 540px,\n md: 720px,\n lg: 960px,\n xl: 1140px\n) !default;\n\n@include _assert-ascending($container-max-widths, \"$container-max-widths\");\n\n\n// Grid columns\n//\n// Set the number of columns and specify the width of the gutters.\n\n$grid-columns: 12 !default;\n$grid-gutter-width: 30px !default;\n$grid-row-columns: 6 !default;\n\n\n// Components\n//\n// Define common padding and border radius sizes and more.\n\n$line-height-lg: 1.5 !default;\n$line-height-sm: 1.5 !default;\n\n$border-width: 1px !default;\n$border-color: $gray-300 !default;\n\n$border-radius: .25rem !default;\n$border-radius-lg: .3rem !default;\n$border-radius-sm: .2rem !default;\n\n$rounded-pill: 50rem !default;\n\n$box-shadow-sm: 0 .125rem .25rem rgba($black, .075) !default;\n$box-shadow: 0 .5rem 1rem rgba($black, .15) !default;\n$box-shadow-lg: 0 1rem 3rem rgba($black, .175) !default;\n\n$component-active-color: $white !default;\n$component-active-bg: theme-color(\"primary\") !default;\n\n$caret-width: .3em !default;\n$caret-vertical-align: $caret-width * .85 !default;\n$caret-spacing: $caret-width * .85 !default;\n\n$transition-base: all .2s ease-in-out !default;\n$transition-fade: opacity .15s linear !default;\n$transition-collapse: height .35s ease !default;\n\n$embed-responsive-aspect-ratios: () !default;\n$embed-responsive-aspect-ratios: join(\n (\n (21 9),\n (16 9),\n (4 3),\n (1 1),\n ),\n $embed-responsive-aspect-ratios\n);\n\n// Typography\n//\n// Font, line-height, and color for body text, headings, and more.\n\n// stylelint-disable value-keyword-case\n$font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\" !default;\n$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace !default;\n$font-family-base: $font-family-sans-serif !default;\n// stylelint-enable value-keyword-case\n\n$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`\n$font-size-lg: $font-size-base * 1.25 !default;\n$font-size-sm: $font-size-base * .875 !default;\n\n$font-weight-lighter: lighter !default;\n$font-weight-light: 300 !default;\n$font-weight-normal: 400 !default;\n$font-weight-bold: 700 !default;\n$font-weight-bolder: bolder !default;\n\n$font-weight-base: $font-weight-normal !default;\n$line-height-base: 1.5 !default;\n\n$h1-font-size: $font-size-base * 2.5 !default;\n$h2-font-size: $font-size-base * 2 !default;\n$h3-font-size: $font-size-base * 1.75 !default;\n$h4-font-size: $font-size-base * 1.5 !default;\n$h5-font-size: $font-size-base * 1.25 !default;\n$h6-font-size: $font-size-base !default;\n\n$headings-margin-bottom: $spacer / 2 !default;\n$headings-font-family: null !default;\n$headings-font-weight: 500 !default;\n$headings-line-height: 1.2 !default;\n$headings-color: null !default;\n\n$display1-size: 6rem !default;\n$display2-size: 5.5rem !default;\n$display3-size: 4.5rem !default;\n$display4-size: 3.5rem !default;\n\n$display1-weight: 300 !default;\n$display2-weight: 300 !default;\n$display3-weight: 300 !default;\n$display4-weight: 300 !default;\n$display-line-height: $headings-line-height !default;\n\n$lead-font-size: $font-size-base * 1.25 !default;\n$lead-font-weight: 300 !default;\n\n$small-font-size: 80% !default;\n\n$text-muted: $gray-600 !default;\n\n$blockquote-small-color: $gray-600 !default;\n$blockquote-small-font-size: $small-font-size !default;\n$blockquote-font-size: $font-size-base * 1.25 !default;\n\n$hr-border-color: rgba($black, .1) !default;\n$hr-border-width: $border-width !default;\n\n$mark-padding: .2em !default;\n\n$dt-font-weight: $font-weight-bold !default;\n\n$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default;\n$nested-kbd-font-weight: $font-weight-bold !default;\n\n$list-inline-padding: .5rem !default;\n\n$mark-bg: #fcf8e3 !default;\n\n$hr-margin-y: $spacer !default;\n\n\n// Tables\n//\n// Customizes the `.table` component with basic values, each used across all table variations.\n\n$table-cell-padding: .75rem !default;\n$table-cell-padding-sm: .3rem !default;\n\n$table-color: $body-color !default;\n$table-bg: null !default;\n$table-accent-bg: rgba($black, .05) !default;\n$table-hover-color: $table-color !default;\n$table-hover-bg: rgba($black, .075) !default;\n$table-active-bg: $table-hover-bg !default;\n\n$table-border-width: $border-width !default;\n$table-border-color: $border-color !default;\n\n$table-head-bg: $gray-200 !default;\n$table-head-color: $gray-700 !default;\n$table-th-font-weight: null !default;\n\n$table-dark-color: $white !default;\n$table-dark-bg: $gray-800 !default;\n$table-dark-accent-bg: rgba($white, .05) !default;\n$table-dark-hover-color: $table-dark-color !default;\n$table-dark-hover-bg: rgba($white, .075) !default;\n$table-dark-border-color: lighten($table-dark-bg, 7.5%) !default;\n\n$table-striped-order: odd !default;\n\n$table-caption-color: $text-muted !default;\n\n$table-bg-level: -9 !default;\n$table-border-level: -6 !default;\n\n\n// Buttons + Forms\n//\n// Shared variables that are reassigned to `$input-` and `$btn-` specific variables.\n\n$input-btn-padding-y: .375rem !default;\n$input-btn-padding-x: .75rem !default;\n$input-btn-font-family: null !default;\n$input-btn-font-size: $font-size-base !default;\n$input-btn-line-height: $line-height-base !default;\n\n$input-btn-focus-width: .2rem !default;\n$input-btn-focus-color: rgba($component-active-bg, .25) !default;\n$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default;\n\n$input-btn-padding-y-sm: .25rem !default;\n$input-btn-padding-x-sm: .5rem !default;\n$input-btn-font-size-sm: $font-size-sm !default;\n$input-btn-line-height-sm: $line-height-sm !default;\n\n$input-btn-padding-y-lg: .5rem !default;\n$input-btn-padding-x-lg: 1rem !default;\n$input-btn-font-size-lg: $font-size-lg !default;\n$input-btn-line-height-lg: $line-height-lg !default;\n\n$input-btn-border-width: $border-width !default;\n\n\n// Buttons\n//\n// For each of Bootstrap's buttons, define text, background, and border color.\n\n$btn-padding-y: $input-btn-padding-y !default;\n$btn-padding-x: $input-btn-padding-x !default;\n$btn-font-family: $input-btn-font-family !default;\n$btn-font-size: $input-btn-font-size !default;\n$btn-line-height: $input-btn-line-height !default;\n$btn-white-space: null !default; // Set to `nowrap` to prevent text wrapping\n\n$btn-padding-y-sm: $input-btn-padding-y-sm !default;\n$btn-padding-x-sm: $input-btn-padding-x-sm !default;\n$btn-font-size-sm: $input-btn-font-size-sm !default;\n$btn-line-height-sm: $input-btn-line-height-sm !default;\n\n$btn-padding-y-lg: $input-btn-padding-y-lg !default;\n$btn-padding-x-lg: $input-btn-padding-x-lg !default;\n$btn-font-size-lg: $input-btn-font-size-lg !default;\n$btn-line-height-lg: $input-btn-line-height-lg !default;\n\n$btn-border-width: $input-btn-border-width !default;\n\n$btn-font-weight: $font-weight-normal !default;\n$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;\n$btn-focus-width: $input-btn-focus-width !default;\n$btn-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$btn-disabled-opacity: .65 !default;\n$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default;\n\n$btn-link-disabled-color: $gray-600 !default;\n\n$btn-block-spacing-y: .5rem !default;\n\n// Allows for customizing button radius independently from global border radius\n$btn-border-radius: $border-radius !default;\n$btn-border-radius-lg: $border-radius-lg !default;\n$btn-border-radius-sm: $border-radius-sm !default;\n\n$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n\n// Forms\n\n$label-margin-bottom: .5rem !default;\n\n$input-padding-y: $input-btn-padding-y !default;\n$input-padding-x: $input-btn-padding-x !default;\n$input-font-family: $input-btn-font-family !default;\n$input-font-size: $input-btn-font-size !default;\n$input-font-weight: $font-weight-base !default;\n$input-line-height: $input-btn-line-height !default;\n\n$input-padding-y-sm: $input-btn-padding-y-sm !default;\n$input-padding-x-sm: $input-btn-padding-x-sm !default;\n$input-font-size-sm: $input-btn-font-size-sm !default;\n$input-line-height-sm: $input-btn-line-height-sm !default;\n\n$input-padding-y-lg: $input-btn-padding-y-lg !default;\n$input-padding-x-lg: $input-btn-padding-x-lg !default;\n$input-font-size-lg: $input-btn-font-size-lg !default;\n$input-line-height-lg: $input-btn-line-height-lg !default;\n\n$input-bg: $white !default;\n$input-disabled-bg: $gray-200 !default;\n\n$input-color: $gray-700 !default;\n$input-border-color: $gray-400 !default;\n$input-border-width: $input-btn-border-width !default;\n$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default;\n\n$input-border-radius: $border-radius !default;\n$input-border-radius-lg: $border-radius-lg !default;\n$input-border-radius-sm: $border-radius-sm !default;\n\n$input-focus-bg: $input-bg !default;\n$input-focus-border-color: lighten($component-active-bg, 25%) !default;\n$input-focus-color: $input-color !default;\n$input-focus-width: $input-btn-focus-width !default;\n$input-focus-box-shadow: $input-btn-focus-box-shadow !default;\n\n$input-placeholder-color: $gray-600 !default;\n$input-plaintext-color: $body-color !default;\n\n$input-height-border: $input-border-width * 2 !default;\n\n$input-height-inner: add($input-line-height * 1em, $input-padding-y * 2) !default;\n$input-height-inner-half: add($input-line-height * .5em, $input-padding-y) !default;\n$input-height-inner-quarter: add($input-line-height * .25em, $input-padding-y / 2) !default;\n\n$input-height: add($input-line-height * 1em, add($input-padding-y * 2, $input-height-border, false)) !default;\n$input-height-sm: add($input-line-height-sm * 1em, add($input-padding-y-sm * 2, $input-height-border, false)) !default;\n$input-height-lg: add($input-line-height-lg * 1em, add($input-padding-y-lg * 2, $input-height-border, false)) !default;\n\n$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$form-text-margin-top: .25rem !default;\n\n$form-check-input-gutter: 1.25rem !default;\n$form-check-input-margin-y: .3rem !default;\n$form-check-input-margin-x: .25rem !default;\n\n$form-check-inline-margin-x: .75rem !default;\n$form-check-inline-input-margin-x: .3125rem !default;\n\n$form-grid-gutter-width: 10px !default;\n$form-group-margin-bottom: 1rem !default;\n\n$input-group-addon-color: $input-color !default;\n$input-group-addon-bg: $gray-200 !default;\n$input-group-addon-border-color: $input-border-color !default;\n\n$custom-forms-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$custom-control-gutter: .5rem !default;\n$custom-control-spacer-x: 1rem !default;\n$custom-control-cursor: null !default;\n\n$custom-control-indicator-size: 1rem !default;\n$custom-control-indicator-bg: $input-bg !default;\n\n$custom-control-indicator-bg-size: 50% 50% !default;\n$custom-control-indicator-box-shadow: $input-box-shadow !default;\n$custom-control-indicator-border-color: $gray-500 !default;\n$custom-control-indicator-border-width: $input-border-width !default;\n\n$custom-control-label-color: null !default;\n\n$custom-control-indicator-disabled-bg: $input-disabled-bg !default;\n$custom-control-label-disabled-color: $gray-600 !default;\n\n$custom-control-indicator-checked-color: $component-active-color !default;\n$custom-control-indicator-checked-bg: $component-active-bg !default;\n$custom-control-indicator-checked-disabled-bg: rgba(theme-color(\"primary\"), .5) !default;\n$custom-control-indicator-checked-box-shadow: null !default;\n$custom-control-indicator-checked-border-color: $custom-control-indicator-checked-bg !default;\n\n$custom-control-indicator-focus-box-shadow: $input-focus-box-shadow !default;\n$custom-control-indicator-focus-border-color: $input-focus-border-color !default;\n\n$custom-control-indicator-active-color: $component-active-color !default;\n$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-control-indicator-active-box-shadow: null !default;\n$custom-control-indicator-active-border-color: $custom-control-indicator-active-bg !default;\n\n$custom-checkbox-indicator-border-radius: $border-radius !default;\n$custom-checkbox-indicator-icon-checked: url(\"data:image/svg+xml,\") !default;\n\n$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default;\n$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default;\n$custom-checkbox-indicator-icon-indeterminate: url(\"data:image/svg+xml,\") !default;\n$custom-checkbox-indicator-indeterminate-box-shadow: null !default;\n$custom-checkbox-indicator-indeterminate-border-color: $custom-checkbox-indicator-indeterminate-bg !default;\n\n$custom-radio-indicator-border-radius: 50% !default;\n$custom-radio-indicator-icon-checked: url(\"data:image/svg+xml,\") !default;\n\n$custom-switch-width: $custom-control-indicator-size * 1.75 !default;\n$custom-switch-indicator-border-radius: $custom-control-indicator-size / 2 !default;\n$custom-switch-indicator-size: subtract($custom-control-indicator-size, $custom-control-indicator-border-width * 4) !default;\n\n$custom-select-padding-y: $input-padding-y !default;\n$custom-select-padding-x: $input-padding-x !default;\n$custom-select-font-family: $input-font-family !default;\n$custom-select-font-size: $input-font-size !default;\n$custom-select-height: $input-height !default;\n$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator\n$custom-select-font-weight: $input-font-weight !default;\n$custom-select-line-height: $input-line-height !default;\n$custom-select-color: $input-color !default;\n$custom-select-disabled-color: $gray-600 !default;\n$custom-select-bg: $input-bg !default;\n$custom-select-disabled-bg: $gray-200 !default;\n$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions\n$custom-select-indicator-color: $gray-800 !default;\n$custom-select-indicator: url(\"data:image/svg+xml,\") !default;\n$custom-select-background: escape-svg($custom-select-indicator) no-repeat right $custom-select-padding-x center / $custom-select-bg-size !default; // Used so we can have multiple background elements (e.g., arrow and feedback icon)\n\n$custom-select-feedback-icon-padding-right: add(1em * .75, (2 * $custom-select-padding-y * .75) + $custom-select-padding-x + $custom-select-indicator-padding) !default;\n$custom-select-feedback-icon-position: center right ($custom-select-padding-x + $custom-select-indicator-padding) !default;\n$custom-select-feedback-icon-size: $input-height-inner-half $input-height-inner-half !default;\n\n$custom-select-border-width: $input-border-width !default;\n$custom-select-border-color: $input-border-color !default;\n$custom-select-border-radius: $border-radius !default;\n$custom-select-box-shadow: inset 0 1px 2px rgba($black, .075) !default;\n\n$custom-select-focus-border-color: $input-focus-border-color !default;\n$custom-select-focus-width: $input-focus-width !default;\n$custom-select-focus-box-shadow: 0 0 0 $custom-select-focus-width $input-btn-focus-color !default;\n\n$custom-select-padding-y-sm: $input-padding-y-sm !default;\n$custom-select-padding-x-sm: $input-padding-x-sm !default;\n$custom-select-font-size-sm: $input-font-size-sm !default;\n$custom-select-height-sm: $input-height-sm !default;\n\n$custom-select-padding-y-lg: $input-padding-y-lg !default;\n$custom-select-padding-x-lg: $input-padding-x-lg !default;\n$custom-select-font-size-lg: $input-font-size-lg !default;\n$custom-select-height-lg: $input-height-lg !default;\n\n$custom-range-track-width: 100% !default;\n$custom-range-track-height: .5rem !default;\n$custom-range-track-cursor: pointer !default;\n$custom-range-track-bg: $gray-300 !default;\n$custom-range-track-border-radius: 1rem !default;\n$custom-range-track-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-range-thumb-width: 1rem !default;\n$custom-range-thumb-height: $custom-range-thumb-width !default;\n$custom-range-thumb-bg: $component-active-bg !default;\n$custom-range-thumb-border: 0 !default;\n$custom-range-thumb-border-radius: 1rem !default;\n$custom-range-thumb-box-shadow: 0 .1rem .25rem rgba($black, .1) !default;\n$custom-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-focus-box-shadow !default;\n$custom-range-thumb-focus-box-shadow-width: $input-focus-width !default; // For focus box shadow issue in IE/Edge\n$custom-range-thumb-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-range-thumb-disabled-bg: $gray-500 !default;\n\n$custom-file-height: $input-height !default;\n$custom-file-height-inner: $input-height-inner !default;\n$custom-file-focus-border-color: $input-focus-border-color !default;\n$custom-file-focus-box-shadow: $input-focus-box-shadow !default;\n$custom-file-disabled-bg: $input-disabled-bg !default;\n\n$custom-file-padding-y: $input-padding-y !default;\n$custom-file-padding-x: $input-padding-x !default;\n$custom-file-line-height: $input-line-height !default;\n$custom-file-font-family: $input-font-family !default;\n$custom-file-font-weight: $input-font-weight !default;\n$custom-file-color: $input-color !default;\n$custom-file-bg: $input-bg !default;\n$custom-file-border-width: $input-border-width !default;\n$custom-file-border-color: $input-border-color !default;\n$custom-file-border-radius: $input-border-radius !default;\n$custom-file-box-shadow: $input-box-shadow !default;\n$custom-file-button-color: $custom-file-color !default;\n$custom-file-button-bg: $input-group-addon-bg !default;\n$custom-file-text: (\n en: \"Browse\"\n) !default;\n\n\n// Form validation\n\n$form-feedback-margin-top: $form-text-margin-top !default;\n$form-feedback-font-size: $small-font-size !default;\n$form-feedback-valid-color: theme-color(\"success\") !default;\n$form-feedback-invalid-color: theme-color(\"danger\") !default;\n\n$form-feedback-icon-valid-color: $form-feedback-valid-color !default;\n$form-feedback-icon-valid: url(\"data:image/svg+xml,\") !default;\n$form-feedback-icon-invalid-color: $form-feedback-invalid-color !default;\n$form-feedback-icon-invalid: url(\"data:image/svg+xml,\") !default;\n\n$form-validation-states: () !default;\n$form-validation-states: map-merge(\n (\n \"valid\": (\n \"color\": $form-feedback-valid-color,\n \"icon\": $form-feedback-icon-valid\n ),\n \"invalid\": (\n \"color\": $form-feedback-invalid-color,\n \"icon\": $form-feedback-icon-invalid\n ),\n ),\n $form-validation-states\n);\n\n// Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n\n$zindex-dropdown: 1000 !default;\n$zindex-sticky: 1020 !default;\n$zindex-fixed: 1030 !default;\n$zindex-modal-backdrop: 1040 !default;\n$zindex-modal: 1050 !default;\n$zindex-popover: 1060 !default;\n$zindex-tooltip: 1070 !default;\n\n\n// Navs\n\n$nav-link-padding-y: .5rem !default;\n$nav-link-padding-x: 1rem !default;\n$nav-link-disabled-color: $gray-600 !default;\n\n$nav-tabs-border-color: $gray-300 !default;\n$nav-tabs-border-width: $border-width !default;\n$nav-tabs-border-radius: $border-radius !default;\n$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default;\n$nav-tabs-link-active-color: $gray-700 !default;\n$nav-tabs-link-active-bg: $body-bg !default;\n$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default;\n\n$nav-pills-border-radius: $border-radius !default;\n$nav-pills-link-active-color: $component-active-color !default;\n$nav-pills-link-active-bg: $component-active-bg !default;\n\n$nav-divider-color: $gray-200 !default;\n$nav-divider-margin-y: $spacer / 2 !default;\n\n\n// Navbar\n\n$navbar-padding-y: $spacer / 2 !default;\n$navbar-padding-x: $spacer !default;\n\n$navbar-nav-link-padding-x: .5rem !default;\n\n$navbar-brand-font-size: $font-size-lg !default;\n// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link\n$nav-link-height: $font-size-base * $line-height-base + $nav-link-padding-y * 2 !default;\n$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;\n$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default;\n\n$navbar-toggler-padding-y: .25rem !default;\n$navbar-toggler-padding-x: .75rem !default;\n$navbar-toggler-font-size: $font-size-lg !default;\n$navbar-toggler-border-radius: $btn-border-radius !default;\n\n$navbar-dark-color: rgba($white, .5) !default;\n$navbar-dark-hover-color: rgba($white, .75) !default;\n$navbar-dark-active-color: $white !default;\n$navbar-dark-disabled-color: rgba($white, .25) !default;\n$navbar-dark-toggler-icon-bg: url(\"data:image/svg+xml,\") !default;\n$navbar-dark-toggler-border-color: rgba($white, .1) !default;\n\n$navbar-light-color: rgba($black, .5) !default;\n$navbar-light-hover-color: rgba($black, .7) !default;\n$navbar-light-active-color: rgba($black, .9) !default;\n$navbar-light-disabled-color: rgba($black, .3) !default;\n$navbar-light-toggler-icon-bg: url(\"data:image/svg+xml,\") !default;\n$navbar-light-toggler-border-color: rgba($black, .1) !default;\n\n$navbar-light-brand-color: $navbar-light-active-color !default;\n$navbar-light-brand-hover-color: $navbar-light-active-color !default;\n$navbar-dark-brand-color: $navbar-dark-active-color !default;\n$navbar-dark-brand-hover-color: $navbar-dark-active-color !default;\n\n\n// Dropdowns\n//\n// Dropdown menu container and contents.\n\n$dropdown-min-width: 10rem !default;\n$dropdown-padding-x: 0 !default;\n$dropdown-padding-y: .5rem !default;\n$dropdown-spacer: .125rem !default;\n$dropdown-font-size: $font-size-base !default;\n$dropdown-color: $body-color !default;\n$dropdown-bg: $white !default;\n$dropdown-border-color: rgba($black, .15) !default;\n$dropdown-border-radius: $border-radius !default;\n$dropdown-border-width: $border-width !default;\n$dropdown-inner-border-radius: subtract($dropdown-border-radius, $dropdown-border-width) !default;\n$dropdown-divider-bg: $gray-200 !default;\n$dropdown-divider-margin-y: $nav-divider-margin-y !default;\n$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default;\n\n$dropdown-link-color: $gray-900 !default;\n$dropdown-link-hover-color: darken($gray-900, 5%) !default;\n$dropdown-link-hover-bg: $gray-100 !default;\n\n$dropdown-link-active-color: $component-active-color !default;\n$dropdown-link-active-bg: $component-active-bg !default;\n\n$dropdown-link-disabled-color: $gray-600 !default;\n\n$dropdown-item-padding-y: .25rem !default;\n$dropdown-item-padding-x: 1.5rem !default;\n\n$dropdown-header-color: $gray-600 !default;\n$dropdown-header-padding: $dropdown-padding-y $dropdown-item-padding-x !default;\n\n\n// Pagination\n\n$pagination-padding-y: .5rem !default;\n$pagination-padding-x: .75rem !default;\n$pagination-padding-y-sm: .25rem !default;\n$pagination-padding-x-sm: .5rem !default;\n$pagination-padding-y-lg: .75rem !default;\n$pagination-padding-x-lg: 1.5rem !default;\n$pagination-line-height: 1.25 !default;\n\n$pagination-color: $link-color !default;\n$pagination-bg: $white !default;\n$pagination-border-width: $border-width !default;\n$pagination-border-color: $gray-300 !default;\n\n$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$pagination-focus-outline: 0 !default;\n\n$pagination-hover-color: $link-hover-color !default;\n$pagination-hover-bg: $gray-200 !default;\n$pagination-hover-border-color: $gray-300 !default;\n\n$pagination-active-color: $component-active-color !default;\n$pagination-active-bg: $component-active-bg !default;\n$pagination-active-border-color: $pagination-active-bg !default;\n\n$pagination-disabled-color: $gray-600 !default;\n$pagination-disabled-bg: $white !default;\n$pagination-disabled-border-color: $gray-300 !default;\n\n\n// Jumbotron\n\n$jumbotron-padding: 2rem !default;\n$jumbotron-color: null !default;\n$jumbotron-bg: $gray-200 !default;\n\n\n// Cards\n\n$card-spacer-y: .75rem !default;\n$card-spacer-x: 1.25rem !default;\n$card-border-width: $border-width !default;\n$card-border-radius: $border-radius !default;\n$card-border-color: rgba($black, .125) !default;\n$card-inner-border-radius: subtract($card-border-radius, $card-border-width) !default;\n$card-cap-bg: rgba($black, .03) !default;\n$card-cap-color: null !default;\n$card-height: null !default;\n$card-color: null !default;\n$card-bg: $white !default;\n\n$card-img-overlay-padding: 1.25rem !default;\n\n$card-group-margin: $grid-gutter-width / 2 !default;\n$card-deck-margin: $card-group-margin !default;\n\n$card-columns-count: 3 !default;\n$card-columns-gap: 1.25rem !default;\n$card-columns-margin: $card-spacer-y !default;\n\n\n// Tooltips\n\n$tooltip-font-size: $font-size-sm !default;\n$tooltip-max-width: 200px !default;\n$tooltip-color: $white !default;\n$tooltip-bg: $black !default;\n$tooltip-border-radius: $border-radius !default;\n$tooltip-opacity: .9 !default;\n$tooltip-padding-y: .25rem !default;\n$tooltip-padding-x: .5rem !default;\n$tooltip-margin: 0 !default;\n\n$tooltip-arrow-width: .8rem !default;\n$tooltip-arrow-height: .4rem !default;\n$tooltip-arrow-color: $tooltip-bg !default;\n\n// Form tooltips must come after regular tooltips\n$form-feedback-tooltip-padding-y: $tooltip-padding-y !default;\n$form-feedback-tooltip-padding-x: $tooltip-padding-x !default;\n$form-feedback-tooltip-font-size: $tooltip-font-size !default;\n$form-feedback-tooltip-line-height: $line-height-base !default;\n$form-feedback-tooltip-opacity: $tooltip-opacity !default;\n$form-feedback-tooltip-border-radius: $tooltip-border-radius !default;\n\n\n// Popovers\n\n$popover-font-size: $font-size-sm !default;\n$popover-bg: $white !default;\n$popover-max-width: 276px !default;\n$popover-border-width: $border-width !default;\n$popover-border-color: rgba($black, .2) !default;\n$popover-border-radius: $border-radius-lg !default;\n$popover-inner-border-radius: subtract($popover-border-radius, $popover-border-width) !default;\n$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default;\n\n$popover-header-bg: darken($popover-bg, 3%) !default;\n$popover-header-color: $headings-color !default;\n$popover-header-padding-y: .5rem !default;\n$popover-header-padding-x: .75rem !default;\n\n$popover-body-color: $body-color !default;\n$popover-body-padding-y: $popover-header-padding-y !default;\n$popover-body-padding-x: $popover-header-padding-x !default;\n\n$popover-arrow-width: 1rem !default;\n$popover-arrow-height: .5rem !default;\n$popover-arrow-color: $popover-bg !default;\n\n$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default;\n\n\n// Toasts\n\n$toast-max-width: 350px !default;\n$toast-padding-x: .75rem !default;\n$toast-padding-y: .25rem !default;\n$toast-font-size: .875rem !default;\n$toast-color: null !default;\n$toast-background-color: rgba($white, .85) !default;\n$toast-border-width: 1px !default;\n$toast-border-color: rgba(0, 0, 0, .1) !default;\n$toast-border-radius: .25rem !default;\n$toast-box-shadow: 0 .25rem .75rem rgba($black, .1) !default;\n\n$toast-header-color: $gray-600 !default;\n$toast-header-background-color: rgba($white, .85) !default;\n$toast-header-border-color: rgba(0, 0, 0, .05) !default;\n\n\n// Badges\n\n$badge-font-size: 75% !default;\n$badge-font-weight: $font-weight-bold !default;\n$badge-padding-y: .25em !default;\n$badge-padding-x: .4em !default;\n$badge-border-radius: $border-radius !default;\n\n$badge-transition: $btn-transition !default;\n$badge-focus-width: $input-btn-focus-width !default;\n\n$badge-pill-padding-x: .6em !default;\n// Use a higher than normal value to ensure completely rounded edges when\n// customizing padding or font-size on labels.\n$badge-pill-border-radius: 10rem !default;\n\n\n// Modals\n\n// Padding applied to the modal body\n$modal-inner-padding: 1rem !default;\n\n// Margin between elements in footer, must be lower than or equal to 2 * $modal-inner-padding\n$modal-footer-margin-between: .5rem !default;\n\n$modal-dialog-margin: .5rem !default;\n$modal-dialog-margin-y-sm-up: 1.75rem !default;\n\n$modal-title-line-height: $line-height-base !default;\n\n$modal-content-color: null !default;\n$modal-content-bg: $white !default;\n$modal-content-border-color: rgba($black, .2) !default;\n$modal-content-border-width: $border-width !default;\n$modal-content-border-radius: $border-radius-lg !default;\n$modal-content-inner-border-radius: subtract($modal-content-border-radius, $modal-content-border-width) !default;\n$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default;\n$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default;\n\n$modal-backdrop-bg: $black !default;\n$modal-backdrop-opacity: .5 !default;\n$modal-header-border-color: $border-color !default;\n$modal-footer-border-color: $modal-header-border-color !default;\n$modal-header-border-width: $modal-content-border-width !default;\n$modal-footer-border-width: $modal-header-border-width !default;\n$modal-header-padding-y: 1rem !default;\n$modal-header-padding-x: 1rem !default;\n$modal-header-padding: $modal-header-padding-y $modal-header-padding-x !default; // Keep this for backwards compatibility\n\n$modal-xl: 1140px !default;\n$modal-lg: 800px !default;\n$modal-md: 500px !default;\n$modal-sm: 300px !default;\n\n$modal-fade-transform: translate(0, -50px) !default;\n$modal-show-transform: none !default;\n$modal-transition: transform .3s ease-out !default;\n$modal-scale-transform: scale(1.02) !default;\n\n\n// Alerts\n//\n// Define alert colors, border radius, and padding.\n\n$alert-padding-y: .75rem !default;\n$alert-padding-x: 1.25rem !default;\n$alert-margin-bottom: 1rem !default;\n$alert-border-radius: $border-radius !default;\n$alert-link-font-weight: $font-weight-bold !default;\n$alert-border-width: $border-width !default;\n\n$alert-bg-level: -10 !default;\n$alert-border-level: -9 !default;\n$alert-color-level: 6 !default;\n\n\n// Progress bars\n\n$progress-height: 1rem !default;\n$progress-font-size: $font-size-base * .75 !default;\n$progress-bg: $gray-200 !default;\n$progress-border-radius: $border-radius !default;\n$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default;\n$progress-bar-color: $white !default;\n$progress-bar-bg: theme-color(\"primary\") !default;\n$progress-bar-animation-timing: 1s linear infinite !default;\n$progress-bar-transition: width .6s ease !default;\n\n\n// List group\n\n$list-group-color: null !default;\n$list-group-bg: $white !default;\n$list-group-border-color: rgba($black, .125) !default;\n$list-group-border-width: $border-width !default;\n$list-group-border-radius: $border-radius !default;\n\n$list-group-item-padding-y: .75rem !default;\n$list-group-item-padding-x: 1.25rem !default;\n\n$list-group-hover-bg: $gray-100 !default;\n$list-group-active-color: $component-active-color !default;\n$list-group-active-bg: $component-active-bg !default;\n$list-group-active-border-color: $list-group-active-bg !default;\n\n$list-group-disabled-color: $gray-600 !default;\n$list-group-disabled-bg: $list-group-bg !default;\n\n$list-group-action-color: $gray-700 !default;\n$list-group-action-hover-color: $list-group-action-color !default;\n\n$list-group-action-active-color: $body-color !default;\n$list-group-action-active-bg: $gray-200 !default;\n\n\n// Image thumbnails\n\n$thumbnail-padding: .25rem !default;\n$thumbnail-bg: $body-bg !default;\n$thumbnail-border-width: $border-width !default;\n$thumbnail-border-color: $gray-300 !default;\n$thumbnail-border-radius: $border-radius !default;\n$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default;\n\n\n// Figures\n\n$figure-caption-font-size: 90% !default;\n$figure-caption-color: $gray-600 !default;\n\n\n// Breadcrumbs\n\n$breadcrumb-font-size: null !default;\n\n$breadcrumb-padding-y: .75rem !default;\n$breadcrumb-padding-x: 1rem !default;\n$breadcrumb-item-padding: .5rem !default;\n\n$breadcrumb-margin-bottom: 1rem !default;\n\n$breadcrumb-bg: $gray-200 !default;\n$breadcrumb-divider-color: $gray-600 !default;\n$breadcrumb-active-color: $gray-600 !default;\n$breadcrumb-divider: quote(\"/\") !default;\n\n$breadcrumb-border-radius: $border-radius !default;\n\n\n// Carousel\n\n$carousel-control-color: $white !default;\n$carousel-control-width: 15% !default;\n$carousel-control-opacity: .5 !default;\n$carousel-control-hover-opacity: .9 !default;\n$carousel-control-transition: opacity .15s ease !default;\n\n$carousel-indicator-width: 30px !default;\n$carousel-indicator-height: 3px !default;\n$carousel-indicator-hit-area-height: 10px !default;\n$carousel-indicator-spacer: 3px !default;\n$carousel-indicator-active-bg: $white !default;\n$carousel-indicator-transition: opacity .6s ease !default;\n\n$carousel-caption-width: 70% !default;\n$carousel-caption-color: $white !default;\n\n$carousel-control-icon-width: 20px !default;\n\n$carousel-control-prev-icon-bg: url(\"data:image/svg+xml,\") !default;\n$carousel-control-next-icon-bg: url(\"data:image/svg+xml,\") !default;\n\n$carousel-transition-duration: .6s !default;\n$carousel-transition: transform $carousel-transition-duration ease-in-out !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)\n\n\n// Spinners\n\n$spinner-width: 2rem !default;\n$spinner-height: $spinner-width !default;\n$spinner-border-width: .25em !default;\n\n$spinner-width-sm: 1rem !default;\n$spinner-height-sm: $spinner-width-sm !default;\n$spinner-border-width-sm: .2em !default;\n\n\n// Close\n\n$close-font-size: $font-size-base * 1.5 !default;\n$close-font-weight: $font-weight-bold !default;\n$close-color: $black !default;\n$close-text-shadow: 0 1px 0 $white !default;\n\n\n// Code\n\n$code-font-size: 87.5% !default;\n$code-color: $pink !default;\n\n$kbd-padding-y: .2rem !default;\n$kbd-padding-x: .4rem !default;\n$kbd-font-size: $code-font-size !default;\n$kbd-color: $white !default;\n$kbd-bg: $gray-900 !default;\n\n$pre-color: $gray-900 !default;\n$pre-scrollable-max-height: 340px !default;\n\n\n// Utilities\n\n$displays: none, inline, inline-block, block, table, table-row, table-cell, flex, inline-flex !default;\n$overflows: auto, hidden !default;\n$positions: static, relative, absolute, fixed, sticky !default;\n$user-selects: all, auto, none !default;\n\n\n// Printing\n\n$print-page-size: a3 !default;\n$print-body-min-width: map-get($grid-breakpoints, \"lg\") !default;\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `$grid-columns`.\n\n@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {\n // Common properties for all breakpoints\n %grid-column {\n position: relative;\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n }\n\n @each $breakpoint in map-keys($breakpoints) {\n $infix: breakpoint-infix($breakpoint, $breakpoints);\n\n @if $columns > 0 {\n // Allow columns to stretch full width below their breakpoints\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @extend %grid-column;\n }\n }\n }\n\n .col#{$infix},\n .col#{$infix}-auto {\n @extend %grid-column;\n }\n\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n // Provide basic `.col-{bp}` classes for equal-width flexbox columns\n .col#{$infix} {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n\n @if $grid-row-columns > 0 {\n @for $i from 1 through $grid-row-columns {\n .row-cols#{$infix}-#{$i} {\n @include row-cols($i);\n }\n }\n }\n\n .col#{$infix}-auto {\n @include make-col-auto();\n }\n\n @if $columns > 0 {\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @include make-col($i, $columns);\n }\n }\n }\n\n .order#{$infix}-first { order: -1; }\n\n .order#{$infix}-last { order: $columns + 1; }\n\n @for $i from 0 through $columns {\n .order#{$infix}-#{$i} { order: $i; }\n }\n\n @if $columns > 0 {\n // `$columns - 1` because offsetting by the width of an entire row isn't possible\n @for $i from 0 through ($columns - 1) {\n @if not ($infix == \"\" and $i == 0) { // Avoid emitting useless .offset-0\n .offset#{$infix}-#{$i} {\n @include make-col-offset($i, $columns);\n }\n }\n }\n }\n }\n }\n}\n","// stylelint-disable declaration-no-important\n\n//\n// Utilities for common `display` values\n//\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n @each $value in $displays {\n .d#{$infix}-#{$value} { display: $value !important; }\n }\n }\n}\n\n\n//\n// Utilities for toggling `display` in print\n//\n\n@media print {\n @each $value in $displays {\n .d-print-#{$value} { display: $value !important; }\n }\n}\n","// stylelint-disable declaration-no-important\n\n// Flex variation\n//\n// Custom styles for additional flex alignment options.\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .flex#{$infix}-row { flex-direction: row !important; }\n .flex#{$infix}-column { flex-direction: column !important; }\n .flex#{$infix}-row-reverse { flex-direction: row-reverse !important; }\n .flex#{$infix}-column-reverse { flex-direction: column-reverse !important; }\n\n .flex#{$infix}-wrap { flex-wrap: wrap !important; }\n .flex#{$infix}-nowrap { flex-wrap: nowrap !important; }\n .flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; }\n .flex#{$infix}-fill { flex: 1 1 auto !important; }\n .flex#{$infix}-grow-0 { flex-grow: 0 !important; }\n .flex#{$infix}-grow-1 { flex-grow: 1 !important; }\n .flex#{$infix}-shrink-0 { flex-shrink: 0 !important; }\n .flex#{$infix}-shrink-1 { flex-shrink: 1 !important; }\n\n .justify-content#{$infix}-start { justify-content: flex-start !important; }\n .justify-content#{$infix}-end { justify-content: flex-end !important; }\n .justify-content#{$infix}-center { justify-content: center !important; }\n .justify-content#{$infix}-between { justify-content: space-between !important; }\n .justify-content#{$infix}-around { justify-content: space-around !important; }\n\n .align-items#{$infix}-start { align-items: flex-start !important; }\n .align-items#{$infix}-end { align-items: flex-end !important; }\n .align-items#{$infix}-center { align-items: center !important; }\n .align-items#{$infix}-baseline { align-items: baseline !important; }\n .align-items#{$infix}-stretch { align-items: stretch !important; }\n\n .align-content#{$infix}-start { align-content: flex-start !important; }\n .align-content#{$infix}-end { align-content: flex-end !important; }\n .align-content#{$infix}-center { align-content: center !important; }\n .align-content#{$infix}-between { align-content: space-between !important; }\n .align-content#{$infix}-around { align-content: space-around !important; }\n .align-content#{$infix}-stretch { align-content: stretch !important; }\n\n .align-self#{$infix}-auto { align-self: auto !important; }\n .align-self#{$infix}-start { align-self: flex-start !important; }\n .align-self#{$infix}-end { align-self: flex-end !important; }\n .align-self#{$infix}-center { align-self: center !important; }\n .align-self#{$infix}-baseline { align-self: baseline !important; }\n .align-self#{$infix}-stretch { align-self: stretch !important; }\n }\n}\n","// stylelint-disable declaration-no-important\n\n// Margin and Padding\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n @each $prop, $abbrev in (margin: m, padding: p) {\n @each $size, $length in $spacers {\n .#{$abbrev}#{$infix}-#{$size} { #{$prop}: $length !important; }\n .#{$abbrev}t#{$infix}-#{$size},\n .#{$abbrev}y#{$infix}-#{$size} {\n #{$prop}-top: $length !important;\n }\n .#{$abbrev}r#{$infix}-#{$size},\n .#{$abbrev}x#{$infix}-#{$size} {\n #{$prop}-right: $length !important;\n }\n .#{$abbrev}b#{$infix}-#{$size},\n .#{$abbrev}y#{$infix}-#{$size} {\n #{$prop}-bottom: $length !important;\n }\n .#{$abbrev}l#{$infix}-#{$size},\n .#{$abbrev}x#{$infix}-#{$size} {\n #{$prop}-left: $length !important;\n }\n }\n }\n\n // Negative margins (e.g., where `.mb-n1` is negative version of `.mb-1`)\n @each $size, $length in $spacers {\n @if $size != 0 {\n .m#{$infix}-n#{$size} { margin: -$length !important; }\n .mt#{$infix}-n#{$size},\n .my#{$infix}-n#{$size} {\n margin-top: -$length !important;\n }\n .mr#{$infix}-n#{$size},\n .mx#{$infix}-n#{$size} {\n margin-right: -$length !important;\n }\n .mb#{$infix}-n#{$size},\n .my#{$infix}-n#{$size} {\n margin-bottom: -$length !important;\n }\n .ml#{$infix}-n#{$size},\n .mx#{$infix}-n#{$size} {\n margin-left: -$length !important;\n }\n }\n }\n\n // Some special margin utils\n .m#{$infix}-auto { margin: auto !important; }\n .mt#{$infix}-auto,\n .my#{$infix}-auto {\n margin-top: auto !important;\n }\n .mr#{$infix}-auto,\n .mx#{$infix}-auto {\n margin-right: auto !important;\n }\n .mb#{$infix}-auto,\n .my#{$infix}-auto {\n margin-bottom: auto !important;\n }\n .ml#{$infix}-auto,\n .mx#{$infix}-auto {\n margin-left: auto !important;\n }\n }\n}\n"]} \ No newline at end of file diff --git a/archive/SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css b/archive/SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css deleted file mode 100644 index d323f93f..00000000 --- a/archive/SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Bootstrap Grid v4.5.3 (https://getbootstrap.com/) - * Copyright 2011-2020 The Bootstrap Authors - * Copyright 2011-2020 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - */html{box-sizing:border-box;-ms-overflow-style:scrollbar}*,::after,::before{box-sizing:inherit}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-sm-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-sm-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-md-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-md-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-md-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-md-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-md-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-md-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-lg-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-lg-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-xl-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-xl-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}} -/*# sourceMappingURL=bootstrap-grid.min.css.map */ \ No newline at end of file diff --git a/archive/SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map b/archive/SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map deleted file mode 100644 index 9c96ff30..00000000 --- a/archive/SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["../../scss/bootstrap-grid.scss","dist/css/bootstrap-grid.css","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_breakpoints.scss","../../scss/mixins/_grid-framework.scss","../../scss/utilities/_display.scss","../../scss/utilities/_flex.scss","../../scss/utilities/_spacing.scss"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Bootstrap Grid v4.5.3 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors\n * Copyright 2011-2020 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\n\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n@import \"functions\";\n@import \"variables\";\n\n@import \"mixins/breakpoints\";\n@import \"mixins/grid-framework\";\n@import \"mixins/grid\";\n\n@import \"grid\";\n@import \"utilities/display\";\n@import \"utilities/flex\";\n@import \"utilities/spacing\";\n","/*!\n * Bootstrap Grid v4.5.3 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors\n * Copyright 2011-2020 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n */\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n.container,\n.container-fluid,\n.container-sm,\n.container-md,\n.container-lg,\n.container-xl {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n@media (min-width: 576px) {\n .container, .container-sm {\n max-width: 540px;\n }\n}\n\n@media (min-width: 768px) {\n .container, .container-sm, .container-md {\n max-width: 720px;\n }\n}\n\n@media (min-width: 992px) {\n .container, .container-sm, .container-md, .container-lg {\n max-width: 960px;\n }\n}\n\n@media (min-width: 1200px) {\n .container, .container-sm, .container-md, .container-lg, .container-xl {\n max-width: 1140px;\n }\n}\n\n.row {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-wrap: wrap;\n flex-wrap: wrap;\n margin-right: -15px;\n margin-left: -15px;\n}\n\n.no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n\n.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n position: relative;\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n}\n\n.col {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n}\n\n.row-cols-1 > * {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.row-cols-2 > * {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.row-cols-3 > * {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.row-cols-4 > * {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.row-cols-5 > * {\n -ms-flex: 0 0 20%;\n flex: 0 0 20%;\n max-width: 20%;\n}\n\n.row-cols-6 > * {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n}\n\n.col-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n}\n\n.col-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.col-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.col-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n}\n\n.col-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.col-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n}\n\n.col-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n}\n\n.col-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n}\n\n.col-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n}\n\n.col-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n}\n\n.col-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.order-first {\n -ms-flex-order: -1;\n order: -1;\n}\n\n.order-last {\n -ms-flex-order: 13;\n order: 13;\n}\n\n.order-0 {\n -ms-flex-order: 0;\n order: 0;\n}\n\n.order-1 {\n -ms-flex-order: 1;\n order: 1;\n}\n\n.order-2 {\n -ms-flex-order: 2;\n order: 2;\n}\n\n.order-3 {\n -ms-flex-order: 3;\n order: 3;\n}\n\n.order-4 {\n -ms-flex-order: 4;\n order: 4;\n}\n\n.order-5 {\n -ms-flex-order: 5;\n order: 5;\n}\n\n.order-6 {\n -ms-flex-order: 6;\n order: 6;\n}\n\n.order-7 {\n -ms-flex-order: 7;\n order: 7;\n}\n\n.order-8 {\n -ms-flex-order: 8;\n order: 8;\n}\n\n.order-9 {\n -ms-flex-order: 9;\n order: 9;\n}\n\n.order-10 {\n -ms-flex-order: 10;\n order: 10;\n}\n\n.order-11 {\n -ms-flex-order: 11;\n order: 11;\n}\n\n.order-12 {\n -ms-flex-order: 12;\n order: 12;\n}\n\n.offset-1 {\n margin-left: 8.333333%;\n}\n\n.offset-2 {\n margin-left: 16.666667%;\n}\n\n.offset-3 {\n margin-left: 25%;\n}\n\n.offset-4 {\n margin-left: 33.333333%;\n}\n\n.offset-5 {\n margin-left: 41.666667%;\n}\n\n.offset-6 {\n margin-left: 50%;\n}\n\n.offset-7 {\n margin-left: 58.333333%;\n}\n\n.offset-8 {\n margin-left: 66.666667%;\n}\n\n.offset-9 {\n margin-left: 75%;\n}\n\n.offset-10 {\n margin-left: 83.333333%;\n}\n\n.offset-11 {\n margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n .col-sm {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .row-cols-sm-1 > * {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .row-cols-sm-2 > * {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .row-cols-sm-3 > * {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .row-cols-sm-4 > * {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .row-cols-sm-5 > * {\n -ms-flex: 0 0 20%;\n flex: 0 0 20%;\n max-width: 20%;\n }\n .row-cols-sm-6 > * {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-sm-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-sm-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-sm-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-sm-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-sm-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-sm-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-sm-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-sm-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-sm-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-sm-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-sm-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-sm-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-sm-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-sm-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-sm-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-sm-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-sm-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-sm-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-sm-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-sm-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-sm-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-sm-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-sm-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-sm-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-sm-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-sm-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-sm-0 {\n margin-left: 0;\n }\n .offset-sm-1 {\n margin-left: 8.333333%;\n }\n .offset-sm-2 {\n margin-left: 16.666667%;\n }\n .offset-sm-3 {\n margin-left: 25%;\n }\n .offset-sm-4 {\n margin-left: 33.333333%;\n }\n .offset-sm-5 {\n margin-left: 41.666667%;\n }\n .offset-sm-6 {\n margin-left: 50%;\n }\n .offset-sm-7 {\n margin-left: 58.333333%;\n }\n .offset-sm-8 {\n margin-left: 66.666667%;\n }\n .offset-sm-9 {\n margin-left: 75%;\n }\n .offset-sm-10 {\n margin-left: 83.333333%;\n }\n .offset-sm-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 768px) {\n .col-md {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .row-cols-md-1 > * {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .row-cols-md-2 > * {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .row-cols-md-3 > * {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .row-cols-md-4 > * {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .row-cols-md-5 > * {\n -ms-flex: 0 0 20%;\n flex: 0 0 20%;\n max-width: 20%;\n }\n .row-cols-md-6 > * {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-md-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-md-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-md-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-md-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-md-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-md-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-md-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-md-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-md-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-md-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-md-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-md-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-md-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-md-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-md-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-md-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-md-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-md-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-md-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-md-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-md-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-md-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-md-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-md-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-md-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-md-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-md-0 {\n margin-left: 0;\n }\n .offset-md-1 {\n margin-left: 8.333333%;\n }\n .offset-md-2 {\n margin-left: 16.666667%;\n }\n .offset-md-3 {\n margin-left: 25%;\n }\n .offset-md-4 {\n margin-left: 33.333333%;\n }\n .offset-md-5 {\n margin-left: 41.666667%;\n }\n .offset-md-6 {\n margin-left: 50%;\n }\n .offset-md-7 {\n margin-left: 58.333333%;\n }\n .offset-md-8 {\n margin-left: 66.666667%;\n }\n .offset-md-9 {\n margin-left: 75%;\n }\n .offset-md-10 {\n margin-left: 83.333333%;\n }\n .offset-md-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 992px) {\n .col-lg {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .row-cols-lg-1 > * {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .row-cols-lg-2 > * {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .row-cols-lg-3 > * {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .row-cols-lg-4 > * {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .row-cols-lg-5 > * {\n -ms-flex: 0 0 20%;\n flex: 0 0 20%;\n max-width: 20%;\n }\n .row-cols-lg-6 > * {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-lg-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-lg-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-lg-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-lg-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-lg-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-lg-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-lg-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-lg-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-lg-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-lg-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-lg-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-lg-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-lg-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-lg-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-lg-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-lg-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-lg-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-lg-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-lg-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-lg-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-lg-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-lg-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-lg-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-lg-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-lg-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-lg-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-lg-0 {\n margin-left: 0;\n }\n .offset-lg-1 {\n margin-left: 8.333333%;\n }\n .offset-lg-2 {\n margin-left: 16.666667%;\n }\n .offset-lg-3 {\n margin-left: 25%;\n }\n .offset-lg-4 {\n margin-left: 33.333333%;\n }\n .offset-lg-5 {\n margin-left: 41.666667%;\n }\n .offset-lg-6 {\n margin-left: 50%;\n }\n .offset-lg-7 {\n margin-left: 58.333333%;\n }\n .offset-lg-8 {\n margin-left: 66.666667%;\n }\n .offset-lg-9 {\n margin-left: 75%;\n }\n .offset-lg-10 {\n margin-left: 83.333333%;\n }\n .offset-lg-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 1200px) {\n .col-xl {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .row-cols-xl-1 > * {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .row-cols-xl-2 > * {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .row-cols-xl-3 > * {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .row-cols-xl-4 > * {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .row-cols-xl-5 > * {\n -ms-flex: 0 0 20%;\n flex: 0 0 20%;\n max-width: 20%;\n }\n .row-cols-xl-6 > * {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-xl-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-xl-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-xl-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-xl-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-xl-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-xl-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-xl-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-xl-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-xl-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-xl-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-xl-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-xl-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-xl-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-xl-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-xl-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-xl-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-xl-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-xl-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-xl-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-xl-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-xl-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-xl-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-xl-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-xl-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-xl-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-xl-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-xl-0 {\n margin-left: 0;\n }\n .offset-xl-1 {\n margin-left: 8.333333%;\n }\n .offset-xl-2 {\n margin-left: 16.666667%;\n }\n .offset-xl-3 {\n margin-left: 25%;\n }\n .offset-xl-4 {\n margin-left: 33.333333%;\n }\n .offset-xl-5 {\n margin-left: 41.666667%;\n }\n .offset-xl-6 {\n margin-left: 50%;\n }\n .offset-xl-7 {\n margin-left: 58.333333%;\n }\n .offset-xl-8 {\n margin-left: 66.666667%;\n }\n .offset-xl-9 {\n margin-left: 75%;\n }\n .offset-xl-10 {\n margin-left: 83.333333%;\n }\n .offset-xl-11 {\n margin-left: 91.666667%;\n }\n}\n\n.d-none {\n display: none !important;\n}\n\n.d-inline {\n display: inline !important;\n}\n\n.d-inline-block {\n display: inline-block !important;\n}\n\n.d-block {\n display: block !important;\n}\n\n.d-table {\n display: table !important;\n}\n\n.d-table-row {\n display: table-row !important;\n}\n\n.d-table-cell {\n display: table-cell !important;\n}\n\n.d-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n}\n\n.d-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n}\n\n@media (min-width: 576px) {\n .d-sm-none {\n display: none !important;\n }\n .d-sm-inline {\n display: inline !important;\n }\n .d-sm-inline-block {\n display: inline-block !important;\n }\n .d-sm-block {\n display: block !important;\n }\n .d-sm-table {\n display: table !important;\n }\n .d-sm-table-row {\n display: table-row !important;\n }\n .d-sm-table-cell {\n display: table-cell !important;\n }\n .d-sm-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-sm-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 768px) {\n .d-md-none {\n display: none !important;\n }\n .d-md-inline {\n display: inline !important;\n }\n .d-md-inline-block {\n display: inline-block !important;\n }\n .d-md-block {\n display: block !important;\n }\n .d-md-table {\n display: table !important;\n }\n .d-md-table-row {\n display: table-row !important;\n }\n .d-md-table-cell {\n display: table-cell !important;\n }\n .d-md-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-md-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 992px) {\n .d-lg-none {\n display: none !important;\n }\n .d-lg-inline {\n display: inline !important;\n }\n .d-lg-inline-block {\n display: inline-block !important;\n }\n .d-lg-block {\n display: block !important;\n }\n .d-lg-table {\n display: table !important;\n }\n .d-lg-table-row {\n display: table-row !important;\n }\n .d-lg-table-cell {\n display: table-cell !important;\n }\n .d-lg-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-lg-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 1200px) {\n .d-xl-none {\n display: none !important;\n }\n .d-xl-inline {\n display: inline !important;\n }\n .d-xl-inline-block {\n display: inline-block !important;\n }\n .d-xl-block {\n display: block !important;\n }\n .d-xl-table {\n display: table !important;\n }\n .d-xl-table-row {\n display: table-row !important;\n }\n .d-xl-table-cell {\n display: table-cell !important;\n }\n .d-xl-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-xl-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media print {\n .d-print-none {\n display: none !important;\n }\n .d-print-inline {\n display: inline !important;\n }\n .d-print-inline-block {\n display: inline-block !important;\n }\n .d-print-block {\n display: block !important;\n }\n .d-print-table {\n display: table !important;\n }\n .d-print-table-row {\n display: table-row !important;\n }\n .d-print-table-cell {\n display: table-cell !important;\n }\n .d-print-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-print-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n.flex-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n}\n\n.flex-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n}\n\n.flex-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n}\n\n.flex-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n}\n\n.flex-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n}\n\n.flex-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n}\n\n.flex-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n}\n\n.flex-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n}\n\n.justify-content-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n}\n\n.justify-content-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n}\n\n.justify-content-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n}\n\n.justify-content-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n}\n\n.justify-content-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n}\n\n.align-items-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n}\n\n.align-items-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n}\n\n.align-items-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n}\n\n.align-items-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n}\n\n.align-items-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n}\n\n.align-content-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n}\n\n.align-content-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n}\n\n.align-content-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n}\n\n.align-content-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n}\n\n.align-content-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n}\n\n.align-content-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n}\n\n.align-self-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n}\n\n.align-self-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n}\n\n.align-self-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n}\n\n.align-self-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n}\n\n.align-self-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n}\n\n.align-self-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n .flex-sm-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-sm-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-sm-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-sm-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-sm-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-sm-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-sm-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-sm-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-sm-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-sm-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-sm-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-sm-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-sm-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-sm-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-sm-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-sm-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-sm-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-sm-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-sm-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-sm-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-sm-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-sm-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-sm-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-sm-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-sm-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-sm-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-sm-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-sm-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-sm-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-sm-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-sm-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-sm-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-sm-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-sm-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 768px) {\n .flex-md-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-md-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-md-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-md-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-md-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-md-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-md-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-md-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-md-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-md-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-md-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-md-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-md-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-md-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-md-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-md-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-md-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-md-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-md-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-md-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-md-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-md-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-md-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-md-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-md-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-md-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-md-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-md-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-md-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-md-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-md-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-md-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-md-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-md-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 992px) {\n .flex-lg-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-lg-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-lg-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-lg-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-lg-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-lg-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-lg-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-lg-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-lg-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-lg-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-lg-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-lg-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-lg-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-lg-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-lg-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-lg-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-lg-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-lg-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-lg-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-lg-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-lg-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-lg-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-lg-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-lg-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-lg-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-lg-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-lg-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-lg-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-lg-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-lg-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-lg-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-lg-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-lg-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-lg-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 1200px) {\n .flex-xl-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-xl-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-xl-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-xl-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-xl-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-xl-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-xl-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-xl-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-xl-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-xl-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-xl-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-xl-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-xl-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-xl-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-xl-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-xl-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-xl-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-xl-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-xl-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-xl-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-xl-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-xl-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-xl-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-xl-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-xl-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-xl-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-xl-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-xl-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-xl-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-xl-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-xl-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-xl-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-xl-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-xl-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n.m-0 {\n margin: 0 !important;\n}\n\n.mt-0,\n.my-0 {\n margin-top: 0 !important;\n}\n\n.mr-0,\n.mx-0 {\n margin-right: 0 !important;\n}\n\n.mb-0,\n.my-0 {\n margin-bottom: 0 !important;\n}\n\n.ml-0,\n.mx-0 {\n margin-left: 0 !important;\n}\n\n.m-1 {\n margin: 0.25rem !important;\n}\n\n.mt-1,\n.my-1 {\n margin-top: 0.25rem !important;\n}\n\n.mr-1,\n.mx-1 {\n margin-right: 0.25rem !important;\n}\n\n.mb-1,\n.my-1 {\n margin-bottom: 0.25rem !important;\n}\n\n.ml-1,\n.mx-1 {\n margin-left: 0.25rem !important;\n}\n\n.m-2 {\n margin: 0.5rem !important;\n}\n\n.mt-2,\n.my-2 {\n margin-top: 0.5rem !important;\n}\n\n.mr-2,\n.mx-2 {\n margin-right: 0.5rem !important;\n}\n\n.mb-2,\n.my-2 {\n margin-bottom: 0.5rem !important;\n}\n\n.ml-2,\n.mx-2 {\n margin-left: 0.5rem !important;\n}\n\n.m-3 {\n margin: 1rem !important;\n}\n\n.mt-3,\n.my-3 {\n margin-top: 1rem !important;\n}\n\n.mr-3,\n.mx-3 {\n margin-right: 1rem !important;\n}\n\n.mb-3,\n.my-3 {\n margin-bottom: 1rem !important;\n}\n\n.ml-3,\n.mx-3 {\n margin-left: 1rem !important;\n}\n\n.m-4 {\n margin: 1.5rem !important;\n}\n\n.mt-4,\n.my-4 {\n margin-top: 1.5rem !important;\n}\n\n.mr-4,\n.mx-4 {\n margin-right: 1.5rem !important;\n}\n\n.mb-4,\n.my-4 {\n margin-bottom: 1.5rem !important;\n}\n\n.ml-4,\n.mx-4 {\n margin-left: 1.5rem !important;\n}\n\n.m-5 {\n margin: 3rem !important;\n}\n\n.mt-5,\n.my-5 {\n margin-top: 3rem !important;\n}\n\n.mr-5,\n.mx-5 {\n margin-right: 3rem !important;\n}\n\n.mb-5,\n.my-5 {\n margin-bottom: 3rem !important;\n}\n\n.ml-5,\n.mx-5 {\n margin-left: 3rem !important;\n}\n\n.p-0 {\n padding: 0 !important;\n}\n\n.pt-0,\n.py-0 {\n padding-top: 0 !important;\n}\n\n.pr-0,\n.px-0 {\n padding-right: 0 !important;\n}\n\n.pb-0,\n.py-0 {\n padding-bottom: 0 !important;\n}\n\n.pl-0,\n.px-0 {\n padding-left: 0 !important;\n}\n\n.p-1 {\n padding: 0.25rem !important;\n}\n\n.pt-1,\n.py-1 {\n padding-top: 0.25rem !important;\n}\n\n.pr-1,\n.px-1 {\n padding-right: 0.25rem !important;\n}\n\n.pb-1,\n.py-1 {\n padding-bottom: 0.25rem !important;\n}\n\n.pl-1,\n.px-1 {\n padding-left: 0.25rem !important;\n}\n\n.p-2 {\n padding: 0.5rem !important;\n}\n\n.pt-2,\n.py-2 {\n padding-top: 0.5rem !important;\n}\n\n.pr-2,\n.px-2 {\n padding-right: 0.5rem !important;\n}\n\n.pb-2,\n.py-2 {\n padding-bottom: 0.5rem !important;\n}\n\n.pl-2,\n.px-2 {\n padding-left: 0.5rem !important;\n}\n\n.p-3 {\n padding: 1rem !important;\n}\n\n.pt-3,\n.py-3 {\n padding-top: 1rem !important;\n}\n\n.pr-3,\n.px-3 {\n padding-right: 1rem !important;\n}\n\n.pb-3,\n.py-3 {\n padding-bottom: 1rem !important;\n}\n\n.pl-3,\n.px-3 {\n padding-left: 1rem !important;\n}\n\n.p-4 {\n padding: 1.5rem !important;\n}\n\n.pt-4,\n.py-4 {\n padding-top: 1.5rem !important;\n}\n\n.pr-4,\n.px-4 {\n padding-right: 1.5rem !important;\n}\n\n.pb-4,\n.py-4 {\n padding-bottom: 1.5rem !important;\n}\n\n.pl-4,\n.px-4 {\n padding-left: 1.5rem !important;\n}\n\n.p-5 {\n padding: 3rem !important;\n}\n\n.pt-5,\n.py-5 {\n padding-top: 3rem !important;\n}\n\n.pr-5,\n.px-5 {\n padding-right: 3rem !important;\n}\n\n.pb-5,\n.py-5 {\n padding-bottom: 3rem !important;\n}\n\n.pl-5,\n.px-5 {\n padding-left: 3rem !important;\n}\n\n.m-n1 {\n margin: -0.25rem !important;\n}\n\n.mt-n1,\n.my-n1 {\n margin-top: -0.25rem !important;\n}\n\n.mr-n1,\n.mx-n1 {\n margin-right: -0.25rem !important;\n}\n\n.mb-n1,\n.my-n1 {\n margin-bottom: -0.25rem !important;\n}\n\n.ml-n1,\n.mx-n1 {\n margin-left: -0.25rem !important;\n}\n\n.m-n2 {\n margin: -0.5rem !important;\n}\n\n.mt-n2,\n.my-n2 {\n margin-top: -0.5rem !important;\n}\n\n.mr-n2,\n.mx-n2 {\n margin-right: -0.5rem !important;\n}\n\n.mb-n2,\n.my-n2 {\n margin-bottom: -0.5rem !important;\n}\n\n.ml-n2,\n.mx-n2 {\n margin-left: -0.5rem !important;\n}\n\n.m-n3 {\n margin: -1rem !important;\n}\n\n.mt-n3,\n.my-n3 {\n margin-top: -1rem !important;\n}\n\n.mr-n3,\n.mx-n3 {\n margin-right: -1rem !important;\n}\n\n.mb-n3,\n.my-n3 {\n margin-bottom: -1rem !important;\n}\n\n.ml-n3,\n.mx-n3 {\n margin-left: -1rem !important;\n}\n\n.m-n4 {\n margin: -1.5rem !important;\n}\n\n.mt-n4,\n.my-n4 {\n margin-top: -1.5rem !important;\n}\n\n.mr-n4,\n.mx-n4 {\n margin-right: -1.5rem !important;\n}\n\n.mb-n4,\n.my-n4 {\n margin-bottom: -1.5rem !important;\n}\n\n.ml-n4,\n.mx-n4 {\n margin-left: -1.5rem !important;\n}\n\n.m-n5 {\n margin: -3rem !important;\n}\n\n.mt-n5,\n.my-n5 {\n margin-top: -3rem !important;\n}\n\n.mr-n5,\n.mx-n5 {\n margin-right: -3rem !important;\n}\n\n.mb-n5,\n.my-n5 {\n margin-bottom: -3rem !important;\n}\n\n.ml-n5,\n.mx-n5 {\n margin-left: -3rem !important;\n}\n\n.m-auto {\n margin: auto !important;\n}\n\n.mt-auto,\n.my-auto {\n margin-top: auto !important;\n}\n\n.mr-auto,\n.mx-auto {\n margin-right: auto !important;\n}\n\n.mb-auto,\n.my-auto {\n margin-bottom: auto !important;\n}\n\n.ml-auto,\n.mx-auto {\n margin-left: auto !important;\n}\n\n@media (min-width: 576px) {\n .m-sm-0 {\n margin: 0 !important;\n }\n .mt-sm-0,\n .my-sm-0 {\n margin-top: 0 !important;\n }\n .mr-sm-0,\n .mx-sm-0 {\n margin-right: 0 !important;\n }\n .mb-sm-0,\n .my-sm-0 {\n margin-bottom: 0 !important;\n }\n .ml-sm-0,\n .mx-sm-0 {\n margin-left: 0 !important;\n }\n .m-sm-1 {\n margin: 0.25rem !important;\n }\n .mt-sm-1,\n .my-sm-1 {\n margin-top: 0.25rem !important;\n }\n .mr-sm-1,\n .mx-sm-1 {\n margin-right: 0.25rem !important;\n }\n .mb-sm-1,\n .my-sm-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-sm-1,\n .mx-sm-1 {\n margin-left: 0.25rem !important;\n }\n .m-sm-2 {\n margin: 0.5rem !important;\n }\n .mt-sm-2,\n .my-sm-2 {\n margin-top: 0.5rem !important;\n }\n .mr-sm-2,\n .mx-sm-2 {\n margin-right: 0.5rem !important;\n }\n .mb-sm-2,\n .my-sm-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-sm-2,\n .mx-sm-2 {\n margin-left: 0.5rem !important;\n }\n .m-sm-3 {\n margin: 1rem !important;\n }\n .mt-sm-3,\n .my-sm-3 {\n margin-top: 1rem !important;\n }\n .mr-sm-3,\n .mx-sm-3 {\n margin-right: 1rem !important;\n }\n .mb-sm-3,\n .my-sm-3 {\n margin-bottom: 1rem !important;\n }\n .ml-sm-3,\n .mx-sm-3 {\n margin-left: 1rem !important;\n }\n .m-sm-4 {\n margin: 1.5rem !important;\n }\n .mt-sm-4,\n .my-sm-4 {\n margin-top: 1.5rem !important;\n }\n .mr-sm-4,\n .mx-sm-4 {\n margin-right: 1.5rem !important;\n }\n .mb-sm-4,\n .my-sm-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-sm-4,\n .mx-sm-4 {\n margin-left: 1.5rem !important;\n }\n .m-sm-5 {\n margin: 3rem !important;\n }\n .mt-sm-5,\n .my-sm-5 {\n margin-top: 3rem !important;\n }\n .mr-sm-5,\n .mx-sm-5 {\n margin-right: 3rem !important;\n }\n .mb-sm-5,\n .my-sm-5 {\n margin-bottom: 3rem !important;\n }\n .ml-sm-5,\n .mx-sm-5 {\n margin-left: 3rem !important;\n }\n .p-sm-0 {\n padding: 0 !important;\n }\n .pt-sm-0,\n .py-sm-0 {\n padding-top: 0 !important;\n }\n .pr-sm-0,\n .px-sm-0 {\n padding-right: 0 !important;\n }\n .pb-sm-0,\n .py-sm-0 {\n padding-bottom: 0 !important;\n }\n .pl-sm-0,\n .px-sm-0 {\n padding-left: 0 !important;\n }\n .p-sm-1 {\n padding: 0.25rem !important;\n }\n .pt-sm-1,\n .py-sm-1 {\n padding-top: 0.25rem !important;\n }\n .pr-sm-1,\n .px-sm-1 {\n padding-right: 0.25rem !important;\n }\n .pb-sm-1,\n .py-sm-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-sm-1,\n .px-sm-1 {\n padding-left: 0.25rem !important;\n }\n .p-sm-2 {\n padding: 0.5rem !important;\n }\n .pt-sm-2,\n .py-sm-2 {\n padding-top: 0.5rem !important;\n }\n .pr-sm-2,\n .px-sm-2 {\n padding-right: 0.5rem !important;\n }\n .pb-sm-2,\n .py-sm-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-sm-2,\n .px-sm-2 {\n padding-left: 0.5rem !important;\n }\n .p-sm-3 {\n padding: 1rem !important;\n }\n .pt-sm-3,\n .py-sm-3 {\n padding-top: 1rem !important;\n }\n .pr-sm-3,\n .px-sm-3 {\n padding-right: 1rem !important;\n }\n .pb-sm-3,\n .py-sm-3 {\n padding-bottom: 1rem !important;\n }\n .pl-sm-3,\n .px-sm-3 {\n padding-left: 1rem !important;\n }\n .p-sm-4 {\n padding: 1.5rem !important;\n }\n .pt-sm-4,\n .py-sm-4 {\n padding-top: 1.5rem !important;\n }\n .pr-sm-4,\n .px-sm-4 {\n padding-right: 1.5rem !important;\n }\n .pb-sm-4,\n .py-sm-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-sm-4,\n .px-sm-4 {\n padding-left: 1.5rem !important;\n }\n .p-sm-5 {\n padding: 3rem !important;\n }\n .pt-sm-5,\n .py-sm-5 {\n padding-top: 3rem !important;\n }\n .pr-sm-5,\n .px-sm-5 {\n padding-right: 3rem !important;\n }\n .pb-sm-5,\n .py-sm-5 {\n padding-bottom: 3rem !important;\n }\n .pl-sm-5,\n .px-sm-5 {\n padding-left: 3rem !important;\n }\n .m-sm-n1 {\n margin: -0.25rem !important;\n }\n .mt-sm-n1,\n .my-sm-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-sm-n1,\n .mx-sm-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-sm-n1,\n .my-sm-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-sm-n1,\n .mx-sm-n1 {\n margin-left: -0.25rem !important;\n }\n .m-sm-n2 {\n margin: -0.5rem !important;\n }\n .mt-sm-n2,\n .my-sm-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-sm-n2,\n .mx-sm-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-sm-n2,\n .my-sm-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-sm-n2,\n .mx-sm-n2 {\n margin-left: -0.5rem !important;\n }\n .m-sm-n3 {\n margin: -1rem !important;\n }\n .mt-sm-n3,\n .my-sm-n3 {\n margin-top: -1rem !important;\n }\n .mr-sm-n3,\n .mx-sm-n3 {\n margin-right: -1rem !important;\n }\n .mb-sm-n3,\n .my-sm-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-sm-n3,\n .mx-sm-n3 {\n margin-left: -1rem !important;\n }\n .m-sm-n4 {\n margin: -1.5rem !important;\n }\n .mt-sm-n4,\n .my-sm-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-sm-n4,\n .mx-sm-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-sm-n4,\n .my-sm-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-sm-n4,\n .mx-sm-n4 {\n margin-left: -1.5rem !important;\n }\n .m-sm-n5 {\n margin: -3rem !important;\n }\n .mt-sm-n5,\n .my-sm-n5 {\n margin-top: -3rem !important;\n }\n .mr-sm-n5,\n .mx-sm-n5 {\n margin-right: -3rem !important;\n }\n .mb-sm-n5,\n .my-sm-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-sm-n5,\n .mx-sm-n5 {\n margin-left: -3rem !important;\n }\n .m-sm-auto {\n margin: auto !important;\n }\n .mt-sm-auto,\n .my-sm-auto {\n margin-top: auto !important;\n }\n .mr-sm-auto,\n .mx-sm-auto {\n margin-right: auto !important;\n }\n .mb-sm-auto,\n .my-sm-auto {\n margin-bottom: auto !important;\n }\n .ml-sm-auto,\n .mx-sm-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 768px) {\n .m-md-0 {\n margin: 0 !important;\n }\n .mt-md-0,\n .my-md-0 {\n margin-top: 0 !important;\n }\n .mr-md-0,\n .mx-md-0 {\n margin-right: 0 !important;\n }\n .mb-md-0,\n .my-md-0 {\n margin-bottom: 0 !important;\n }\n .ml-md-0,\n .mx-md-0 {\n margin-left: 0 !important;\n }\n .m-md-1 {\n margin: 0.25rem !important;\n }\n .mt-md-1,\n .my-md-1 {\n margin-top: 0.25rem !important;\n }\n .mr-md-1,\n .mx-md-1 {\n margin-right: 0.25rem !important;\n }\n .mb-md-1,\n .my-md-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-md-1,\n .mx-md-1 {\n margin-left: 0.25rem !important;\n }\n .m-md-2 {\n margin: 0.5rem !important;\n }\n .mt-md-2,\n .my-md-2 {\n margin-top: 0.5rem !important;\n }\n .mr-md-2,\n .mx-md-2 {\n margin-right: 0.5rem !important;\n }\n .mb-md-2,\n .my-md-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-md-2,\n .mx-md-2 {\n margin-left: 0.5rem !important;\n }\n .m-md-3 {\n margin: 1rem !important;\n }\n .mt-md-3,\n .my-md-3 {\n margin-top: 1rem !important;\n }\n .mr-md-3,\n .mx-md-3 {\n margin-right: 1rem !important;\n }\n .mb-md-3,\n .my-md-3 {\n margin-bottom: 1rem !important;\n }\n .ml-md-3,\n .mx-md-3 {\n margin-left: 1rem !important;\n }\n .m-md-4 {\n margin: 1.5rem !important;\n }\n .mt-md-4,\n .my-md-4 {\n margin-top: 1.5rem !important;\n }\n .mr-md-4,\n .mx-md-4 {\n margin-right: 1.5rem !important;\n }\n .mb-md-4,\n .my-md-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-md-4,\n .mx-md-4 {\n margin-left: 1.5rem !important;\n }\n .m-md-5 {\n margin: 3rem !important;\n }\n .mt-md-5,\n .my-md-5 {\n margin-top: 3rem !important;\n }\n .mr-md-5,\n .mx-md-5 {\n margin-right: 3rem !important;\n }\n .mb-md-5,\n .my-md-5 {\n margin-bottom: 3rem !important;\n }\n .ml-md-5,\n .mx-md-5 {\n margin-left: 3rem !important;\n }\n .p-md-0 {\n padding: 0 !important;\n }\n .pt-md-0,\n .py-md-0 {\n padding-top: 0 !important;\n }\n .pr-md-0,\n .px-md-0 {\n padding-right: 0 !important;\n }\n .pb-md-0,\n .py-md-0 {\n padding-bottom: 0 !important;\n }\n .pl-md-0,\n .px-md-0 {\n padding-left: 0 !important;\n }\n .p-md-1 {\n padding: 0.25rem !important;\n }\n .pt-md-1,\n .py-md-1 {\n padding-top: 0.25rem !important;\n }\n .pr-md-1,\n .px-md-1 {\n padding-right: 0.25rem !important;\n }\n .pb-md-1,\n .py-md-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-md-1,\n .px-md-1 {\n padding-left: 0.25rem !important;\n }\n .p-md-2 {\n padding: 0.5rem !important;\n }\n .pt-md-2,\n .py-md-2 {\n padding-top: 0.5rem !important;\n }\n .pr-md-2,\n .px-md-2 {\n padding-right: 0.5rem !important;\n }\n .pb-md-2,\n .py-md-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-md-2,\n .px-md-2 {\n padding-left: 0.5rem !important;\n }\n .p-md-3 {\n padding: 1rem !important;\n }\n .pt-md-3,\n .py-md-3 {\n padding-top: 1rem !important;\n }\n .pr-md-3,\n .px-md-3 {\n padding-right: 1rem !important;\n }\n .pb-md-3,\n .py-md-3 {\n padding-bottom: 1rem !important;\n }\n .pl-md-3,\n .px-md-3 {\n padding-left: 1rem !important;\n }\n .p-md-4 {\n padding: 1.5rem !important;\n }\n .pt-md-4,\n .py-md-4 {\n padding-top: 1.5rem !important;\n }\n .pr-md-4,\n .px-md-4 {\n padding-right: 1.5rem !important;\n }\n .pb-md-4,\n .py-md-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-md-4,\n .px-md-4 {\n padding-left: 1.5rem !important;\n }\n .p-md-5 {\n padding: 3rem !important;\n }\n .pt-md-5,\n .py-md-5 {\n padding-top: 3rem !important;\n }\n .pr-md-5,\n .px-md-5 {\n padding-right: 3rem !important;\n }\n .pb-md-5,\n .py-md-5 {\n padding-bottom: 3rem !important;\n }\n .pl-md-5,\n .px-md-5 {\n padding-left: 3rem !important;\n }\n .m-md-n1 {\n margin: -0.25rem !important;\n }\n .mt-md-n1,\n .my-md-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-md-n1,\n .mx-md-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-md-n1,\n .my-md-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-md-n1,\n .mx-md-n1 {\n margin-left: -0.25rem !important;\n }\n .m-md-n2 {\n margin: -0.5rem !important;\n }\n .mt-md-n2,\n .my-md-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-md-n2,\n .mx-md-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-md-n2,\n .my-md-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-md-n2,\n .mx-md-n2 {\n margin-left: -0.5rem !important;\n }\n .m-md-n3 {\n margin: -1rem !important;\n }\n .mt-md-n3,\n .my-md-n3 {\n margin-top: -1rem !important;\n }\n .mr-md-n3,\n .mx-md-n3 {\n margin-right: -1rem !important;\n }\n .mb-md-n3,\n .my-md-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-md-n3,\n .mx-md-n3 {\n margin-left: -1rem !important;\n }\n .m-md-n4 {\n margin: -1.5rem !important;\n }\n .mt-md-n4,\n .my-md-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-md-n4,\n .mx-md-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-md-n4,\n .my-md-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-md-n4,\n .mx-md-n4 {\n margin-left: -1.5rem !important;\n }\n .m-md-n5 {\n margin: -3rem !important;\n }\n .mt-md-n5,\n .my-md-n5 {\n margin-top: -3rem !important;\n }\n .mr-md-n5,\n .mx-md-n5 {\n margin-right: -3rem !important;\n }\n .mb-md-n5,\n .my-md-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-md-n5,\n .mx-md-n5 {\n margin-left: -3rem !important;\n }\n .m-md-auto {\n margin: auto !important;\n }\n .mt-md-auto,\n .my-md-auto {\n margin-top: auto !important;\n }\n .mr-md-auto,\n .mx-md-auto {\n margin-right: auto !important;\n }\n .mb-md-auto,\n .my-md-auto {\n margin-bottom: auto !important;\n }\n .ml-md-auto,\n .mx-md-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 992px) {\n .m-lg-0 {\n margin: 0 !important;\n }\n .mt-lg-0,\n .my-lg-0 {\n margin-top: 0 !important;\n }\n .mr-lg-0,\n .mx-lg-0 {\n margin-right: 0 !important;\n }\n .mb-lg-0,\n .my-lg-0 {\n margin-bottom: 0 !important;\n }\n .ml-lg-0,\n .mx-lg-0 {\n margin-left: 0 !important;\n }\n .m-lg-1 {\n margin: 0.25rem !important;\n }\n .mt-lg-1,\n .my-lg-1 {\n margin-top: 0.25rem !important;\n }\n .mr-lg-1,\n .mx-lg-1 {\n margin-right: 0.25rem !important;\n }\n .mb-lg-1,\n .my-lg-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-lg-1,\n .mx-lg-1 {\n margin-left: 0.25rem !important;\n }\n .m-lg-2 {\n margin: 0.5rem !important;\n }\n .mt-lg-2,\n .my-lg-2 {\n margin-top: 0.5rem !important;\n }\n .mr-lg-2,\n .mx-lg-2 {\n margin-right: 0.5rem !important;\n }\n .mb-lg-2,\n .my-lg-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-lg-2,\n .mx-lg-2 {\n margin-left: 0.5rem !important;\n }\n .m-lg-3 {\n margin: 1rem !important;\n }\n .mt-lg-3,\n .my-lg-3 {\n margin-top: 1rem !important;\n }\n .mr-lg-3,\n .mx-lg-3 {\n margin-right: 1rem !important;\n }\n .mb-lg-3,\n .my-lg-3 {\n margin-bottom: 1rem !important;\n }\n .ml-lg-3,\n .mx-lg-3 {\n margin-left: 1rem !important;\n }\n .m-lg-4 {\n margin: 1.5rem !important;\n }\n .mt-lg-4,\n .my-lg-4 {\n margin-top: 1.5rem !important;\n }\n .mr-lg-4,\n .mx-lg-4 {\n margin-right: 1.5rem !important;\n }\n .mb-lg-4,\n .my-lg-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-lg-4,\n .mx-lg-4 {\n margin-left: 1.5rem !important;\n }\n .m-lg-5 {\n margin: 3rem !important;\n }\n .mt-lg-5,\n .my-lg-5 {\n margin-top: 3rem !important;\n }\n .mr-lg-5,\n .mx-lg-5 {\n margin-right: 3rem !important;\n }\n .mb-lg-5,\n .my-lg-5 {\n margin-bottom: 3rem !important;\n }\n .ml-lg-5,\n .mx-lg-5 {\n margin-left: 3rem !important;\n }\n .p-lg-0 {\n padding: 0 !important;\n }\n .pt-lg-0,\n .py-lg-0 {\n padding-top: 0 !important;\n }\n .pr-lg-0,\n .px-lg-0 {\n padding-right: 0 !important;\n }\n .pb-lg-0,\n .py-lg-0 {\n padding-bottom: 0 !important;\n }\n .pl-lg-0,\n .px-lg-0 {\n padding-left: 0 !important;\n }\n .p-lg-1 {\n padding: 0.25rem !important;\n }\n .pt-lg-1,\n .py-lg-1 {\n padding-top: 0.25rem !important;\n }\n .pr-lg-1,\n .px-lg-1 {\n padding-right: 0.25rem !important;\n }\n .pb-lg-1,\n .py-lg-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-lg-1,\n .px-lg-1 {\n padding-left: 0.25rem !important;\n }\n .p-lg-2 {\n padding: 0.5rem !important;\n }\n .pt-lg-2,\n .py-lg-2 {\n padding-top: 0.5rem !important;\n }\n .pr-lg-2,\n .px-lg-2 {\n padding-right: 0.5rem !important;\n }\n .pb-lg-2,\n .py-lg-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-lg-2,\n .px-lg-2 {\n padding-left: 0.5rem !important;\n }\n .p-lg-3 {\n padding: 1rem !important;\n }\n .pt-lg-3,\n .py-lg-3 {\n padding-top: 1rem !important;\n }\n .pr-lg-3,\n .px-lg-3 {\n padding-right: 1rem !important;\n }\n .pb-lg-3,\n .py-lg-3 {\n padding-bottom: 1rem !important;\n }\n .pl-lg-3,\n .px-lg-3 {\n padding-left: 1rem !important;\n }\n .p-lg-4 {\n padding: 1.5rem !important;\n }\n .pt-lg-4,\n .py-lg-4 {\n padding-top: 1.5rem !important;\n }\n .pr-lg-4,\n .px-lg-4 {\n padding-right: 1.5rem !important;\n }\n .pb-lg-4,\n .py-lg-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-lg-4,\n .px-lg-4 {\n padding-left: 1.5rem !important;\n }\n .p-lg-5 {\n padding: 3rem !important;\n }\n .pt-lg-5,\n .py-lg-5 {\n padding-top: 3rem !important;\n }\n .pr-lg-5,\n .px-lg-5 {\n padding-right: 3rem !important;\n }\n .pb-lg-5,\n .py-lg-5 {\n padding-bottom: 3rem !important;\n }\n .pl-lg-5,\n .px-lg-5 {\n padding-left: 3rem !important;\n }\n .m-lg-n1 {\n margin: -0.25rem !important;\n }\n .mt-lg-n1,\n .my-lg-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-lg-n1,\n .mx-lg-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-lg-n1,\n .my-lg-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-lg-n1,\n .mx-lg-n1 {\n margin-left: -0.25rem !important;\n }\n .m-lg-n2 {\n margin: -0.5rem !important;\n }\n .mt-lg-n2,\n .my-lg-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-lg-n2,\n .mx-lg-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-lg-n2,\n .my-lg-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-lg-n2,\n .mx-lg-n2 {\n margin-left: -0.5rem !important;\n }\n .m-lg-n3 {\n margin: -1rem !important;\n }\n .mt-lg-n3,\n .my-lg-n3 {\n margin-top: -1rem !important;\n }\n .mr-lg-n3,\n .mx-lg-n3 {\n margin-right: -1rem !important;\n }\n .mb-lg-n3,\n .my-lg-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-lg-n3,\n .mx-lg-n3 {\n margin-left: -1rem !important;\n }\n .m-lg-n4 {\n margin: -1.5rem !important;\n }\n .mt-lg-n4,\n .my-lg-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-lg-n4,\n .mx-lg-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-lg-n4,\n .my-lg-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-lg-n4,\n .mx-lg-n4 {\n margin-left: -1.5rem !important;\n }\n .m-lg-n5 {\n margin: -3rem !important;\n }\n .mt-lg-n5,\n .my-lg-n5 {\n margin-top: -3rem !important;\n }\n .mr-lg-n5,\n .mx-lg-n5 {\n margin-right: -3rem !important;\n }\n .mb-lg-n5,\n .my-lg-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-lg-n5,\n .mx-lg-n5 {\n margin-left: -3rem !important;\n }\n .m-lg-auto {\n margin: auto !important;\n }\n .mt-lg-auto,\n .my-lg-auto {\n margin-top: auto !important;\n }\n .mr-lg-auto,\n .mx-lg-auto {\n margin-right: auto !important;\n }\n .mb-lg-auto,\n .my-lg-auto {\n margin-bottom: auto !important;\n }\n .ml-lg-auto,\n .mx-lg-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 1200px) {\n .m-xl-0 {\n margin: 0 !important;\n }\n .mt-xl-0,\n .my-xl-0 {\n margin-top: 0 !important;\n }\n .mr-xl-0,\n .mx-xl-0 {\n margin-right: 0 !important;\n }\n .mb-xl-0,\n .my-xl-0 {\n margin-bottom: 0 !important;\n }\n .ml-xl-0,\n .mx-xl-0 {\n margin-left: 0 !important;\n }\n .m-xl-1 {\n margin: 0.25rem !important;\n }\n .mt-xl-1,\n .my-xl-1 {\n margin-top: 0.25rem !important;\n }\n .mr-xl-1,\n .mx-xl-1 {\n margin-right: 0.25rem !important;\n }\n .mb-xl-1,\n .my-xl-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-xl-1,\n .mx-xl-1 {\n margin-left: 0.25rem !important;\n }\n .m-xl-2 {\n margin: 0.5rem !important;\n }\n .mt-xl-2,\n .my-xl-2 {\n margin-top: 0.5rem !important;\n }\n .mr-xl-2,\n .mx-xl-2 {\n margin-right: 0.5rem !important;\n }\n .mb-xl-2,\n .my-xl-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-xl-2,\n .mx-xl-2 {\n margin-left: 0.5rem !important;\n }\n .m-xl-3 {\n margin: 1rem !important;\n }\n .mt-xl-3,\n .my-xl-3 {\n margin-top: 1rem !important;\n }\n .mr-xl-3,\n .mx-xl-3 {\n margin-right: 1rem !important;\n }\n .mb-xl-3,\n .my-xl-3 {\n margin-bottom: 1rem !important;\n }\n .ml-xl-3,\n .mx-xl-3 {\n margin-left: 1rem !important;\n }\n .m-xl-4 {\n margin: 1.5rem !important;\n }\n .mt-xl-4,\n .my-xl-4 {\n margin-top: 1.5rem !important;\n }\n .mr-xl-4,\n .mx-xl-4 {\n margin-right: 1.5rem !important;\n }\n .mb-xl-4,\n .my-xl-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-xl-4,\n .mx-xl-4 {\n margin-left: 1.5rem !important;\n }\n .m-xl-5 {\n margin: 3rem !important;\n }\n .mt-xl-5,\n .my-xl-5 {\n margin-top: 3rem !important;\n }\n .mr-xl-5,\n .mx-xl-5 {\n margin-right: 3rem !important;\n }\n .mb-xl-5,\n .my-xl-5 {\n margin-bottom: 3rem !important;\n }\n .ml-xl-5,\n .mx-xl-5 {\n margin-left: 3rem !important;\n }\n .p-xl-0 {\n padding: 0 !important;\n }\n .pt-xl-0,\n .py-xl-0 {\n padding-top: 0 !important;\n }\n .pr-xl-0,\n .px-xl-0 {\n padding-right: 0 !important;\n }\n .pb-xl-0,\n .py-xl-0 {\n padding-bottom: 0 !important;\n }\n .pl-xl-0,\n .px-xl-0 {\n padding-left: 0 !important;\n }\n .p-xl-1 {\n padding: 0.25rem !important;\n }\n .pt-xl-1,\n .py-xl-1 {\n padding-top: 0.25rem !important;\n }\n .pr-xl-1,\n .px-xl-1 {\n padding-right: 0.25rem !important;\n }\n .pb-xl-1,\n .py-xl-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-xl-1,\n .px-xl-1 {\n padding-left: 0.25rem !important;\n }\n .p-xl-2 {\n padding: 0.5rem !important;\n }\n .pt-xl-2,\n .py-xl-2 {\n padding-top: 0.5rem !important;\n }\n .pr-xl-2,\n .px-xl-2 {\n padding-right: 0.5rem !important;\n }\n .pb-xl-2,\n .py-xl-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-xl-2,\n .px-xl-2 {\n padding-left: 0.5rem !important;\n }\n .p-xl-3 {\n padding: 1rem !important;\n }\n .pt-xl-3,\n .py-xl-3 {\n padding-top: 1rem !important;\n }\n .pr-xl-3,\n .px-xl-3 {\n padding-right: 1rem !important;\n }\n .pb-xl-3,\n .py-xl-3 {\n padding-bottom: 1rem !important;\n }\n .pl-xl-3,\n .px-xl-3 {\n padding-left: 1rem !important;\n }\n .p-xl-4 {\n padding: 1.5rem !important;\n }\n .pt-xl-4,\n .py-xl-4 {\n padding-top: 1.5rem !important;\n }\n .pr-xl-4,\n .px-xl-4 {\n padding-right: 1.5rem !important;\n }\n .pb-xl-4,\n .py-xl-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-xl-4,\n .px-xl-4 {\n padding-left: 1.5rem !important;\n }\n .p-xl-5 {\n padding: 3rem !important;\n }\n .pt-xl-5,\n .py-xl-5 {\n padding-top: 3rem !important;\n }\n .pr-xl-5,\n .px-xl-5 {\n padding-right: 3rem !important;\n }\n .pb-xl-5,\n .py-xl-5 {\n padding-bottom: 3rem !important;\n }\n .pl-xl-5,\n .px-xl-5 {\n padding-left: 3rem !important;\n }\n .m-xl-n1 {\n margin: -0.25rem !important;\n }\n .mt-xl-n1,\n .my-xl-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-xl-n1,\n .mx-xl-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-xl-n1,\n .my-xl-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-xl-n1,\n .mx-xl-n1 {\n margin-left: -0.25rem !important;\n }\n .m-xl-n2 {\n margin: -0.5rem !important;\n }\n .mt-xl-n2,\n .my-xl-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-xl-n2,\n .mx-xl-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-xl-n2,\n .my-xl-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-xl-n2,\n .mx-xl-n2 {\n margin-left: -0.5rem !important;\n }\n .m-xl-n3 {\n margin: -1rem !important;\n }\n .mt-xl-n3,\n .my-xl-n3 {\n margin-top: -1rem !important;\n }\n .mr-xl-n3,\n .mx-xl-n3 {\n margin-right: -1rem !important;\n }\n .mb-xl-n3,\n .my-xl-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-xl-n3,\n .mx-xl-n3 {\n margin-left: -1rem !important;\n }\n .m-xl-n4 {\n margin: -1.5rem !important;\n }\n .mt-xl-n4,\n .my-xl-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-xl-n4,\n .mx-xl-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-xl-n4,\n .my-xl-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-xl-n4,\n .mx-xl-n4 {\n margin-left: -1.5rem !important;\n }\n .m-xl-n5 {\n margin: -3rem !important;\n }\n .mt-xl-n5,\n .my-xl-n5 {\n margin-top: -3rem !important;\n }\n .mr-xl-n5,\n .mx-xl-n5 {\n margin-right: -3rem !important;\n }\n .mb-xl-n5,\n .my-xl-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-xl-n5,\n .mx-xl-n5 {\n margin-left: -3rem !important;\n }\n .m-xl-auto {\n margin: auto !important;\n }\n .mt-xl-auto,\n .my-xl-auto {\n margin-top: auto !important;\n }\n .mr-xl-auto,\n .mx-xl-auto {\n margin-right: auto !important;\n }\n .mb-xl-auto,\n .my-xl-auto {\n margin-bottom: auto !important;\n }\n .ml-xl-auto,\n .mx-xl-auto {\n margin-left: auto !important;\n }\n}\n/*# sourceMappingURL=bootstrap-grid.css.map */","// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n@if $enable-grid-classes {\n // Single container class with breakpoint max-widths\n .container,\n // 100% wide container at all breakpoints\n .container-fluid {\n @include make-container();\n }\n\n // Responsive containers that are 100% wide until a breakpoint\n @each $breakpoint, $container-max-width in $container-max-widths {\n .container-#{$breakpoint} {\n @extend .container-fluid;\n }\n\n @include media-breakpoint-up($breakpoint, $grid-breakpoints) {\n %responsive-container-#{$breakpoint} {\n max-width: $container-max-width;\n }\n\n // Extend each breakpoint which is smaller or equal to the current breakpoint\n $extend-breakpoint: true;\n\n @each $name, $width in $grid-breakpoints {\n @if ($extend-breakpoint) {\n .container#{breakpoint-infix($name, $grid-breakpoints)} {\n @extend %responsive-container-#{$breakpoint};\n }\n\n // Once the current breakpoint is reached, stop extending\n @if ($breakpoint == $name) {\n $extend-breakpoint: false;\n }\n }\n }\n }\n }\n}\n\n\n// Row\n//\n// Rows contain your columns.\n\n@if $enable-grid-classes {\n .row {\n @include make-row();\n }\n\n // Remove the negative margin from default .row, then the horizontal padding\n // from all immediate children columns (to prevent runaway style inheritance).\n .no-gutters {\n margin-right: 0;\n margin-left: 0;\n\n > .col,\n > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n }\n }\n}\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n@if $enable-grid-classes {\n @include make-grid-columns();\n}\n","/// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n@mixin make-container($gutter: $grid-gutter-width) {\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n margin-right: auto;\n margin-left: auto;\n}\n\n@mixin make-row($gutter: $grid-gutter-width) {\n display: flex;\n flex-wrap: wrap;\n margin-right: -$gutter / 2;\n margin-left: -$gutter / 2;\n}\n\n// For each breakpoint, define the maximum width of the container in a media query\n@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {\n @each $breakpoint, $container-max-width in $max-widths {\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n max-width: $container-max-width;\n }\n }\n @include deprecate(\"The `make-container-max-widths` mixin\", \"v4.5.2\", \"v5\");\n}\n\n@mixin make-col-ready($gutter: $grid-gutter-width) {\n position: relative;\n // Prevent columns from becoming too narrow when at smaller grid tiers by\n // always setting `width: 100%;`. This works because we use `flex` values\n // later on to override this initial width.\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n}\n\n@mixin make-col($size, $columns: $grid-columns) {\n flex: 0 0 percentage($size / $columns);\n // Add a `max-width` to ensure content within each column does not blow out\n // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari\n // do not appear to require this.\n max-width: percentage($size / $columns);\n}\n\n@mixin make-col-auto() {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%; // Reset earlier grid tiers\n}\n\n@mixin make-col-offset($size, $columns: $grid-columns) {\n $num: $size / $columns;\n margin-left: if($num == 0, 0, percentage($num));\n}\n\n// Row columns\n//\n// Specify on a parent element(e.g., .row) to force immediate children into NN\n// numberof columns. Supports wrapping to new lines, but does not do a Masonry\n// style grid.\n@mixin row-cols($count) {\n > * {\n flex: 0 0 100% / $count;\n max-width: 100% / $count;\n }\n}\n","// Breakpoint viewport sizes and media queries.\n//\n// Breakpoints are defined as a map of (name: minimum width), order from small to large:\n//\n// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)\n//\n// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.\n\n// Name of the next breakpoint, or null for the last breakpoint.\n//\n// >> breakpoint-next(sm)\n// md\n// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// md\n// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))\n// md\n@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {\n $n: index($breakpoint-names, $name);\n @return if($n != null and $n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);\n}\n\n// Minimum breakpoint width. Null for the smallest (first) breakpoint.\n//\n// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 576px\n@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {\n $min: map-get($breakpoints, $name);\n @return if($min != 0, $min, null);\n}\n\n// Maximum breakpoint width. Null for the largest (last) breakpoint.\n// The maximum value is calculated as the minimum of the next one less 0.02px\n// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.\n// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max\n// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.\n// See https://bugs.webkit.org/show_bug.cgi?id=178261\n//\n// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 767.98px\n@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {\n $next: breakpoint-next($name, $breakpoints);\n @return if($next, breakpoint-min($next, $breakpoints) - .02, null);\n}\n\n// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.\n// Useful for making responsive utilities.\n//\n// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"\" (Returns a blank string)\n// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"-sm\"\n@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {\n @return if(breakpoint-min($name, $breakpoints) == null, \"\", \"-#{$name}\");\n}\n\n// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.\n// Makes the @content apply to the given breakpoint and wider.\n@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n @if $min {\n @media (min-width: $min) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media of at most the maximum breakpoint width. No query for the largest breakpoint.\n// Makes the @content apply to the given breakpoint and narrower.\n@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {\n $max: breakpoint-max($name, $breakpoints);\n @if $max {\n @media (max-width: $max) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media that spans multiple breakpoint widths.\n// Makes the @content apply between the min and max breakpoints\n@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($lower, $breakpoints);\n $max: breakpoint-max($upper, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($lower, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($upper, $breakpoints) {\n @content;\n }\n }\n}\n\n// Media between the breakpoint's minimum and maximum widths.\n// No minimum for the smallest breakpoint, and no maximum for the largest one.\n// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.\n@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n $max: breakpoint-max($name, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($name, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($name, $breakpoints) {\n @content;\n }\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `$grid-columns`.\n\n@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {\n // Common properties for all breakpoints\n %grid-column {\n position: relative;\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n }\n\n @each $breakpoint in map-keys($breakpoints) {\n $infix: breakpoint-infix($breakpoint, $breakpoints);\n\n @if $columns > 0 {\n // Allow columns to stretch full width below their breakpoints\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @extend %grid-column;\n }\n }\n }\n\n .col#{$infix},\n .col#{$infix}-auto {\n @extend %grid-column;\n }\n\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n // Provide basic `.col-{bp}` classes for equal-width flexbox columns\n .col#{$infix} {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n\n @if $grid-row-columns > 0 {\n @for $i from 1 through $grid-row-columns {\n .row-cols#{$infix}-#{$i} {\n @include row-cols($i);\n }\n }\n }\n\n .col#{$infix}-auto {\n @include make-col-auto();\n }\n\n @if $columns > 0 {\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @include make-col($i, $columns);\n }\n }\n }\n\n .order#{$infix}-first { order: -1; }\n\n .order#{$infix}-last { order: $columns + 1; }\n\n @for $i from 0 through $columns {\n .order#{$infix}-#{$i} { order: $i; }\n }\n\n @if $columns > 0 {\n // `$columns - 1` because offsetting by the width of an entire row isn't possible\n @for $i from 0 through ($columns - 1) {\n @if not ($infix == \"\" and $i == 0) { // Avoid emitting useless .offset-0\n .offset#{$infix}-#{$i} {\n @include make-col-offset($i, $columns);\n }\n }\n }\n }\n }\n }\n}\n","// stylelint-disable declaration-no-important\n\n//\n// Utilities for common `display` values\n//\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n @each $value in $displays {\n .d#{$infix}-#{$value} { display: $value !important; }\n }\n }\n}\n\n\n//\n// Utilities for toggling `display` in print\n//\n\n@media print {\n @each $value in $displays {\n .d-print-#{$value} { display: $value !important; }\n }\n}\n","// stylelint-disable declaration-no-important\n\n// Flex variation\n//\n// Custom styles for additional flex alignment options.\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .flex#{$infix}-row { flex-direction: row !important; }\n .flex#{$infix}-column { flex-direction: column !important; }\n .flex#{$infix}-row-reverse { flex-direction: row-reverse !important; }\n .flex#{$infix}-column-reverse { flex-direction: column-reverse !important; }\n\n .flex#{$infix}-wrap { flex-wrap: wrap !important; }\n .flex#{$infix}-nowrap { flex-wrap: nowrap !important; }\n .flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; }\n .flex#{$infix}-fill { flex: 1 1 auto !important; }\n .flex#{$infix}-grow-0 { flex-grow: 0 !important; }\n .flex#{$infix}-grow-1 { flex-grow: 1 !important; }\n .flex#{$infix}-shrink-0 { flex-shrink: 0 !important; }\n .flex#{$infix}-shrink-1 { flex-shrink: 1 !important; }\n\n .justify-content#{$infix}-start { justify-content: flex-start !important; }\n .justify-content#{$infix}-end { justify-content: flex-end !important; }\n .justify-content#{$infix}-center { justify-content: center !important; }\n .justify-content#{$infix}-between { justify-content: space-between !important; }\n .justify-content#{$infix}-around { justify-content: space-around !important; }\n\n .align-items#{$infix}-start { align-items: flex-start !important; }\n .align-items#{$infix}-end { align-items: flex-end !important; }\n .align-items#{$infix}-center { align-items: center !important; }\n .align-items#{$infix}-baseline { align-items: baseline !important; }\n .align-items#{$infix}-stretch { align-items: stretch !important; }\n\n .align-content#{$infix}-start { align-content: flex-start !important; }\n .align-content#{$infix}-end { align-content: flex-end !important; }\n .align-content#{$infix}-center { align-content: center !important; }\n .align-content#{$infix}-between { align-content: space-between !important; }\n .align-content#{$infix}-around { align-content: space-around !important; }\n .align-content#{$infix}-stretch { align-content: stretch !important; }\n\n .align-self#{$infix}-auto { align-self: auto !important; }\n .align-self#{$infix}-start { align-self: flex-start !important; }\n .align-self#{$infix}-end { align-self: flex-end !important; }\n .align-self#{$infix}-center { align-self: center !important; }\n .align-self#{$infix}-baseline { align-self: baseline !important; }\n .align-self#{$infix}-stretch { align-self: stretch !important; }\n }\n}\n","// stylelint-disable declaration-no-important\n\n// Margin and Padding\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n @each $prop, $abbrev in (margin: m, padding: p) {\n @each $size, $length in $spacers {\n .#{$abbrev}#{$infix}-#{$size} { #{$prop}: $length !important; }\n .#{$abbrev}t#{$infix}-#{$size},\n .#{$abbrev}y#{$infix}-#{$size} {\n #{$prop}-top: $length !important;\n }\n .#{$abbrev}r#{$infix}-#{$size},\n .#{$abbrev}x#{$infix}-#{$size} {\n #{$prop}-right: $length !important;\n }\n .#{$abbrev}b#{$infix}-#{$size},\n .#{$abbrev}y#{$infix}-#{$size} {\n #{$prop}-bottom: $length !important;\n }\n .#{$abbrev}l#{$infix}-#{$size},\n .#{$abbrev}x#{$infix}-#{$size} {\n #{$prop}-left: $length !important;\n }\n }\n }\n\n // Negative margins (e.g., where `.mb-n1` is negative version of `.mb-1`)\n @each $size, $length in $spacers {\n @if $size != 0 {\n .m#{$infix}-n#{$size} { margin: -$length !important; }\n .mt#{$infix}-n#{$size},\n .my#{$infix}-n#{$size} {\n margin-top: -$length !important;\n }\n .mr#{$infix}-n#{$size},\n .mx#{$infix}-n#{$size} {\n margin-right: -$length !important;\n }\n .mb#{$infix}-n#{$size},\n .my#{$infix}-n#{$size} {\n margin-bottom: -$length !important;\n }\n .ml#{$infix}-n#{$size},\n .mx#{$infix}-n#{$size} {\n margin-left: -$length !important;\n }\n }\n }\n\n // Some special margin utils\n .m#{$infix}-auto { margin: auto !important; }\n .mt#{$infix}-auto,\n .my#{$infix}-auto {\n margin-top: auto !important;\n }\n .mr#{$infix}-auto,\n .mx#{$infix}-auto {\n margin-right: auto !important;\n }\n .mb#{$infix}-auto,\n .my#{$infix}-auto {\n margin-bottom: auto !important;\n }\n .ml#{$infix}-auto,\n .mx#{$infix}-auto {\n margin-left: auto !important;\n }\n }\n}\n"]} \ No newline at end of file diff --git a/archive/SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css b/archive/SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css deleted file mode 100644 index 4c642187..00000000 --- a/archive/SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css +++ /dev/null @@ -1,326 +0,0 @@ -/*! - * Bootstrap Reboot v4.5.3 (https://getbootstrap.com/) - * Copyright 2011-2020 The Bootstrap Authors - * Copyright 2011-2020 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) - */ -*, -*::before, -*::after { - box-sizing: border-box; -} - -html { - font-family: sans-serif; - line-height: 1.15; - -webkit-text-size-adjust: 100%; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} - -article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { - display: block; -} - -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: #212529; - text-align: left; - background-color: #fff; -} - -[tabindex="-1"]:focus:not(:focus-visible) { - outline: 0 !important; -} - -hr { - box-sizing: content-box; - height: 0; - overflow: visible; -} - -h1, h2, h3, h4, h5, h6 { - margin-top: 0; - margin-bottom: 0.5rem; -} - -p { - margin-top: 0; - margin-bottom: 1rem; -} - -abbr[title], -abbr[data-original-title] { - text-decoration: underline; - -webkit-text-decoration: underline dotted; - text-decoration: underline dotted; - cursor: help; - border-bottom: 0; - -webkit-text-decoration-skip-ink: none; - text-decoration-skip-ink: none; -} - -address { - margin-bottom: 1rem; - font-style: normal; - line-height: inherit; -} - -ol, -ul, -dl { - margin-top: 0; - margin-bottom: 1rem; -} - -ol ol, -ul ul, -ol ul, -ul ol { - margin-bottom: 0; -} - -dt { - font-weight: 700; -} - -dd { - margin-bottom: .5rem; - margin-left: 0; -} - -blockquote { - margin: 0 0 1rem; -} - -b, -strong { - font-weight: bolder; -} - -small { - font-size: 80%; -} - -sub, -sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; -} - -sub { - bottom: -.25em; -} - -sup { - top: -.5em; -} - -a { - color: #007bff; - text-decoration: none; - background-color: transparent; -} - -a:hover { - color: #0056b3; - text-decoration: underline; -} - -a:not([href]):not([class]) { - color: inherit; - text-decoration: none; -} - -a:not([href]):not([class]):hover { - color: inherit; - text-decoration: none; -} - -pre, -code, -kbd, -samp { - font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; - font-size: 1em; -} - -pre { - margin-top: 0; - margin-bottom: 1rem; - overflow: auto; - -ms-overflow-style: scrollbar; -} - -figure { - margin: 0 0 1rem; -} - -img { - vertical-align: middle; - border-style: none; -} - -svg { - overflow: hidden; - vertical-align: middle; -} - -table { - border-collapse: collapse; -} - -caption { - padding-top: 0.75rem; - padding-bottom: 0.75rem; - color: #6c757d; - text-align: left; - caption-side: bottom; -} - -th { - text-align: inherit; - text-align: -webkit-match-parent; -} - -label { - display: inline-block; - margin-bottom: 0.5rem; -} - -button { - border-radius: 0; -} - -button:focus { - outline: 1px dotted; - outline: 5px auto -webkit-focus-ring-color; -} - -input, -button, -select, -optgroup, -textarea { - margin: 0; - font-family: inherit; - font-size: inherit; - line-height: inherit; -} - -button, -input { - overflow: visible; -} - -button, -select { - text-transform: none; -} - -[role="button"] { - cursor: pointer; -} - -select { - word-wrap: normal; -} - -button, -[type="button"], -[type="reset"], -[type="submit"] { - -webkit-appearance: button; -} - -button:not(:disabled), -[type="button"]:not(:disabled), -[type="reset"]:not(:disabled), -[type="submit"]:not(:disabled) { - cursor: pointer; -} - -button::-moz-focus-inner, -[type="button"]::-moz-focus-inner, -[type="reset"]::-moz-focus-inner, -[type="submit"]::-moz-focus-inner { - padding: 0; - border-style: none; -} - -input[type="radio"], -input[type="checkbox"] { - box-sizing: border-box; - padding: 0; -} - -textarea { - overflow: auto; - resize: vertical; -} - -fieldset { - min-width: 0; - padding: 0; - margin: 0; - border: 0; -} - -legend { - display: block; - width: 100%; - max-width: 100%; - padding: 0; - margin-bottom: .5rem; - font-size: 1.5rem; - line-height: inherit; - color: inherit; - white-space: normal; -} - -progress { - vertical-align: baseline; -} - -[type="number"]::-webkit-inner-spin-button, -[type="number"]::-webkit-outer-spin-button { - height: auto; -} - -[type="search"] { - outline-offset: -2px; - -webkit-appearance: none; -} - -[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} - -::-webkit-file-upload-button { - font: inherit; - -webkit-appearance: button; -} - -output { - display: inline-block; -} - -summary { - display: list-item; - cursor: pointer; -} - -template { - display: none; -} - -[hidden] { - display: none !important; -} -/*# sourceMappingURL=bootstrap-reboot.css.map */ \ No newline at end of file diff --git a/archive/SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map b/archive/SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map deleted file mode 100644 index e79cab0c..00000000 --- a/archive/SecurityService/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["../../scss/bootstrap-reboot.scss","bootstrap-reboot.css","../../scss/_reboot.scss","../../scss/_variables.scss","../../scss/vendor/_rfs.scss","../../scss/mixins/_hover.scss"],"names":[],"mappings":"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","file":"bootstrap-reboot.css","sourcesContent":["/*!\n * Bootstrap Reboot v4.5.3 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors\n * Copyright 2011-2020 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n\n@import \"functions\";\n@import \"variables\";\n@import \"mixins\";\n@import \"reboot\";\n","/*!\n * Bootstrap Reboot v4.5.3 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors\n * Copyright 2011-2020 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus:not(:focus-visible) {\n outline: 0 !important;\n}\n\nhr {\n box-sizing: content-box;\n height: 0;\n overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n text-decoration: underline;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0;\n text-decoration-skip-ink: none;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 80%;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -.25em;\n}\n\nsup {\n top: -.5em;\n}\n\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n}\n\na:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\na:not([href]):not([class]) {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([class]):hover {\n color: inherit;\n text-decoration: none;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n}\n\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n -ms-overflow-style: scrollbar;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg {\n vertical-align: middle;\n border-style: none;\n}\n\nsvg {\n overflow: hidden;\n vertical-align: middle;\n}\n\ntable {\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n text-align: inherit;\n text-align: -webkit-match-parent;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 0.5rem;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\n[role=\"button\"] {\n cursor: pointer;\n}\n\nselect {\n word-wrap: normal;\n}\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\nbutton:not(:disabled),\n[type=\"button\"]:not(:disabled),\n[type=\"reset\"]:not(:disabled),\n[type=\"submit\"]:not(:disabled) {\n cursor: pointer;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box;\n padding: 0;\n}\n\ntextarea {\n overflow: auto;\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n max-width: 100%;\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit;\n white-space: normal;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n outline-offset: -2px;\n -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\ntemplate {\n display: none;\n}\n\n[hidden] {\n display: none !important;\n}\n\n/*# sourceMappingURL=bootstrap-reboot.css.map */","// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n// 2. Change the default font family in all browsers.\n// 3. Correct the line height in all browsers.\n// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.\n// 5. Change the default tap highlight to be completely transparent in iOS.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box; // 1\n}\n\nhtml {\n font-family: sans-serif; // 2\n line-height: 1.15; // 3\n -webkit-text-size-adjust: 100%; // 4\n -webkit-tap-highlight-color: rgba($black, 0); // 5\n}\n\n// Shim for \"new\" HTML5 structural elements to display correctly (IE10, older browsers)\n// TODO: remove in v5\n// stylelint-disable-next-line selector-list-comma-newline-after\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Set an explicit initial text-align value so that we can later use\n// the `inherit` value on things like `` elements.\n\nbody {\n margin: 0; // 1\n font-family: $font-family-base;\n @include font-size($font-size-base);\n font-weight: $font-weight-base;\n line-height: $line-height-base;\n color: $body-color;\n text-align: left; // 3\n background-color: $body-bg; // 2\n}\n\n// Future-proof rule: in browsers that support :focus-visible, suppress the focus outline\n// on elements that programmatically receive focus but wouldn't normally show a visible\n// focus outline. In general, this would mean that the outline is only applied if the\n// interaction that led to the element receiving programmatic focus was a keyboard interaction,\n// or the browser has somehow determined that the user is primarily a keyboard user and/or\n// wants focus outlines to always be presented.\n//\n// See https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible\n// and https://developer.paciellogroup.com/blog/2018/03/focus-visible-and-backwards-compatibility/\n[tabindex=\"-1\"]:focus:not(:focus-visible) {\n outline: 0 !important;\n}\n\n\n// Content grouping\n//\n// 1. Add the correct box sizing in Firefox.\n// 2. Show the overflow in Edge and IE.\n\nhr {\n box-sizing: content-box; // 1\n height: 0; // 1\n overflow: visible; // 2\n}\n\n\n//\n// Typography\n//\n\n// Remove top margins from headings\n//\n// By default, `

    `-`

    ` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n// stylelint-disable-next-line selector-list-comma-newline-after\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: $headings-margin-bottom;\n}\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on `

    `s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n// Abbreviations\n//\n// 1. Duplicate behavior to the data-* attribute for our tooltip plugin\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Remove the bottom border in Firefox 39-.\n// 5. Prevent the text-decoration to be skipped.\n\nabbr[title],\nabbr[data-original-title] { // 1\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n border-bottom: 0; // 4\n text-decoration-skip-ink: none; // 5\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // Undo browser default\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: $font-weight-bolder; // Add the correct font weight in Chrome, Edge, and Safari\n}\n\nsmall {\n @include font-size(80%); // Add the correct font size in all browsers\n}\n\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n//\n\nsub,\nsup {\n position: relative;\n @include font-size(75%);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n//\n// Links\n//\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n background-color: transparent; // Remove the gray background on active links in IE 10.\n\n @include hover() {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([class]) {\n color: inherit;\n text-decoration: none;\n\n @include hover() {\n color: inherit;\n text-decoration: none;\n }\n}\n\n\n//\n// Code\n//\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-monospace;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n}\n\npre {\n // Remove browser default top margin\n margin-top: 0;\n // Reset browser default of `1em` to use `rem`s\n margin-bottom: 1rem;\n // Don't allow content to break outside\n overflow: auto;\n // Disable auto-hiding scrollbar in IE & legacy Edge to avoid overlap,\n // making it impossible to interact with the content\n -ms-overflow-style: scrollbar;\n}\n\n\n//\n// Figures\n//\n\nfigure {\n // Apply a consistent margin strategy (matches our type styles).\n margin: 0 0 1rem;\n}\n\n\n//\n// Images and content\n//\n\nimg {\n vertical-align: middle;\n border-style: none; // Remove the border on images inside links in IE 10-.\n}\n\nsvg {\n // Workaround for the SVG overflow bug in IE10/11 is still required.\n // See https://github.com/twbs/bootstrap/issues/26878\n overflow: hidden;\n vertical-align: middle;\n}\n\n\n//\n// Tables\n//\n\ntable {\n border-collapse: collapse; // Prevent double borders\n}\n\ncaption {\n padding-top: $table-cell-padding;\n padding-bottom: $table-cell-padding;\n color: $table-caption-color;\n text-align: left;\n caption-side: bottom;\n}\n\n// 1. Removes font-weight bold by inheriting\n// 2. Matches default `` alignment by inheriting `text-align`.\n// 3. Fix alignment for Safari\n\nth {\n font-weight: $table-th-font-weight; // 1\n text-align: inherit; // 2\n text-align: -webkit-match-parent; // 3\n}\n\n\n//\n// Forms\n//\n\nlabel {\n // Allow labels to use `margin` for spacing.\n display: inline-block;\n margin-bottom: $label-margin-bottom;\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24093\nbutton {\n // stylelint-disable-next-line property-disallowed-list\n border-radius: 0;\n}\n\n// Work around a Firefox/IE bug where the transparent `button` background\n// results in a loss of the default `button` focus styles.\n//\n// Credit: https://github.com/suitcss/base/\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // Remove the margin in Firefox and Safari\n font-family: inherit;\n @include font-size(inherit);\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible; // Show the overflow in Edge\n}\n\nbutton,\nselect {\n text-transform: none; // Remove the inheritance of text transform in Firefox\n}\n\n// Set the cursor for non-`

    ',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:Qt,popperConfig:null},Zt={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"},te=function(){function t(t,e){if("undefined"==typeof It)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var e=t.prototype;return e.enable=function(){this._isEnabled=!0},e.disable=function(){this._isEnabled=!1},e.toggleEnabled=function(){this._isEnabled=!this._isEnabled},e.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=i.default(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),i.default(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(i.default(this.getTipElement()).hasClass("show"))return void this._leave(null,this);this._enter(null,this)}},e.dispose=function(){clearTimeout(this._timeout),i.default.removeData(this.element,this.constructor.DATA_KEY),i.default(this.element).off(this.constructor.EVENT_KEY),i.default(this.element).closest(".modal").off("hide.bs.modal",this._hideModalHandler),this.tip&&i.default(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},e.show=function(){var t=this;if("none"===i.default(this.element).css("display"))throw new Error("Please use show on visible elements");var e=i.default.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){i.default(this.element).trigger(e);var n=l.findShadowRoot(this.element),o=i.default.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(e.isDefaultPrevented()||!o)return;var r=this.getTipElement(),a=l.getUID(this.constructor.NAME);r.setAttribute("id",a),this.element.setAttribute("aria-describedby",a),this.setContent(),this.config.animation&&i.default(r).addClass("fade");var s="function"==typeof this.config.placement?this.config.placement.call(this,r,this.element):this.config.placement,u=this._getAttachment(s);this.addAttachmentClass(u);var f=this._getContainer();i.default(r).data(this.constructor.DATA_KEY,this),i.default.contains(this.element.ownerDocument.documentElement,this.tip)||i.default(r).appendTo(f),i.default(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new It(this.element,r,this._getPopperConfig(u)),i.default(r).addClass("show"),"ontouchstart"in document.documentElement&&i.default(document.body).children().on("mouseover",null,i.default.noop);var d=function(){t.config.animation&&t._fixTransition();var e=t._hoverState;t._hoverState=null,i.default(t.element).trigger(t.constructor.Event.SHOWN),"out"===e&&t._leave(null,t)};if(i.default(this.tip).hasClass("fade")){var c=l.getTransitionDurationFromElement(this.tip);i.default(this.tip).one(l.TRANSITION_END,d).emulateTransitionEnd(c)}else d()}},e.hide=function(t){var e=this,n=this.getTipElement(),o=i.default.Event(this.constructor.Event.HIDE),r=function(){"show"!==e._hoverState&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),i.default(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(i.default(this.element).trigger(o),!o.isDefaultPrevented()){if(i.default(n).removeClass("show"),"ontouchstart"in document.documentElement&&i.default(document.body).children().off("mouseover",null,i.default.noop),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,i.default(this.tip).hasClass("fade")){var a=l.getTransitionDurationFromElement(n);i.default(n).one(l.TRANSITION_END,r).emulateTransitionEnd(a)}else r();this._hoverState=""}},e.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},e.isWithContent=function(){return Boolean(this.getTitle())},e.addAttachmentClass=function(t){i.default(this.getTipElement()).addClass("bs-tooltip-"+t)},e.getTipElement=function(){return this.tip=this.tip||i.default(this.config.template)[0],this.tip},e.setContent=function(){var t=this.getTipElement();this.setElementContent(i.default(t.querySelectorAll(".tooltip-inner")),this.getTitle()),i.default(t).removeClass("fade show")},e.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=Vt(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?i.default(e).parent().is(t)||t.empty().append(e):t.text(i.default(e).text())},e.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},e._getPopperConfig=function(t){var e=this;return a({},{placement:t,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:".arrow"},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}},this.config.popperConfig)},e._getOffset=function(){var t=this,e={};return"function"==typeof this.config.offset?e.fn=function(e){return e.offsets=a({},e.offsets,t.config.offset(e.offsets,t.element)||{}),e}:e.offset=this.config.offset,e},e._getContainer=function(){return!1===this.config.container?document.body:l.isElement(this.config.container)?i.default(this.config.container):i.default(document).find(this.config.container)},e._getAttachment=function(t){return $t[t.toUpperCase()]},e._setListeners=function(){var t=this;this.config.trigger.split(" ").forEach((function(e){if("click"===e)i.default(t.element).on(t.constructor.Event.CLICK,t.config.selector,(function(e){return t.toggle(e)}));else if("manual"!==e){var n="hover"===e?t.constructor.Event.MOUSEENTER:t.constructor.Event.FOCUSIN,o="hover"===e?t.constructor.Event.MOUSELEAVE:t.constructor.Event.FOCUSOUT;i.default(t.element).on(n,t.config.selector,(function(e){return t._enter(e)})).on(o,t.config.selector,(function(e){return t._leave(e)}))}})),this._hideModalHandler=function(){t.element&&t.hide()},i.default(this.element).closest(".modal").on("hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=a({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},e._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},e._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||i.default(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),i.default(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?"focus":"hover"]=!0),i.default(e.getTipElement()).hasClass("show")||"show"===e._hoverState?e._hoverState="show":(clearTimeout(e._timeout),e._hoverState="show",e.config.delay&&e.config.delay.show?e._timeout=setTimeout((function(){"show"===e._hoverState&&e.show()}),e.config.delay.show):e.show())},e._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||i.default(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),i.default(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?"focus":"hover"]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState="out",e.config.delay&&e.config.delay.hide?e._timeout=setTimeout((function(){"out"===e._hoverState&&e.hide()}),e.config.delay.hide):e.hide())},e._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},e._getConfig=function(t){var e=i.default(this.element).data();return Object.keys(e).forEach((function(t){-1!==Kt.indexOf(t)&&delete e[t]})),"number"==typeof(t=a({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),l.typeCheckConfig(Yt,t,this.constructor.DefaultType),t.sanitize&&(t.template=Vt(t.template,t.whiteList,t.sanitizeFn)),t},e._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},e._cleanTipClass=function(){var t=i.default(this.getTipElement()),e=t.attr("class").match(Xt);null!==e&&e.length&&t.removeClass(e.join(""))},e._handlePopperPlacementChange=function(t){this.tip=t.instance.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},e._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(i.default(t).removeClass("fade"),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},t._jQueryInterface=function(e){return this.each((function(){var n=i.default(this),o=n.data("bs.tooltip"),r="object"==typeof e&&e;if((o||!/dispose|hide/.test(e))&&(o||(o=new t(this,r),n.data("bs.tooltip",o)),"string"==typeof e)){if("undefined"==typeof o[e])throw new TypeError('No method named "'+e+'"');o[e]()}}))},r(t,null,[{key:"VERSION",get:function(){return"4.5.3"}},{key:"Default",get:function(){return Jt}},{key:"NAME",get:function(){return Yt}},{key:"DATA_KEY",get:function(){return"bs.tooltip"}},{key:"Event",get:function(){return Zt}},{key:"EVENT_KEY",get:function(){return".bs.tooltip"}},{key:"DefaultType",get:function(){return Gt}}]),t}();i.default.fn[Yt]=te._jQueryInterface,i.default.fn[Yt].Constructor=te,i.default.fn[Yt].noConflict=function(){return i.default.fn[Yt]=zt,te._jQueryInterface};var ee="popover",ne=i.default.fn[ee],ie=new RegExp("(^|\\s)bs-popover\\S+","g"),oe=a({},te.Default,{placement:"right",trigger:"click",content:"",template:''}),re=a({},te.DefaultType,{content:"(string|element|function)"}),ae={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"},se=function(t){var e,n;function o(){return t.apply(this,arguments)||this}n=t,(e=o).prototype=Object.create(n.prototype),e.prototype.constructor=e,e.__proto__=n;var a=o.prototype;return a.isWithContent=function(){return this.getTitle()||this._getContent()},a.addAttachmentClass=function(t){i.default(this.getTipElement()).addClass("bs-popover-"+t)},a.getTipElement=function(){return this.tip=this.tip||i.default(this.config.template)[0],this.tip},a.setContent=function(){var t=i.default(this.getTipElement());this.setElementContent(t.find(".popover-header"),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(".popover-body"),e),t.removeClass("fade show")},a._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},a._cleanTipClass=function(){var t=i.default(this.getTipElement()),e=t.attr("class").match(ie);null!==e&&e.length>0&&t.removeClass(e.join(""))},o._jQueryInterface=function(t){return this.each((function(){var e=i.default(this).data("bs.popover"),n="object"==typeof t?t:null;if((e||!/dispose|hide/.test(t))&&(e||(e=new o(this,n),i.default(this).data("bs.popover",e)),"string"==typeof t)){if("undefined"==typeof e[t])throw new TypeError('No method named "'+t+'"');e[t]()}}))},r(o,null,[{key:"VERSION",get:function(){return"4.5.3"}},{key:"Default",get:function(){return oe}},{key:"NAME",get:function(){return ee}},{key:"DATA_KEY",get:function(){return"bs.popover"}},{key:"Event",get:function(){return ae}},{key:"EVENT_KEY",get:function(){return".bs.popover"}},{key:"DefaultType",get:function(){return re}}]),o}(te);i.default.fn[ee]=se._jQueryInterface,i.default.fn[ee].Constructor=se,i.default.fn[ee].noConflict=function(){return i.default.fn[ee]=ne,se._jQueryInterface};var le="scrollspy",ue=i.default.fn[le],fe={offset:10,method:"auto",target:""},de={offset:"number",method:"string",target:"(string|element)"},ce=function(){function t(t,e){var n=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(e),this._selector=this._config.target+" .nav-link,"+this._config.target+" .list-group-item,"+this._config.target+" .dropdown-item",this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,i.default(this._scrollElement).on("scroll.bs.scrollspy",(function(t){return n._process(t)})),this.refresh(),this._process()}var e=t.prototype;return e.refresh=function(){var t=this,e=this._scrollElement===this._scrollElement.window?"offset":"position",n="auto"===this._config.method?e:this._config.method,o="position"===n?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map((function(t){var e,r=l.getSelectorFromElement(t);if(r&&(e=document.querySelector(r)),e){var a=e.getBoundingClientRect();if(a.width||a.height)return[i.default(e)[n]().top+o,r]}return null})).filter((function(t){return t})).sort((function(t,e){return t[0]-e[0]})).forEach((function(e){t._offsets.push(e[0]),t._targets.push(e[1])}))},e.dispose=function(){i.default.removeData(this._element,"bs.scrollspy"),i.default(this._scrollElement).off(".bs.scrollspy"),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},e._getConfig=function(t){if("string"!=typeof(t=a({},fe,"object"==typeof t&&t?t:{})).target&&l.isElement(t.target)){var e=i.default(t.target).attr("id");e||(e=l.getUID(le),i.default(t.target).attr("id",e)),t.target="#"+e}return l.typeCheckConfig(le,t,de),t},e._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},e._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},e._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},e._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=n){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t0)return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;){this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t li > .active":".active";n=(n=i.default.makeArray(i.default(o).find(a)))[n.length-1]}var s=i.default.Event("hide.bs.tab",{relatedTarget:this._element}),u=i.default.Event("show.bs.tab",{relatedTarget:n});if(n&&i.default(n).trigger(s),i.default(this._element).trigger(u),!u.isDefaultPrevented()&&!s.isDefaultPrevented()){r&&(e=document.querySelector(r)),this._activate(this._element,o);var f=function(){var e=i.default.Event("hidden.bs.tab",{relatedTarget:t._element}),o=i.default.Event("shown.bs.tab",{relatedTarget:n});i.default(n).trigger(e),i.default(t._element).trigger(o)};e?this._activate(e,e.parentNode,f):f()}}},e.dispose=function(){i.default.removeData(this._element,"bs.tab"),this._element=null},e._activate=function(t,e,n){var o=this,r=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?i.default(e).children(".active"):i.default(e).find("> li > .active"))[0],a=n&&r&&i.default(r).hasClass("fade"),s=function(){return o._transitionComplete(t,r,n)};if(r&&a){var u=l.getTransitionDurationFromElement(r);i.default(r).removeClass("show").one(l.TRANSITION_END,s).emulateTransitionEnd(u)}else s()},e._transitionComplete=function(t,e,n){if(e){i.default(e).removeClass("active");var o=i.default(e.parentNode).find("> .dropdown-menu .active")[0];o&&i.default(o).removeClass("active"),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}if(i.default(t).addClass("active"),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),l.reflow(t),t.classList.contains("fade")&&t.classList.add("show"),t.parentNode&&i.default(t.parentNode).hasClass("dropdown-menu")){var r=i.default(t).closest(".dropdown")[0];if(r){var a=[].slice.call(r.querySelectorAll(".dropdown-toggle"));i.default(a).addClass("active")}t.setAttribute("aria-expanded",!0)}n&&n()},t._jQueryInterface=function(e){return this.each((function(){var n=i.default(this),o=n.data("bs.tab");if(o||(o=new t(this),n.data("bs.tab",o)),"string"==typeof e){if("undefined"==typeof o[e])throw new TypeError('No method named "'+e+'"');o[e]()}}))},r(t,null,[{key:"VERSION",get:function(){return"4.5.3"}}]),t}();i.default(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',(function(t){t.preventDefault(),pe._jQueryInterface.call(i.default(this),"show")})),i.default.fn.tab=pe._jQueryInterface,i.default.fn.tab.Constructor=pe,i.default.fn.tab.noConflict=function(){return i.default.fn.tab=he,pe._jQueryInterface};var me=i.default.fn.toast,ge={animation:"boolean",autohide:"boolean",delay:"number"},ve={animation:!0,autohide:!0,delay:500},_e=function(){function t(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var e=t.prototype;return e.show=function(){var t=this,e=i.default.Event("show.bs.toast");if(i.default(this._element).trigger(e),!e.isDefaultPrevented()){this._clearTimeout(),this._config.animation&&this._element.classList.add("fade");var n=function(){t._element.classList.remove("showing"),t._element.classList.add("show"),i.default(t._element).trigger("shown.bs.toast"),t._config.autohide&&(t._timeout=setTimeout((function(){t.hide()}),t._config.delay))};if(this._element.classList.remove("hide"),l.reflow(this._element),this._element.classList.add("showing"),this._config.animation){var o=l.getTransitionDurationFromElement(this._element);i.default(this._element).one(l.TRANSITION_END,n).emulateTransitionEnd(o)}else n()}},e.hide=function(){if(this._element.classList.contains("show")){var t=i.default.Event("hide.bs.toast");i.default(this._element).trigger(t),t.isDefaultPrevented()||this._close()}},e.dispose=function(){this._clearTimeout(),this._element.classList.contains("show")&&this._element.classList.remove("show"),i.default(this._element).off("click.dismiss.bs.toast"),i.default.removeData(this._element,"bs.toast"),this._element=null,this._config=null},e._getConfig=function(t){return t=a({},ve,i.default(this._element).data(),"object"==typeof t&&t?t:{}),l.typeCheckConfig("toast",t,this.constructor.DefaultType),t},e._setListeners=function(){var t=this;i.default(this._element).on("click.dismiss.bs.toast",'[data-dismiss="toast"]',(function(){return t.hide()}))},e._close=function(){var t=this,e=function(){t._element.classList.add("hide"),i.default(t._element).trigger("hidden.bs.toast")};if(this._element.classList.remove("show"),this._config.animation){var n=l.getTransitionDurationFromElement(this._element);i.default(this._element).one(l.TRANSITION_END,e).emulateTransitionEnd(n)}else e()},e._clearTimeout=function(){clearTimeout(this._timeout),this._timeout=null},t._jQueryInterface=function(e){return this.each((function(){var n=i.default(this),o=n.data("bs.toast");if(o||(o=new t(this,"object"==typeof e&&e),n.data("bs.toast",o)),"string"==typeof e){if("undefined"==typeof o[e])throw new TypeError('No method named "'+e+'"');o[e](this)}}))},r(t,null,[{key:"VERSION",get:function(){return"4.5.3"}},{key:"DefaultType",get:function(){return ge}},{key:"Default",get:function(){return ve}}]),t}();i.default.fn.toast=_e._jQueryInterface,i.default.fn.toast.Constructor=_e,i.default.fn.toast.noConflict=function(){return i.default.fn.toast=me,_e._jQueryInterface},t.Alert=d,t.Button=h,t.Carousel=y,t.Collapse=S,t.Dropdown=Ft,t.Modal=Bt,t.Popover=se,t.Scrollspy=ce,t.Tab=pe,t.Toast=_e,t.Tooltip=te,t.Util=l,Object.defineProperty(t,"__esModule",{value:!0})})); -//# sourceMappingURL=bootstrap.bundle.min.js.map \ No newline at end of file diff --git a/archive/SecurityService/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map b/archive/SecurityService/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map deleted file mode 100644 index 4146d43c..00000000 --- a/archive/SecurityService/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["../../js/src/util.js","../../js/src/alert.js","../../js/src/button.js","../../js/src/carousel.js","../../js/src/collapse.js","../../node_modules/popper.js/dist/esm/popper.js","../../js/src/dropdown.js","../../js/src/modal.js","../../js/src/tools/sanitizer.js","../../js/src/tooltip.js","../../js/src/popover.js","../../js/src/scrollspy.js","../../js/src/tab.js","../../js/src/toast.js"],"names":["transitionEndEmulator","duration","_this","this","called","$","one","Util","TRANSITION_END","setTimeout","triggerTransitionEnd","getUID","prefix","Math","random","document","getElementById","getSelectorFromElement","element","selector","getAttribute","hrefAttr","trim","querySelector","_","getTransitionDurationFromElement","transitionDuration","css","transitionDelay","floatTransitionDuration","parseFloat","floatTransitionDelay","split","reflow","offsetHeight","trigger","supportsTransitionEnd","Boolean","isElement","obj","nodeType","typeCheckConfig","componentName","config","configTypes","property","Object","prototype","hasOwnProperty","call","expectedTypes","value","valueType","toString","match","toLowerCase","RegExp","test","Error","toUpperCase","findShadowRoot","documentElement","attachShadow","getRootNode","root","ShadowRoot","parentNode","jQueryDetection","TypeError","version","fn","jquery","emulateTransitionEnd","event","special","bindType","delegateType","handle","target","is","handleObj","handler","apply","arguments","NAME","JQUERY_NO_CONFLICT","Alert","_element","close","rootElement","_getRootElement","_triggerCloseEvent","isDefaultPrevented","_removeElement","dispose","removeData","parent","closest","closeEvent","Event","removeClass","hasClass","_destroyElement","detach","remove","_jQueryInterface","each","$element","data","_handleDismiss","alertInstance","preventDefault","on","Constructor","noConflict","Button","shouldAvoidTriggerChange","toggle","triggerChangeEvent","addAriaPressed","input","type","checked","classList","contains","activeElement","focus","hasAttribute","setAttribute","toggleClass","avoidTriggerChange","button","initialButton","inputBtn","tagName","window","buttons","slice","querySelectorAll","i","len","length","add","EVENT_KEY","Default","interval","keyboard","slide","pause","wrap","touch","DefaultType","PointerType","TOUCH","PEN","Carousel","_items","_interval","_activeElement","_isPaused","_isSliding","touchTimeout","touchStartX","touchDeltaX","_config","_getConfig","_indicatorsElement","_touchSupported","navigator","maxTouchPoints","_pointerEvent","PointerEvent","MSPointerEvent","_addEventListeners","next","_slide","nextWhenVisible","hidden","prev","cycle","clearInterval","setInterval","visibilityState","bind","to","index","activeIndex","_getItemIndex","direction","off","_extends","_handleSwipe","absDeltax","abs","_this2","_keydown","_addTouchEventListeners","_this3","start","originalEvent","pointerType","clientX","touches","end","clearTimeout","e","move","which","indexOf","_getItemByDirection","isNextDirection","isPrevDirection","lastItemIndex","itemIndex","_triggerSlideEvent","relatedTarget","eventDirectionName","targetIndex","fromIndex","slideEvent","from","_setActiveIndicatorElement","indicators","nextIndicator","children","addClass","directionalClassName","orderClassName","_this4","activeElementIndex","nextElement","nextElementIndex","isCycling","slidEvent","nextElementInterval","parseInt","defaultInterval","CLASS_NAME_ACTIVE","action","ride","_dataApiClickHandler","slideIndex","carousels","$carousel","Collapse","_isTransitioning","_triggerArray","id","toggleList","elem","filterElement","filter","foundElem","_selector","push","_parent","_getParent","_addAriaAndCollapsedClass","hide","show","actives","activesData","not","startEvent","dimension","_getDimension","style","attr","setTransitioning","scrollSize","CLASS_NAME_COLLAPSE","getBoundingClientRect","triggerArrayLength","isTransitioning","_getTargetFromElement","triggerArray","isOpen","currentTarget","$trigger","selectors","$target","isBrowser","timeoutDuration","longerTimeoutBrowsers","userAgent","debounce","Promise","resolve","then","scheduled","isFunction","functionToCheck","getStyleComputedProperty","ownerDocument","defaultView","getComputedStyle","getParentNode","nodeName","host","getScrollParent","body","_getStyleComputedProp","overflow","overflowX","overflowY","getReferenceNode","reference","referenceNode","isIE11","MSInputMethodContext","documentMode","isIE10","isIE","getOffsetParent","noOffsetParent","offsetParent","nextElementSibling","getRoot","node","findCommonOffsetParent","element1","element2","order","compareDocumentPosition","Node","DOCUMENT_POSITION_FOLLOWING","range","createRange","setStart","setEnd","commonAncestorContainer","firstElementChild","element1root","getScroll","side","undefined","upperSide","html","scrollingElement","includeScroll","rect","subtract","scrollTop","scrollLeft","modifier","top","bottom","left","right","getBordersSize","styles","axis","sideA","sideB","getSize","computedStyle","max","getWindowSizes","height","width","classCallCheck","instance","createClass","defineProperties","props","descriptor","enumerable","configurable","writable","defineProperty","key","protoProps","staticProps","assign","source","getClientRect","offsets","result","sizes","clientWidth","clientHeight","horizScrollbar","offsetWidth","vertScrollbar","getOffsetRectRelativeToArbitraryNode","fixedPosition","isHTML","childrenRect","parentRect","scrollParent","borderTopWidth","borderLeftWidth","marginTop","marginLeft","getViewportOffsetRectRelativeToArtbitraryNode","excludeScroll","relativeOffset","innerWidth","innerHeight","offset","isFixed","getFixedPositionOffsetParent","parentElement","el","getBoundaries","popper","padding","boundariesElement","boundaries","boundariesNode","_getWindowSizes","isPaddingNumber","getArea","_ref","computeAutoPlacement","placement","refRect","rects","sortedAreas","keys","map","area","sort","a","b","filteredAreas","_ref2","computedPlacement","variation","getReferenceOffsets","state","commonOffsetParent","getOuterSizes","x","marginBottom","y","marginRight","getOppositePlacement","hash","replace","matched","getPopperOffsets","referenceOffsets","popperRect","popperOffsets","isHoriz","mainSide","secondarySide","measurement","secondaryMeasurement","find","arr","check","Array","runModifiers","modifiers","ends","prop","findIndex","cur","forEach","console","warn","enabled","update","isDestroyed","arrowStyles","attributes","flipped","options","positionFixed","flip","originalPlacement","position","isCreated","onUpdate","onCreate","isModifierEnabled","modifierName","some","name","getSupportedPropertyName","prefixes","upperProp","charAt","toCheck","destroy","removeAttribute","willChange","disableEventListeners","removeOnDestroy","removeChild","getWindow","setupEventListeners","updateBound","addEventListener","passive","scrollElement","attachToScrollParents","callback","scrollParents","isBody","eventsEnabled","enableEventListeners","scheduleUpdate","cancelAnimationFrame","removeEventListener","isNumeric","n","isNaN","isFinite","setStyles","unit","isFirefox","isModifierRequired","requestingName","requestedName","requesting","isRequired","_requesting","requested","placements","validPlacements","clockwise","counter","concat","reverse","BEHAVIORS","parseOffset","basePlacement","useHeight","fragments","frag","divider","search","splitRegex","ops","op","mergeWithPrevious","reduce","str","toValue","index2","Defaults","shift","shiftvariation","_data$offsets","isVertical","shiftOffsets","preventOverflow","transformProp","popperStyles","transform","priority","primary","escapeWithReference","secondary","min","keepTogether","floor","opSide","arrow","_data$offsets$arrow","arrowElement","sideCapitalized","altSide","arrowElementSize","center","popperMarginSide","popperBorderSide","sideValue","round","placementOpposite","flipOrder","behavior","step","refOffsets","overlapsRef","overflowsLeft","overflowsRight","overflowsTop","overflowsBottom","overflowsBoundaries","flippedVariationByRef","flipVariations","flippedVariationByContent","flipVariationsByContent","flippedVariation","getOppositeVariation","inner","subtractLength","bound","computeStyle","legacyGpuAccelerationOption","gpuAcceleration","offsetParentRect","shouldRound","noRound","v","referenceWidth","popperWidth","isVariation","horizontalToInteger","verticalToInteger","getRoundedOffsets","devicePixelRatio","prefixedProperty","invertTop","invertLeft","x-placement","applyStyle","onLoad","modifierOptions","Popper","requestAnimationFrame","Utils","global","PopperUtils","REGEXP_KEYDOWN","ARROW_UP_KEYCODE","boundary","display","popperConfig","Dropdown","_popper","_menu","_getMenuElement","_inNavbar","_detectNavbar","disabled","isActive","_clearMenus","usePopper","showEvent","_getParentFromElement","referenceElement","_getPopperConfig","noop","hideEvent","stopPropagation","constructor","_getPlacement","$parentDropdown","_getOffset","toggles","context","clickEvent","dropdownMenu","_dataApiKeydownHandler","items","item","EVENT_CLICK_DATA_API","backdrop","Modal","_dialog","_backdrop","_isShown","_isBodyOverflowing","_ignoreBackdropClick","_scrollbarWidth","_checkScrollbar","_setScrollbar","_adjustDialog","_setEscapeEvent","_setResizeEvent","_showBackdrop","_showElement","transition","_hideModal","htmlElement","handleUpdate","_triggerBackdropTransition","hideEventPrevented","isModalOverflowing","scrollHeight","modalTransitionDuration","modalBody","ELEMENT_NODE","appendChild","_enforceFocus","shownEvent","transitionComplete","_this5","has","_this6","_this7","_this8","_resetAdjustments","_resetScrollbar","_removeBackdrop","_this9","animate","createElement","className","appendTo","backdropTransitionDuration","callbackRemove","paddingLeft","paddingRight","_getScrollbarWidth","_this10","fixedContent","stickyContent","actualPadding","calculatedPadding","actualMargin","calculatedMargin","elements","margin","scrollDiv","scrollbarWidth","_this11","uriAttrs","DefaultWhitelist","*","br","col","code","div","em","hr","h1","h2","h3","h4","h5","h6","img","li","ol","p","pre","s","small","span","sub","sup","strong","u","ul","SAFE_URL_PATTERN","DATA_URL_PATTERN","sanitizeHtml","unsafeHtml","whiteList","sanitizeFn","createdDocument","DOMParser","parseFromString","whitelistKeys","_loop","elName","attributeList","whitelistedAttributes","allowedAttributeList","attrName","nodeValue","regExp","attrRegex","allowedAttribute","innerHTML","BSCLS_PREFIX_REGEX","DISALLOWED_ATTRIBUTES","animation","template","title","delay","container","fallbackPlacement","sanitize","AttachmentMap","AUTO","TOP","RIGHT","BOTTOM","LEFT","HIDE","HIDDEN","SHOW","SHOWN","INSERTED","CLICK","FOCUSIN","FOCUSOUT","MOUSEENTER","MOUSELEAVE","Tooltip","_isEnabled","_timeout","_hoverState","_activeTrigger","tip","_setListeners","enable","disable","toggleEnabled","dataKey","DATA_KEY","_getDelegateConfig","click","_isWithActiveTrigger","_enter","_leave","getTipElement","_hideModalHandler","isWithContent","shadowRoot","isInTheDom","tipId","setContent","attachment","_getAttachment","addAttachmentClass","_getContainer","complete","_fixTransition","prevHoverState","_cleanTipClass","getTitle","CLASS_PREFIX","setElementContent","CLASS_NAME_FADE","content","text","empty","append","_handlePopperPlacementChange","eventIn","eventOut","_fixTitle","titleType","dataAttributes","dataAttr","$tip","tabClass","join","popperData","initConfigAnimation","Popover","_getContent","method","ScrollSpy","_scrollElement","_offsets","_targets","_activeTarget","_scrollHeight","_process","refresh","autoMethod","offsetMethod","offsetBase","_getScrollTop","_getScrollHeight","targetSelector","targetBCR","pageYOffset","_getOffsetHeight","maxScroll","_activate","_clear","queries","$link","parents","SELECTOR_NAV_LINKS","scrollSpys","$spy","Tab","previous","listElement","itemSelector","makeArray","hiddenEvent","active","_transitionComplete","dropdownChild","dropdownElement","dropdownToggleList","$this","autohide","Toast","_clearTimeout","_close"],"mappings":"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","sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.5.3): util.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\n\n/**\n * ------------------------------------------------------------------------\n * Private TransitionEnd Helpers\n * ------------------------------------------------------------------------\n */\n\nconst TRANSITION_END = 'transitionend'\nconst MAX_UID = 1000000\nconst MILLISECONDS_MULTIPLIER = 1000\n\n// Shoutout AngusCroll (https://goo.gl/pxwQGp)\nfunction toType(obj) {\n if (obj === null || typeof obj === 'undefined') {\n return `${obj}`\n }\n\n return {}.toString.call(obj).match(/\\s([a-z]+)/i)[1].toLowerCase()\n}\n\nfunction getSpecialTransitionEndEvent() {\n return {\n bindType: TRANSITION_END,\n delegateType: TRANSITION_END,\n handle(event) {\n if ($(event.target).is(this)) {\n return event.handleObj.handler.apply(this, arguments) // eslint-disable-line prefer-rest-params\n }\n\n return undefined\n }\n }\n}\n\nfunction transitionEndEmulator(duration) {\n let called = false\n\n $(this).one(Util.TRANSITION_END, () => {\n called = true\n })\n\n setTimeout(() => {\n if (!called) {\n Util.triggerTransitionEnd(this)\n }\n }, duration)\n\n return this\n}\n\nfunction setTransitionEndSupport() {\n $.fn.emulateTransitionEnd = transitionEndEmulator\n $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent()\n}\n\n/**\n * --------------------------------------------------------------------------\n * Public Util Api\n * --------------------------------------------------------------------------\n */\n\nconst Util = {\n TRANSITION_END: 'bsTransitionEnd',\n\n getUID(prefix) {\n do {\n prefix += ~~(Math.random() * MAX_UID) // \"~~\" acts like a faster Math.floor() here\n } while (document.getElementById(prefix))\n\n return prefix\n },\n\n getSelectorFromElement(element) {\n let selector = element.getAttribute('data-target')\n\n if (!selector || selector === '#') {\n const hrefAttr = element.getAttribute('href')\n selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : ''\n }\n\n try {\n return document.querySelector(selector) ? selector : null\n } catch (_) {\n return null\n }\n },\n\n getTransitionDurationFromElement(element) {\n if (!element) {\n return 0\n }\n\n // Get transition-duration of the element\n let transitionDuration = $(element).css('transition-duration')\n let transitionDelay = $(element).css('transition-delay')\n\n const floatTransitionDuration = parseFloat(transitionDuration)\n const floatTransitionDelay = parseFloat(transitionDelay)\n\n // Return 0 if element or transition duration is not found\n if (!floatTransitionDuration && !floatTransitionDelay) {\n return 0\n }\n\n // If multiple durations are defined, take the first\n transitionDuration = transitionDuration.split(',')[0]\n transitionDelay = transitionDelay.split(',')[0]\n\n return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER\n },\n\n reflow(element) {\n return element.offsetHeight\n },\n\n triggerTransitionEnd(element) {\n $(element).trigger(TRANSITION_END)\n },\n\n supportsTransitionEnd() {\n return Boolean(TRANSITION_END)\n },\n\n isElement(obj) {\n return (obj[0] || obj).nodeType\n },\n\n typeCheckConfig(componentName, config, configTypes) {\n for (const property in configTypes) {\n if (Object.prototype.hasOwnProperty.call(configTypes, property)) {\n const expectedTypes = configTypes[property]\n const value = config[property]\n const valueType = value && Util.isElement(value) ?\n 'element' : toType(value)\n\n if (!new RegExp(expectedTypes).test(valueType)) {\n throw new Error(\n `${componentName.toUpperCase()}: ` +\n `Option \"${property}\" provided type \"${valueType}\" ` +\n `but expected type \"${expectedTypes}\".`)\n }\n }\n }\n },\n\n findShadowRoot(element) {\n if (!document.documentElement.attachShadow) {\n return null\n }\n\n // Can find the shadow root otherwise it'll return the document\n if (typeof element.getRootNode === 'function') {\n const root = element.getRootNode()\n return root instanceof ShadowRoot ? root : null\n }\n\n if (element instanceof ShadowRoot) {\n return element\n }\n\n // when we don't find a shadow root\n if (!element.parentNode) {\n return null\n }\n\n return Util.findShadowRoot(element.parentNode)\n },\n\n jQueryDetection() {\n if (typeof $ === 'undefined') {\n throw new TypeError('Bootstrap\\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\\'s JavaScript.')\n }\n\n const version = $.fn.jquery.split(' ')[0].split('.')\n const minMajor = 1\n const ltMajor = 2\n const minMinor = 9\n const minPatch = 1\n const maxMajor = 4\n\n if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) {\n throw new Error('Bootstrap\\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0')\n }\n }\n}\n\nUtil.jQueryDetection()\nsetTransitionEndSupport()\n\nexport default Util\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.5.3): alert.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\nimport Util from './util'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'alert'\nconst VERSION = '4.5.3'\nconst DATA_KEY = 'bs.alert'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\n\nconst SELECTOR_DISMISS = '[data-dismiss=\"alert\"]'\n\nconst EVENT_CLOSE = `close${EVENT_KEY}`\nconst EVENT_CLOSED = `closed${EVENT_KEY}`\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\n\nconst CLASS_NAME_ALERT = 'alert'\nconst CLASS_NAME_FADE = 'fade'\nconst CLASS_NAME_SHOW = 'show'\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass Alert {\n constructor(element) {\n this._element = element\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n // Public\n\n close(element) {\n let rootElement = this._element\n if (element) {\n rootElement = this._getRootElement(element)\n }\n\n const customEvent = this._triggerCloseEvent(rootElement)\n\n if (customEvent.isDefaultPrevented()) {\n return\n }\n\n this._removeElement(rootElement)\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n this._element = null\n }\n\n // Private\n\n _getRootElement(element) {\n const selector = Util.getSelectorFromElement(element)\n let parent = false\n\n if (selector) {\n parent = document.querySelector(selector)\n }\n\n if (!parent) {\n parent = $(element).closest(`.${CLASS_NAME_ALERT}`)[0]\n }\n\n return parent\n }\n\n _triggerCloseEvent(element) {\n const closeEvent = $.Event(EVENT_CLOSE)\n\n $(element).trigger(closeEvent)\n return closeEvent\n }\n\n _removeElement(element) {\n $(element).removeClass(CLASS_NAME_SHOW)\n\n if (!$(element).hasClass(CLASS_NAME_FADE)) {\n this._destroyElement(element)\n return\n }\n\n const transitionDuration = Util.getTransitionDurationFromElement(element)\n\n $(element)\n .one(Util.TRANSITION_END, event => this._destroyElement(element, event))\n .emulateTransitionEnd(transitionDuration)\n }\n\n _destroyElement(element) {\n $(element)\n .detach()\n .trigger(EVENT_CLOSED)\n .remove()\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n const $element = $(this)\n let data = $element.data(DATA_KEY)\n\n if (!data) {\n data = new Alert(this)\n $element.data(DATA_KEY, data)\n }\n\n if (config === 'close') {\n data[config](this)\n }\n })\n }\n\n static _handleDismiss(alertInstance) {\n return function (event) {\n if (event) {\n event.preventDefault()\n }\n\n alertInstance.close(this)\n }\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n$(document).on(\n EVENT_CLICK_DATA_API,\n SELECTOR_DISMISS,\n Alert._handleDismiss(new Alert())\n)\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Alert._jQueryInterface\n$.fn[NAME].Constructor = Alert\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Alert._jQueryInterface\n}\n\nexport default Alert\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.5.3): button.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'button'\nconst VERSION = '4.5.3'\nconst DATA_KEY = 'bs.button'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\n\nconst CLASS_NAME_ACTIVE = 'active'\nconst CLASS_NAME_BUTTON = 'btn'\nconst CLASS_NAME_FOCUS = 'focus'\n\nconst SELECTOR_DATA_TOGGLE_CARROT = '[data-toggle^=\"button\"]'\nconst SELECTOR_DATA_TOGGLES = '[data-toggle=\"buttons\"]'\nconst SELECTOR_DATA_TOGGLE = '[data-toggle=\"button\"]'\nconst SELECTOR_DATA_TOGGLES_BUTTONS = '[data-toggle=\"buttons\"] .btn'\nconst SELECTOR_INPUT = 'input:not([type=\"hidden\"])'\nconst SELECTOR_ACTIVE = '.active'\nconst SELECTOR_BUTTON = '.btn'\n\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\nconst EVENT_FOCUS_BLUR_DATA_API = `focus${EVENT_KEY}${DATA_API_KEY} ` +\n `blur${EVENT_KEY}${DATA_API_KEY}`\nconst EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass Button {\n constructor(element) {\n this._element = element\n this.shouldAvoidTriggerChange = false\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n // Public\n\n toggle() {\n let triggerChangeEvent = true\n let addAriaPressed = true\n const rootElement = $(this._element).closest(SELECTOR_DATA_TOGGLES)[0]\n\n if (rootElement) {\n const input = this._element.querySelector(SELECTOR_INPUT)\n\n if (input) {\n if (input.type === 'radio') {\n if (input.checked && this._element.classList.contains(CLASS_NAME_ACTIVE)) {\n triggerChangeEvent = false\n } else {\n const activeElement = rootElement.querySelector(SELECTOR_ACTIVE)\n\n if (activeElement) {\n $(activeElement).removeClass(CLASS_NAME_ACTIVE)\n }\n }\n }\n\n if (triggerChangeEvent) {\n // if it's not a radio button or checkbox don't add a pointless/invalid checked property to the input\n if (input.type === 'checkbox' || input.type === 'radio') {\n input.checked = !this._element.classList.contains(CLASS_NAME_ACTIVE)\n }\n\n if (!this.shouldAvoidTriggerChange) {\n $(input).trigger('change')\n }\n }\n\n input.focus()\n addAriaPressed = false\n }\n }\n\n if (!(this._element.hasAttribute('disabled') || this._element.classList.contains('disabled'))) {\n if (addAriaPressed) {\n this._element.setAttribute('aria-pressed', !this._element.classList.contains(CLASS_NAME_ACTIVE))\n }\n\n if (triggerChangeEvent) {\n $(this._element).toggleClass(CLASS_NAME_ACTIVE)\n }\n }\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n this._element = null\n }\n\n // Static\n\n static _jQueryInterface(config, avoidTriggerChange) {\n return this.each(function () {\n const $element = $(this)\n let data = $element.data(DATA_KEY)\n\n if (!data) {\n data = new Button(this)\n $element.data(DATA_KEY, data)\n }\n\n data.shouldAvoidTriggerChange = avoidTriggerChange\n\n if (config === 'toggle') {\n data[config]()\n }\n })\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n$(document)\n .on(EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE_CARROT, event => {\n let button = event.target\n const initialButton = button\n\n if (!$(button).hasClass(CLASS_NAME_BUTTON)) {\n button = $(button).closest(SELECTOR_BUTTON)[0]\n }\n\n if (!button || button.hasAttribute('disabled') || button.classList.contains('disabled')) {\n event.preventDefault() // work around Firefox bug #1540995\n } else {\n const inputBtn = button.querySelector(SELECTOR_INPUT)\n\n if (inputBtn && (inputBtn.hasAttribute('disabled') || inputBtn.classList.contains('disabled'))) {\n event.preventDefault() // work around Firefox bug #1540995\n return\n }\n\n if (initialButton.tagName === 'INPUT' || button.tagName !== 'LABEL') {\n Button._jQueryInterface.call($(button), 'toggle', initialButton.tagName === 'INPUT')\n }\n }\n })\n .on(EVENT_FOCUS_BLUR_DATA_API, SELECTOR_DATA_TOGGLE_CARROT, event => {\n const button = $(event.target).closest(SELECTOR_BUTTON)[0]\n $(button).toggleClass(CLASS_NAME_FOCUS, /^focus(in)?$/.test(event.type))\n })\n\n$(window).on(EVENT_LOAD_DATA_API, () => {\n // ensure correct active class is set to match the controls' actual values/states\n\n // find all checkboxes/readio buttons inside data-toggle groups\n let buttons = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLES_BUTTONS))\n for (let i = 0, len = buttons.length; i < len; i++) {\n const button = buttons[i]\n const input = button.querySelector(SELECTOR_INPUT)\n if (input.checked || input.hasAttribute('checked')) {\n button.classList.add(CLASS_NAME_ACTIVE)\n } else {\n button.classList.remove(CLASS_NAME_ACTIVE)\n }\n }\n\n // find all button toggles\n buttons = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLE))\n for (let i = 0, len = buttons.length; i < len; i++) {\n const button = buttons[i]\n if (button.getAttribute('aria-pressed') === 'true') {\n button.classList.add(CLASS_NAME_ACTIVE)\n } else {\n button.classList.remove(CLASS_NAME_ACTIVE)\n }\n }\n})\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Button._jQueryInterface\n$.fn[NAME].Constructor = Button\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Button._jQueryInterface\n}\n\nexport default Button\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.5.3): carousel.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\nimport Util from './util'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'carousel'\nconst VERSION = '4.5.3'\nconst DATA_KEY = 'bs.carousel'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\nconst ARROW_LEFT_KEYCODE = 37 // KeyboardEvent.which value for left arrow key\nconst ARROW_RIGHT_KEYCODE = 39 // KeyboardEvent.which value for right arrow key\nconst TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch\nconst SWIPE_THRESHOLD = 40\n\nconst Default = {\n interval: 5000,\n keyboard: true,\n slide: false,\n pause: 'hover',\n wrap: true,\n touch: true\n}\n\nconst DefaultType = {\n interval: '(number|boolean)',\n keyboard: 'boolean',\n slide: '(boolean|string)',\n pause: '(string|boolean)',\n wrap: 'boolean',\n touch: 'boolean'\n}\n\nconst DIRECTION_NEXT = 'next'\nconst DIRECTION_PREV = 'prev'\nconst DIRECTION_LEFT = 'left'\nconst DIRECTION_RIGHT = 'right'\n\nconst EVENT_SLIDE = `slide${EVENT_KEY}`\nconst EVENT_SLID = `slid${EVENT_KEY}`\nconst EVENT_KEYDOWN = `keydown${EVENT_KEY}`\nconst EVENT_MOUSEENTER = `mouseenter${EVENT_KEY}`\nconst EVENT_MOUSELEAVE = `mouseleave${EVENT_KEY}`\nconst EVENT_TOUCHSTART = `touchstart${EVENT_KEY}`\nconst EVENT_TOUCHMOVE = `touchmove${EVENT_KEY}`\nconst EVENT_TOUCHEND = `touchend${EVENT_KEY}`\nconst EVENT_POINTERDOWN = `pointerdown${EVENT_KEY}`\nconst EVENT_POINTERUP = `pointerup${EVENT_KEY}`\nconst EVENT_DRAG_START = `dragstart${EVENT_KEY}`\nconst EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\n\nconst CLASS_NAME_CAROUSEL = 'carousel'\nconst CLASS_NAME_ACTIVE = 'active'\nconst CLASS_NAME_SLIDE = 'slide'\nconst CLASS_NAME_RIGHT = 'carousel-item-right'\nconst CLASS_NAME_LEFT = 'carousel-item-left'\nconst CLASS_NAME_NEXT = 'carousel-item-next'\nconst CLASS_NAME_PREV = 'carousel-item-prev'\nconst CLASS_NAME_POINTER_EVENT = 'pointer-event'\n\nconst SELECTOR_ACTIVE = '.active'\nconst SELECTOR_ACTIVE_ITEM = '.active.carousel-item'\nconst SELECTOR_ITEM = '.carousel-item'\nconst SELECTOR_ITEM_IMG = '.carousel-item img'\nconst SELECTOR_NEXT_PREV = '.carousel-item-next, .carousel-item-prev'\nconst SELECTOR_INDICATORS = '.carousel-indicators'\nconst SELECTOR_DATA_SLIDE = '[data-slide], [data-slide-to]'\nconst SELECTOR_DATA_RIDE = '[data-ride=\"carousel\"]'\n\nconst PointerType = {\n TOUCH: 'touch',\n PEN: 'pen'\n}\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\nclass Carousel {\n constructor(element, config) {\n this._items = null\n this._interval = null\n this._activeElement = null\n this._isPaused = false\n this._isSliding = false\n this.touchTimeout = null\n this.touchStartX = 0\n this.touchDeltaX = 0\n\n this._config = this._getConfig(config)\n this._element = element\n this._indicatorsElement = this._element.querySelector(SELECTOR_INDICATORS)\n this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0\n this._pointerEvent = Boolean(window.PointerEvent || window.MSPointerEvent)\n\n this._addEventListeners()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n next() {\n if (!this._isSliding) {\n this._slide(DIRECTION_NEXT)\n }\n }\n\n nextWhenVisible() {\n const $element = $(this._element)\n // Don't call next when the page isn't visible\n // or the carousel or its parent isn't visible\n if (!document.hidden &&\n ($element.is(':visible') && $element.css('visibility') !== 'hidden')) {\n this.next()\n }\n }\n\n prev() {\n if (!this._isSliding) {\n this._slide(DIRECTION_PREV)\n }\n }\n\n pause(event) {\n if (!event) {\n this._isPaused = true\n }\n\n if (this._element.querySelector(SELECTOR_NEXT_PREV)) {\n Util.triggerTransitionEnd(this._element)\n this.cycle(true)\n }\n\n clearInterval(this._interval)\n this._interval = null\n }\n\n cycle(event) {\n if (!event) {\n this._isPaused = false\n }\n\n if (this._interval) {\n clearInterval(this._interval)\n this._interval = null\n }\n\n if (this._config.interval && !this._isPaused) {\n this._interval = setInterval(\n (document.visibilityState ? this.nextWhenVisible : this.next).bind(this),\n this._config.interval\n )\n }\n }\n\n to(index) {\n this._activeElement = this._element.querySelector(SELECTOR_ACTIVE_ITEM)\n\n const activeIndex = this._getItemIndex(this._activeElement)\n\n if (index > this._items.length - 1 || index < 0) {\n return\n }\n\n if (this._isSliding) {\n $(this._element).one(EVENT_SLID, () => this.to(index))\n return\n }\n\n if (activeIndex === index) {\n this.pause()\n this.cycle()\n return\n }\n\n const direction = index > activeIndex ?\n DIRECTION_NEXT :\n DIRECTION_PREV\n\n this._slide(direction, this._items[index])\n }\n\n dispose() {\n $(this._element).off(EVENT_KEY)\n $.removeData(this._element, DATA_KEY)\n\n this._items = null\n this._config = null\n this._element = null\n this._interval = null\n this._isPaused = null\n this._isSliding = null\n this._activeElement = null\n this._indicatorsElement = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _handleSwipe() {\n const absDeltax = Math.abs(this.touchDeltaX)\n\n if (absDeltax <= SWIPE_THRESHOLD) {\n return\n }\n\n const direction = absDeltax / this.touchDeltaX\n\n this.touchDeltaX = 0\n\n // swipe left\n if (direction > 0) {\n this.prev()\n }\n\n // swipe right\n if (direction < 0) {\n this.next()\n }\n }\n\n _addEventListeners() {\n if (this._config.keyboard) {\n $(this._element).on(EVENT_KEYDOWN, event => this._keydown(event))\n }\n\n if (this._config.pause === 'hover') {\n $(this._element)\n .on(EVENT_MOUSEENTER, event => this.pause(event))\n .on(EVENT_MOUSELEAVE, event => this.cycle(event))\n }\n\n if (this._config.touch) {\n this._addTouchEventListeners()\n }\n }\n\n _addTouchEventListeners() {\n if (!this._touchSupported) {\n return\n }\n\n const start = event => {\n if (this._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) {\n this.touchStartX = event.originalEvent.clientX\n } else if (!this._pointerEvent) {\n this.touchStartX = event.originalEvent.touches[0].clientX\n }\n }\n\n const move = event => {\n // ensure swiping with one touch and not pinching\n if (event.originalEvent.touches && event.originalEvent.touches.length > 1) {\n this.touchDeltaX = 0\n } else {\n this.touchDeltaX = event.originalEvent.touches[0].clientX - this.touchStartX\n }\n }\n\n const end = event => {\n if (this._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) {\n this.touchDeltaX = event.originalEvent.clientX - this.touchStartX\n }\n\n this._handleSwipe()\n if (this._config.pause === 'hover') {\n // If it's a touch-enabled device, mouseenter/leave are fired as\n // part of the mouse compatibility events on first tap - the carousel\n // would stop cycling until user tapped out of it;\n // here, we listen for touchend, explicitly pause the carousel\n // (as if it's the second time we tap on it, mouseenter compat event\n // is NOT fired) and after a timeout (to allow for mouse compatibility\n // events to fire) we explicitly restart cycling\n\n this.pause()\n if (this.touchTimeout) {\n clearTimeout(this.touchTimeout)\n }\n\n this.touchTimeout = setTimeout(event => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval)\n }\n }\n\n $(this._element.querySelectorAll(SELECTOR_ITEM_IMG))\n .on(EVENT_DRAG_START, e => e.preventDefault())\n\n if (this._pointerEvent) {\n $(this._element).on(EVENT_POINTERDOWN, event => start(event))\n $(this._element).on(EVENT_POINTERUP, event => end(event))\n\n this._element.classList.add(CLASS_NAME_POINTER_EVENT)\n } else {\n $(this._element).on(EVENT_TOUCHSTART, event => start(event))\n $(this._element).on(EVENT_TOUCHMOVE, event => move(event))\n $(this._element).on(EVENT_TOUCHEND, event => end(event))\n }\n }\n\n _keydown(event) {\n if (/input|textarea/i.test(event.target.tagName)) {\n return\n }\n\n switch (event.which) {\n case ARROW_LEFT_KEYCODE:\n event.preventDefault()\n this.prev()\n break\n case ARROW_RIGHT_KEYCODE:\n event.preventDefault()\n this.next()\n break\n default:\n }\n }\n\n _getItemIndex(element) {\n this._items = element && element.parentNode ?\n [].slice.call(element.parentNode.querySelectorAll(SELECTOR_ITEM)) :\n []\n return this._items.indexOf(element)\n }\n\n _getItemByDirection(direction, activeElement) {\n const isNextDirection = direction === DIRECTION_NEXT\n const isPrevDirection = direction === DIRECTION_PREV\n const activeIndex = this._getItemIndex(activeElement)\n const lastItemIndex = this._items.length - 1\n const isGoingToWrap = isPrevDirection && activeIndex === 0 ||\n isNextDirection && activeIndex === lastItemIndex\n\n if (isGoingToWrap && !this._config.wrap) {\n return activeElement\n }\n\n const delta = direction === DIRECTION_PREV ? -1 : 1\n const itemIndex = (activeIndex + delta) % this._items.length\n\n return itemIndex === -1 ?\n this._items[this._items.length - 1] : this._items[itemIndex]\n }\n\n _triggerSlideEvent(relatedTarget, eventDirectionName) {\n const targetIndex = this._getItemIndex(relatedTarget)\n const fromIndex = this._getItemIndex(this._element.querySelector(SELECTOR_ACTIVE_ITEM))\n const slideEvent = $.Event(EVENT_SLIDE, {\n relatedTarget,\n direction: eventDirectionName,\n from: fromIndex,\n to: targetIndex\n })\n\n $(this._element).trigger(slideEvent)\n\n return slideEvent\n }\n\n _setActiveIndicatorElement(element) {\n if (this._indicatorsElement) {\n const indicators = [].slice.call(this._indicatorsElement.querySelectorAll(SELECTOR_ACTIVE))\n $(indicators).removeClass(CLASS_NAME_ACTIVE)\n\n const nextIndicator = this._indicatorsElement.children[\n this._getItemIndex(element)\n ]\n\n if (nextIndicator) {\n $(nextIndicator).addClass(CLASS_NAME_ACTIVE)\n }\n }\n }\n\n _slide(direction, element) {\n const activeElement = this._element.querySelector(SELECTOR_ACTIVE_ITEM)\n const activeElementIndex = this._getItemIndex(activeElement)\n const nextElement = element || activeElement &&\n this._getItemByDirection(direction, activeElement)\n const nextElementIndex = this._getItemIndex(nextElement)\n const isCycling = Boolean(this._interval)\n\n let directionalClassName\n let orderClassName\n let eventDirectionName\n\n if (direction === DIRECTION_NEXT) {\n directionalClassName = CLASS_NAME_LEFT\n orderClassName = CLASS_NAME_NEXT\n eventDirectionName = DIRECTION_LEFT\n } else {\n directionalClassName = CLASS_NAME_RIGHT\n orderClassName = CLASS_NAME_PREV\n eventDirectionName = DIRECTION_RIGHT\n }\n\n if (nextElement && $(nextElement).hasClass(CLASS_NAME_ACTIVE)) {\n this._isSliding = false\n return\n }\n\n const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName)\n if (slideEvent.isDefaultPrevented()) {\n return\n }\n\n if (!activeElement || !nextElement) {\n // Some weirdness is happening, so we bail\n return\n }\n\n this._isSliding = true\n\n if (isCycling) {\n this.pause()\n }\n\n this._setActiveIndicatorElement(nextElement)\n\n const slidEvent = $.Event(EVENT_SLID, {\n relatedTarget: nextElement,\n direction: eventDirectionName,\n from: activeElementIndex,\n to: nextElementIndex\n })\n\n if ($(this._element).hasClass(CLASS_NAME_SLIDE)) {\n $(nextElement).addClass(orderClassName)\n\n Util.reflow(nextElement)\n\n $(activeElement).addClass(directionalClassName)\n $(nextElement).addClass(directionalClassName)\n\n const nextElementInterval = parseInt(nextElement.getAttribute('data-interval'), 10)\n if (nextElementInterval) {\n this._config.defaultInterval = this._config.defaultInterval || this._config.interval\n this._config.interval = nextElementInterval\n } else {\n this._config.interval = this._config.defaultInterval || this._config.interval\n }\n\n const transitionDuration = Util.getTransitionDurationFromElement(activeElement)\n\n $(activeElement)\n .one(Util.TRANSITION_END, () => {\n $(nextElement)\n .removeClass(`${directionalClassName} ${orderClassName}`)\n .addClass(CLASS_NAME_ACTIVE)\n\n $(activeElement).removeClass(`${CLASS_NAME_ACTIVE} ${orderClassName} ${directionalClassName}`)\n\n this._isSliding = false\n\n setTimeout(() => $(this._element).trigger(slidEvent), 0)\n })\n .emulateTransitionEnd(transitionDuration)\n } else {\n $(activeElement).removeClass(CLASS_NAME_ACTIVE)\n $(nextElement).addClass(CLASS_NAME_ACTIVE)\n\n this._isSliding = false\n $(this._element).trigger(slidEvent)\n }\n\n if (isCycling) {\n this.cycle()\n }\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n let _config = {\n ...Default,\n ...$(this).data()\n }\n\n if (typeof config === 'object') {\n _config = {\n ..._config,\n ...config\n }\n }\n\n const action = typeof config === 'string' ? config : _config.slide\n\n if (!data) {\n data = new Carousel(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'number') {\n data.to(config)\n } else if (typeof action === 'string') {\n if (typeof data[action] === 'undefined') {\n throw new TypeError(`No method named \"${action}\"`)\n }\n\n data[action]()\n } else if (_config.interval && _config.ride) {\n data.pause()\n data.cycle()\n }\n })\n }\n\n static _dataApiClickHandler(event) {\n const selector = Util.getSelectorFromElement(this)\n\n if (!selector) {\n return\n }\n\n const target = $(selector)[0]\n\n if (!target || !$(target).hasClass(CLASS_NAME_CAROUSEL)) {\n return\n }\n\n const config = {\n ...$(target).data(),\n ...$(this).data()\n }\n const slideIndex = this.getAttribute('data-slide-to')\n\n if (slideIndex) {\n config.interval = false\n }\n\n Carousel._jQueryInterface.call($(target), config)\n\n if (slideIndex) {\n $(target).data(DATA_KEY).to(slideIndex)\n }\n\n event.preventDefault()\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n$(document).on(EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, Carousel._dataApiClickHandler)\n\n$(window).on(EVENT_LOAD_DATA_API, () => {\n const carousels = [].slice.call(document.querySelectorAll(SELECTOR_DATA_RIDE))\n for (let i = 0, len = carousels.length; i < len; i++) {\n const $carousel = $(carousels[i])\n Carousel._jQueryInterface.call($carousel, $carousel.data())\n }\n})\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Carousel._jQueryInterface\n$.fn[NAME].Constructor = Carousel\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Carousel._jQueryInterface\n}\n\nexport default Carousel\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.5.3): collapse.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\nimport Util from './util'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'collapse'\nconst VERSION = '4.5.3'\nconst DATA_KEY = 'bs.collapse'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\n\nconst Default = {\n toggle: true,\n parent: ''\n}\n\nconst DefaultType = {\n toggle: 'boolean',\n parent: '(string|element)'\n}\n\nconst EVENT_SHOW = `show${EVENT_KEY}`\nconst EVENT_SHOWN = `shown${EVENT_KEY}`\nconst EVENT_HIDE = `hide${EVENT_KEY}`\nconst EVENT_HIDDEN = `hidden${EVENT_KEY}`\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\n\nconst CLASS_NAME_SHOW = 'show'\nconst CLASS_NAME_COLLAPSE = 'collapse'\nconst CLASS_NAME_COLLAPSING = 'collapsing'\nconst CLASS_NAME_COLLAPSED = 'collapsed'\n\nconst DIMENSION_WIDTH = 'width'\nconst DIMENSION_HEIGHT = 'height'\n\nconst SELECTOR_ACTIVES = '.show, .collapsing'\nconst SELECTOR_DATA_TOGGLE = '[data-toggle=\"collapse\"]'\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass Collapse {\n constructor(element, config) {\n this._isTransitioning = false\n this._element = element\n this._config = this._getConfig(config)\n this._triggerArray = [].slice.call(document.querySelectorAll(\n `[data-toggle=\"collapse\"][href=\"#${element.id}\"],` +\n `[data-toggle=\"collapse\"][data-target=\"#${element.id}\"]`\n ))\n\n const toggleList = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLE))\n for (let i = 0, len = toggleList.length; i < len; i++) {\n const elem = toggleList[i]\n const selector = Util.getSelectorFromElement(elem)\n const filterElement = [].slice.call(document.querySelectorAll(selector))\n .filter(foundElem => foundElem === element)\n\n if (selector !== null && filterElement.length > 0) {\n this._selector = selector\n this._triggerArray.push(elem)\n }\n }\n\n this._parent = this._config.parent ? this._getParent() : null\n\n if (!this._config.parent) {\n this._addAriaAndCollapsedClass(this._element, this._triggerArray)\n }\n\n if (this._config.toggle) {\n this.toggle()\n }\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n toggle() {\n if ($(this._element).hasClass(CLASS_NAME_SHOW)) {\n this.hide()\n } else {\n this.show()\n }\n }\n\n show() {\n if (this._isTransitioning ||\n $(this._element).hasClass(CLASS_NAME_SHOW)) {\n return\n }\n\n let actives\n let activesData\n\n if (this._parent) {\n actives = [].slice.call(this._parent.querySelectorAll(SELECTOR_ACTIVES))\n .filter(elem => {\n if (typeof this._config.parent === 'string') {\n return elem.getAttribute('data-parent') === this._config.parent\n }\n\n return elem.classList.contains(CLASS_NAME_COLLAPSE)\n })\n\n if (actives.length === 0) {\n actives = null\n }\n }\n\n if (actives) {\n activesData = $(actives).not(this._selector).data(DATA_KEY)\n if (activesData && activesData._isTransitioning) {\n return\n }\n }\n\n const startEvent = $.Event(EVENT_SHOW)\n $(this._element).trigger(startEvent)\n if (startEvent.isDefaultPrevented()) {\n return\n }\n\n if (actives) {\n Collapse._jQueryInterface.call($(actives).not(this._selector), 'hide')\n if (!activesData) {\n $(actives).data(DATA_KEY, null)\n }\n }\n\n const dimension = this._getDimension()\n\n $(this._element)\n .removeClass(CLASS_NAME_COLLAPSE)\n .addClass(CLASS_NAME_COLLAPSING)\n\n this._element.style[dimension] = 0\n\n if (this._triggerArray.length) {\n $(this._triggerArray)\n .removeClass(CLASS_NAME_COLLAPSED)\n .attr('aria-expanded', true)\n }\n\n this.setTransitioning(true)\n\n const complete = () => {\n $(this._element)\n .removeClass(CLASS_NAME_COLLAPSING)\n .addClass(`${CLASS_NAME_COLLAPSE} ${CLASS_NAME_SHOW}`)\n\n this._element.style[dimension] = ''\n\n this.setTransitioning(false)\n\n $(this._element).trigger(EVENT_SHOWN)\n }\n\n const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1)\n const scrollSize = `scroll${capitalizedDimension}`\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n\n this._element.style[dimension] = `${this._element[scrollSize]}px`\n }\n\n hide() {\n if (this._isTransitioning ||\n !$(this._element).hasClass(CLASS_NAME_SHOW)) {\n return\n }\n\n const startEvent = $.Event(EVENT_HIDE)\n $(this._element).trigger(startEvent)\n if (startEvent.isDefaultPrevented()) {\n return\n }\n\n const dimension = this._getDimension()\n\n this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`\n\n Util.reflow(this._element)\n\n $(this._element)\n .addClass(CLASS_NAME_COLLAPSING)\n .removeClass(`${CLASS_NAME_COLLAPSE} ${CLASS_NAME_SHOW}`)\n\n const triggerArrayLength = this._triggerArray.length\n if (triggerArrayLength > 0) {\n for (let i = 0; i < triggerArrayLength; i++) {\n const trigger = this._triggerArray[i]\n const selector = Util.getSelectorFromElement(trigger)\n\n if (selector !== null) {\n const $elem = $([].slice.call(document.querySelectorAll(selector)))\n if (!$elem.hasClass(CLASS_NAME_SHOW)) {\n $(trigger).addClass(CLASS_NAME_COLLAPSED)\n .attr('aria-expanded', false)\n }\n }\n }\n }\n\n this.setTransitioning(true)\n\n const complete = () => {\n this.setTransitioning(false)\n $(this._element)\n .removeClass(CLASS_NAME_COLLAPSING)\n .addClass(CLASS_NAME_COLLAPSE)\n .trigger(EVENT_HIDDEN)\n }\n\n this._element.style[dimension] = ''\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n }\n\n setTransitioning(isTransitioning) {\n this._isTransitioning = isTransitioning\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n\n this._config = null\n this._parent = null\n this._element = null\n this._triggerArray = null\n this._isTransitioning = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n config.toggle = Boolean(config.toggle) // Coerce string values\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _getDimension() {\n const hasWidth = $(this._element).hasClass(DIMENSION_WIDTH)\n return hasWidth ? DIMENSION_WIDTH : DIMENSION_HEIGHT\n }\n\n _getParent() {\n let parent\n\n if (Util.isElement(this._config.parent)) {\n parent = this._config.parent\n\n // It's a jQuery object\n if (typeof this._config.parent.jquery !== 'undefined') {\n parent = this._config.parent[0]\n }\n } else {\n parent = document.querySelector(this._config.parent)\n }\n\n const selector = `[data-toggle=\"collapse\"][data-parent=\"${this._config.parent}\"]`\n const children = [].slice.call(parent.querySelectorAll(selector))\n\n $(children).each((i, element) => {\n this._addAriaAndCollapsedClass(\n Collapse._getTargetFromElement(element),\n [element]\n )\n })\n\n return parent\n }\n\n _addAriaAndCollapsedClass(element, triggerArray) {\n const isOpen = $(element).hasClass(CLASS_NAME_SHOW)\n\n if (triggerArray.length) {\n $(triggerArray)\n .toggleClass(CLASS_NAME_COLLAPSED, !isOpen)\n .attr('aria-expanded', isOpen)\n }\n }\n\n // Static\n\n static _getTargetFromElement(element) {\n const selector = Util.getSelectorFromElement(element)\n return selector ? document.querySelector(selector) : null\n }\n\n static _jQueryInterface(config) {\n return this.each(function () {\n const $element = $(this)\n let data = $element.data(DATA_KEY)\n const _config = {\n ...Default,\n ...$element.data(),\n ...(typeof config === 'object' && config ? config : {})\n }\n\n if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) {\n _config.toggle = false\n }\n\n if (!data) {\n data = new Collapse(this, _config)\n $element.data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n }\n })\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n$(document).on(EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {\n // preventDefault only for elements (which change the URL) not inside the collapsible element\n if (event.currentTarget.tagName === 'A') {\n event.preventDefault()\n }\n\n const $trigger = $(this)\n const selector = Util.getSelectorFromElement(this)\n const selectors = [].slice.call(document.querySelectorAll(selector))\n\n $(selectors).each(function () {\n const $target = $(this)\n const data = $target.data(DATA_KEY)\n const config = data ? 'toggle' : $trigger.data()\n Collapse._jQueryInterface.call($target, config)\n })\n})\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Collapse._jQueryInterface\n$.fn[NAME].Constructor = Collapse\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Collapse._jQueryInterface\n}\n\nexport default Collapse\n","/**!\n * @fileOverview Kickass library to create and place poppers near their reference elements.\n * @version 1.16.1\n * @license\n * Copyright (c) 2016 Federico Zivolo and contributors\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\nvar isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && typeof navigator !== 'undefined';\n\nvar timeoutDuration = function () {\n var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];\n for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {\n if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {\n return 1;\n }\n }\n return 0;\n}();\n\nfunction microtaskDebounce(fn) {\n var called = false;\n return function () {\n if (called) {\n return;\n }\n called = true;\n window.Promise.resolve().then(function () {\n called = false;\n fn();\n });\n };\n}\n\nfunction taskDebounce(fn) {\n var scheduled = false;\n return function () {\n if (!scheduled) {\n scheduled = true;\n setTimeout(function () {\n scheduled = false;\n fn();\n }, timeoutDuration);\n }\n };\n}\n\nvar supportsMicroTasks = isBrowser && window.Promise;\n\n/**\n* Create a debounced version of a method, that's asynchronously deferred\n* but called in the minimum time possible.\n*\n* @method\n* @memberof Popper.Utils\n* @argument {Function} fn\n* @returns {Function}\n*/\nvar debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;\n\n/**\n * Check if the given variable is a function\n * @method\n * @memberof Popper.Utils\n * @argument {Any} functionToCheck - variable to check\n * @returns {Boolean} answer to: is a function?\n */\nfunction isFunction(functionToCheck) {\n var getType = {};\n return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';\n}\n\n/**\n * Get CSS computed property of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Eement} element\n * @argument {String} property\n */\nfunction getStyleComputedProperty(element, property) {\n if (element.nodeType !== 1) {\n return [];\n }\n // NOTE: 1 DOM access here\n var window = element.ownerDocument.defaultView;\n var css = window.getComputedStyle(element, null);\n return property ? css[property] : css;\n}\n\n/**\n * Returns the parentNode or the host of the element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} parent\n */\nfunction getParentNode(element) {\n if (element.nodeName === 'HTML') {\n return element;\n }\n return element.parentNode || element.host;\n}\n\n/**\n * Returns the scrolling parent of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} scroll parent\n */\nfunction getScrollParent(element) {\n // Return body, `getScroll` will take care to get the correct `scrollTop` from it\n if (!element) {\n return document.body;\n }\n\n switch (element.nodeName) {\n case 'HTML':\n case 'BODY':\n return element.ownerDocument.body;\n case '#document':\n return element.body;\n }\n\n // Firefox want us to check `-x` and `-y` variations as well\n\n var _getStyleComputedProp = getStyleComputedProperty(element),\n overflow = _getStyleComputedProp.overflow,\n overflowX = _getStyleComputedProp.overflowX,\n overflowY = _getStyleComputedProp.overflowY;\n\n if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {\n return element;\n }\n\n return getScrollParent(getParentNode(element));\n}\n\n/**\n * Returns the reference node of the reference object, or the reference object itself.\n * @method\n * @memberof Popper.Utils\n * @param {Element|Object} reference - the reference element (the popper will be relative to this)\n * @returns {Element} parent\n */\nfunction getReferenceNode(reference) {\n return reference && reference.referenceNode ? reference.referenceNode : reference;\n}\n\nvar isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode);\nvar isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent);\n\n/**\n * Determines if the browser is Internet Explorer\n * @method\n * @memberof Popper.Utils\n * @param {Number} version to check\n * @returns {Boolean} isIE\n */\nfunction isIE(version) {\n if (version === 11) {\n return isIE11;\n }\n if (version === 10) {\n return isIE10;\n }\n return isIE11 || isIE10;\n}\n\n/**\n * Returns the offset parent of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} offset parent\n */\nfunction getOffsetParent(element) {\n if (!element) {\n return document.documentElement;\n }\n\n var noOffsetParent = isIE(10) ? document.body : null;\n\n // NOTE: 1 DOM access here\n var offsetParent = element.offsetParent || null;\n // Skip hidden elements which don't have an offsetParent\n while (offsetParent === noOffsetParent && element.nextElementSibling) {\n offsetParent = (element = element.nextElementSibling).offsetParent;\n }\n\n var nodeName = offsetParent && offsetParent.nodeName;\n\n if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {\n return element ? element.ownerDocument.documentElement : document.documentElement;\n }\n\n // .offsetParent will return the closest TH, TD or TABLE in case\n // no offsetParent is present, I hate this job...\n if (['TH', 'TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {\n return getOffsetParent(offsetParent);\n }\n\n return offsetParent;\n}\n\nfunction isOffsetContainer(element) {\n var nodeName = element.nodeName;\n\n if (nodeName === 'BODY') {\n return false;\n }\n return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;\n}\n\n/**\n * Finds the root node (document, shadowDOM root) of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} node\n * @returns {Element} root node\n */\nfunction getRoot(node) {\n if (node.parentNode !== null) {\n return getRoot(node.parentNode);\n }\n\n return node;\n}\n\n/**\n * Finds the offset parent common to the two provided nodes\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element1\n * @argument {Element} element2\n * @returns {Element} common offset parent\n */\nfunction findCommonOffsetParent(element1, element2) {\n // This check is needed to avoid errors in case one of the elements isn't defined for any reason\n if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {\n return document.documentElement;\n }\n\n // Here we make sure to give as \"start\" the element that comes first in the DOM\n var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;\n var start = order ? element1 : element2;\n var end = order ? element2 : element1;\n\n // Get common ancestor container\n var range = document.createRange();\n range.setStart(start, 0);\n range.setEnd(end, 0);\n var commonAncestorContainer = range.commonAncestorContainer;\n\n // Both nodes are inside #document\n\n if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {\n if (isOffsetContainer(commonAncestorContainer)) {\n return commonAncestorContainer;\n }\n\n return getOffsetParent(commonAncestorContainer);\n }\n\n // one of the nodes is inside shadowDOM, find which one\n var element1root = getRoot(element1);\n if (element1root.host) {\n return findCommonOffsetParent(element1root.host, element2);\n } else {\n return findCommonOffsetParent(element1, getRoot(element2).host);\n }\n}\n\n/**\n * Gets the scroll value of the given element in the given side (top and left)\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @argument {String} side `top` or `left`\n * @returns {number} amount of scrolled pixels\n */\nfunction getScroll(element) {\n var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';\n\n var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';\n var nodeName = element.nodeName;\n\n if (nodeName === 'BODY' || nodeName === 'HTML') {\n var html = element.ownerDocument.documentElement;\n var scrollingElement = element.ownerDocument.scrollingElement || html;\n return scrollingElement[upperSide];\n }\n\n return element[upperSide];\n}\n\n/*\n * Sum or subtract the element scroll values (left and top) from a given rect object\n * @method\n * @memberof Popper.Utils\n * @param {Object} rect - Rect object you want to change\n * @param {HTMLElement} element - The element from the function reads the scroll values\n * @param {Boolean} subtract - set to true if you want to subtract the scroll values\n * @return {Object} rect - The modifier rect object\n */\nfunction includeScroll(rect, element) {\n var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\n var scrollTop = getScroll(element, 'top');\n var scrollLeft = getScroll(element, 'left');\n var modifier = subtract ? -1 : 1;\n rect.top += scrollTop * modifier;\n rect.bottom += scrollTop * modifier;\n rect.left += scrollLeft * modifier;\n rect.right += scrollLeft * modifier;\n return rect;\n}\n\n/*\n * Helper to detect borders of a given element\n * @method\n * @memberof Popper.Utils\n * @param {CSSStyleDeclaration} styles\n * Result of `getStyleComputedProperty` on the given element\n * @param {String} axis - `x` or `y`\n * @return {number} borders - The borders size of the given axis\n */\n\nfunction getBordersSize(styles, axis) {\n var sideA = axis === 'x' ? 'Left' : 'Top';\n var sideB = sideA === 'Left' ? 'Right' : 'Bottom';\n\n return parseFloat(styles['border' + sideA + 'Width']) + parseFloat(styles['border' + sideB + 'Width']);\n}\n\nfunction getSize(axis, body, html, computedStyle) {\n return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE(10) ? parseInt(html['offset' + axis]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')]) : 0);\n}\n\nfunction getWindowSizes(document) {\n var body = document.body;\n var html = document.documentElement;\n var computedStyle = isIE(10) && getComputedStyle(html);\n\n return {\n height: getSize('Height', body, html, computedStyle),\n width: getSize('Width', body, html, computedStyle)\n };\n}\n\nvar classCallCheck = function (instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n};\n\nvar createClass = function () {\n function defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n }\n\n return function (Constructor, protoProps, staticProps) {\n if (protoProps) defineProperties(Constructor.prototype, protoProps);\n if (staticProps) defineProperties(Constructor, staticProps);\n return Constructor;\n };\n}();\n\n\n\n\n\nvar defineProperty = function (obj, key, value) {\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n\n return obj;\n};\n\nvar _extends = Object.assign || function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n\n return target;\n};\n\n/**\n * Given element offsets, generate an output similar to getBoundingClientRect\n * @method\n * @memberof Popper.Utils\n * @argument {Object} offsets\n * @returns {Object} ClientRect like output\n */\nfunction getClientRect(offsets) {\n return _extends({}, offsets, {\n right: offsets.left + offsets.width,\n bottom: offsets.top + offsets.height\n });\n}\n\n/**\n * Get bounding client rect of given element\n * @method\n * @memberof Popper.Utils\n * @param {HTMLElement} element\n * @return {Object} client rect\n */\nfunction getBoundingClientRect(element) {\n var rect = {};\n\n // IE10 10 FIX: Please, don't ask, the element isn't\n // considered in DOM in some circumstances...\n // This isn't reproducible in IE10 compatibility mode of IE11\n try {\n if (isIE(10)) {\n rect = element.getBoundingClientRect();\n var scrollTop = getScroll(element, 'top');\n var scrollLeft = getScroll(element, 'left');\n rect.top += scrollTop;\n rect.left += scrollLeft;\n rect.bottom += scrollTop;\n rect.right += scrollLeft;\n } else {\n rect = element.getBoundingClientRect();\n }\n } catch (e) {}\n\n var result = {\n left: rect.left,\n top: rect.top,\n width: rect.right - rect.left,\n height: rect.bottom - rect.top\n };\n\n // subtract scrollbar size from sizes\n var sizes = element.nodeName === 'HTML' ? getWindowSizes(element.ownerDocument) : {};\n var width = sizes.width || element.clientWidth || result.width;\n var height = sizes.height || element.clientHeight || result.height;\n\n var horizScrollbar = element.offsetWidth - width;\n var vertScrollbar = element.offsetHeight - height;\n\n // if an hypothetical scrollbar is detected, we must be sure it's not a `border`\n // we make this check conditional for performance reasons\n if (horizScrollbar || vertScrollbar) {\n var styles = getStyleComputedProperty(element);\n horizScrollbar -= getBordersSize(styles, 'x');\n vertScrollbar -= getBordersSize(styles, 'y');\n\n result.width -= horizScrollbar;\n result.height -= vertScrollbar;\n }\n\n return getClientRect(result);\n}\n\nfunction getOffsetRectRelativeToArbitraryNode(children, parent) {\n var fixedPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\n var isIE10 = isIE(10);\n var isHTML = parent.nodeName === 'HTML';\n var childrenRect = getBoundingClientRect(children);\n var parentRect = getBoundingClientRect(parent);\n var scrollParent = getScrollParent(children);\n\n var styles = getStyleComputedProperty(parent);\n var borderTopWidth = parseFloat(styles.borderTopWidth);\n var borderLeftWidth = parseFloat(styles.borderLeftWidth);\n\n // In cases where the parent is fixed, we must ignore negative scroll in offset calc\n if (fixedPosition && isHTML) {\n parentRect.top = Math.max(parentRect.top, 0);\n parentRect.left = Math.max(parentRect.left, 0);\n }\n var offsets = getClientRect({\n top: childrenRect.top - parentRect.top - borderTopWidth,\n left: childrenRect.left - parentRect.left - borderLeftWidth,\n width: childrenRect.width,\n height: childrenRect.height\n });\n offsets.marginTop = 0;\n offsets.marginLeft = 0;\n\n // Subtract margins of documentElement in case it's being used as parent\n // we do this only on HTML because it's the only element that behaves\n // differently when margins are applied to it. The margins are included in\n // the box of the documentElement, in the other cases not.\n if (!isIE10 && isHTML) {\n var marginTop = parseFloat(styles.marginTop);\n var marginLeft = parseFloat(styles.marginLeft);\n\n offsets.top -= borderTopWidth - marginTop;\n offsets.bottom -= borderTopWidth - marginTop;\n offsets.left -= borderLeftWidth - marginLeft;\n offsets.right -= borderLeftWidth - marginLeft;\n\n // Attach marginTop and marginLeft because in some circumstances we may need them\n offsets.marginTop = marginTop;\n offsets.marginLeft = marginLeft;\n }\n\n if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {\n offsets = includeScroll(offsets, parent);\n }\n\n return offsets;\n}\n\nfunction getViewportOffsetRectRelativeToArtbitraryNode(element) {\n var excludeScroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n\n var html = element.ownerDocument.documentElement;\n var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);\n var width = Math.max(html.clientWidth, window.innerWidth || 0);\n var height = Math.max(html.clientHeight, window.innerHeight || 0);\n\n var scrollTop = !excludeScroll ? getScroll(html) : 0;\n var scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0;\n\n var offset = {\n top: scrollTop - relativeOffset.top + relativeOffset.marginTop,\n left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,\n width: width,\n height: height\n };\n\n return getClientRect(offset);\n}\n\n/**\n * Check if the given element is fixed or is inside a fixed parent\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @argument {Element} customContainer\n * @returns {Boolean} answer to \"isFixed?\"\n */\nfunction isFixed(element) {\n var nodeName = element.nodeName;\n if (nodeName === 'BODY' || nodeName === 'HTML') {\n return false;\n }\n if (getStyleComputedProperty(element, 'position') === 'fixed') {\n return true;\n }\n var parentNode = getParentNode(element);\n if (!parentNode) {\n return false;\n }\n return isFixed(parentNode);\n}\n\n/**\n * Finds the first parent of an element that has a transformed property defined\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} first transformed parent or documentElement\n */\n\nfunction getFixedPositionOffsetParent(element) {\n // This check is needed to avoid errors in case one of the elements isn't defined for any reason\n if (!element || !element.parentElement || isIE()) {\n return document.documentElement;\n }\n var el = element.parentElement;\n while (el && getStyleComputedProperty(el, 'transform') === 'none') {\n el = el.parentElement;\n }\n return el || document.documentElement;\n}\n\n/**\n * Computed the boundaries limits and return them\n * @method\n * @memberof Popper.Utils\n * @param {HTMLElement} popper\n * @param {HTMLElement} reference\n * @param {number} padding\n * @param {HTMLElement} boundariesElement - Element used to define the boundaries\n * @param {Boolean} fixedPosition - Is in fixed position mode\n * @returns {Object} Coordinates of the boundaries\n */\nfunction getBoundaries(popper, reference, padding, boundariesElement) {\n var fixedPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;\n\n // NOTE: 1 DOM access here\n\n var boundaries = { top: 0, left: 0 };\n var offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, getReferenceNode(reference));\n\n // Handle viewport case\n if (boundariesElement === 'viewport') {\n boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition);\n } else {\n // Handle other cases based on DOM element used as boundaries\n var boundariesNode = void 0;\n if (boundariesElement === 'scrollParent') {\n boundariesNode = getScrollParent(getParentNode(reference));\n if (boundariesNode.nodeName === 'BODY') {\n boundariesNode = popper.ownerDocument.documentElement;\n }\n } else if (boundariesElement === 'window') {\n boundariesNode = popper.ownerDocument.documentElement;\n } else {\n boundariesNode = boundariesElement;\n }\n\n var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition);\n\n // In case of HTML, we need a different computation\n if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {\n var _getWindowSizes = getWindowSizes(popper.ownerDocument),\n height = _getWindowSizes.height,\n width = _getWindowSizes.width;\n\n boundaries.top += offsets.top - offsets.marginTop;\n boundaries.bottom = height + offsets.top;\n boundaries.left += offsets.left - offsets.marginLeft;\n boundaries.right = width + offsets.left;\n } else {\n // for all the other DOM elements, this one is good\n boundaries = offsets;\n }\n }\n\n // Add paddings\n padding = padding || 0;\n var isPaddingNumber = typeof padding === 'number';\n boundaries.left += isPaddingNumber ? padding : padding.left || 0;\n boundaries.top += isPaddingNumber ? padding : padding.top || 0;\n boundaries.right -= isPaddingNumber ? padding : padding.right || 0;\n boundaries.bottom -= isPaddingNumber ? padding : padding.bottom || 0;\n\n return boundaries;\n}\n\nfunction getArea(_ref) {\n var width = _ref.width,\n height = _ref.height;\n\n return width * height;\n}\n\n/**\n * Utility used to transform the `auto` placement to the placement with more\n * available space.\n * @method\n * @memberof Popper.Utils\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {\n var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;\n\n if (placement.indexOf('auto') === -1) {\n return placement;\n }\n\n var boundaries = getBoundaries(popper, reference, padding, boundariesElement);\n\n var rects = {\n top: {\n width: boundaries.width,\n height: refRect.top - boundaries.top\n },\n right: {\n width: boundaries.right - refRect.right,\n height: boundaries.height\n },\n bottom: {\n width: boundaries.width,\n height: boundaries.bottom - refRect.bottom\n },\n left: {\n width: refRect.left - boundaries.left,\n height: boundaries.height\n }\n };\n\n var sortedAreas = Object.keys(rects).map(function (key) {\n return _extends({\n key: key\n }, rects[key], {\n area: getArea(rects[key])\n });\n }).sort(function (a, b) {\n return b.area - a.area;\n });\n\n var filteredAreas = sortedAreas.filter(function (_ref2) {\n var width = _ref2.width,\n height = _ref2.height;\n return width >= popper.clientWidth && height >= popper.clientHeight;\n });\n\n var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;\n\n var variation = placement.split('-')[1];\n\n return computedPlacement + (variation ? '-' + variation : '');\n}\n\n/**\n * Get offsets to the reference element\n * @method\n * @memberof Popper.Utils\n * @param {Object} state\n * @param {Element} popper - the popper element\n * @param {Element} reference - the reference element (the popper will be relative to this)\n * @param {Element} fixedPosition - is in fixed position mode\n * @returns {Object} An object containing the offsets which will be applied to the popper\n */\nfunction getReferenceOffsets(state, popper, reference) {\n var fixedPosition = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;\n\n var commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, getReferenceNode(reference));\n return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition);\n}\n\n/**\n * Get the outer sizes of the given element (offset size + margins)\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Object} object containing width and height properties\n */\nfunction getOuterSizes(element) {\n var window = element.ownerDocument.defaultView;\n var styles = window.getComputedStyle(element);\n var x = parseFloat(styles.marginTop || 0) + parseFloat(styles.marginBottom || 0);\n var y = parseFloat(styles.marginLeft || 0) + parseFloat(styles.marginRight || 0);\n var result = {\n width: element.offsetWidth + y,\n height: element.offsetHeight + x\n };\n return result;\n}\n\n/**\n * Get the opposite placement of the given one\n * @method\n * @memberof Popper.Utils\n * @argument {String} placement\n * @returns {String} flipped placement\n */\nfunction getOppositePlacement(placement) {\n var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };\n return placement.replace(/left|right|bottom|top/g, function (matched) {\n return hash[matched];\n });\n}\n\n/**\n * Get offsets to the popper\n * @method\n * @memberof Popper.Utils\n * @param {Object} position - CSS position the Popper will get applied\n * @param {HTMLElement} popper - the popper element\n * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)\n * @param {String} placement - one of the valid placement options\n * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper\n */\nfunction getPopperOffsets(popper, referenceOffsets, placement) {\n placement = placement.split('-')[0];\n\n // Get popper node sizes\n var popperRect = getOuterSizes(popper);\n\n // Add position, width and height to our offsets object\n var popperOffsets = {\n width: popperRect.width,\n height: popperRect.height\n };\n\n // depending by the popper placement we have to compute its offsets slightly differently\n var isHoriz = ['right', 'left'].indexOf(placement) !== -1;\n var mainSide = isHoriz ? 'top' : 'left';\n var secondarySide = isHoriz ? 'left' : 'top';\n var measurement = isHoriz ? 'height' : 'width';\n var secondaryMeasurement = !isHoriz ? 'height' : 'width';\n\n popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;\n if (placement === secondarySide) {\n popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];\n } else {\n popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];\n }\n\n return popperOffsets;\n}\n\n/**\n * Mimics the `find` method of Array\n * @method\n * @memberof Popper.Utils\n * @argument {Array} arr\n * @argument prop\n * @argument value\n * @returns index or -1\n */\nfunction find(arr, check) {\n // use native find if supported\n if (Array.prototype.find) {\n return arr.find(check);\n }\n\n // use `filter` to obtain the same behavior of `find`\n return arr.filter(check)[0];\n}\n\n/**\n * Return the index of the matching object\n * @method\n * @memberof Popper.Utils\n * @argument {Array} arr\n * @argument prop\n * @argument value\n * @returns index or -1\n */\nfunction findIndex(arr, prop, value) {\n // use native findIndex if supported\n if (Array.prototype.findIndex) {\n return arr.findIndex(function (cur) {\n return cur[prop] === value;\n });\n }\n\n // use `find` + `indexOf` if `findIndex` isn't supported\n var match = find(arr, function (obj) {\n return obj[prop] === value;\n });\n return arr.indexOf(match);\n}\n\n/**\n * Loop trough the list of modifiers and run them in order,\n * each of them will then edit the data object.\n * @method\n * @memberof Popper.Utils\n * @param {dataObject} data\n * @param {Array} modifiers\n * @param {String} ends - Optional modifier name used as stopper\n * @returns {dataObject}\n */\nfunction runModifiers(modifiers, data, ends) {\n var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));\n\n modifiersToRun.forEach(function (modifier) {\n if (modifier['function']) {\n // eslint-disable-line dot-notation\n console.warn('`modifier.function` is deprecated, use `modifier.fn`!');\n }\n var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation\n if (modifier.enabled && isFunction(fn)) {\n // Add properties to offsets to make them a complete clientRect object\n // we do this before each modifier to make sure the previous one doesn't\n // mess with these values\n data.offsets.popper = getClientRect(data.offsets.popper);\n data.offsets.reference = getClientRect(data.offsets.reference);\n\n data = fn(data, modifier);\n }\n });\n\n return data;\n}\n\n/**\n * Updates the position of the popper, computing the new offsets and applying\n * the new style.
    \n * Prefer `scheduleUpdate` over `update` because of performance reasons.\n * @method\n * @memberof Popper\n */\nfunction update() {\n // if popper is destroyed, don't perform any further update\n if (this.state.isDestroyed) {\n return;\n }\n\n var data = {\n instance: this,\n styles: {},\n arrowStyles: {},\n attributes: {},\n flipped: false,\n offsets: {}\n };\n\n // compute reference element offsets\n data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed);\n\n // compute auto placement, store placement inside the data object,\n // modifiers will be able to edit `placement` if needed\n // and refer to originalPlacement to know the original value\n data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding);\n\n // store the computed placement inside `originalPlacement`\n data.originalPlacement = data.placement;\n\n data.positionFixed = this.options.positionFixed;\n\n // compute the popper offsets\n data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);\n\n data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute';\n\n // run the modifiers\n data = runModifiers(this.modifiers, data);\n\n // the first `update` will call `onCreate` callback\n // the other ones will call `onUpdate` callback\n if (!this.state.isCreated) {\n this.state.isCreated = true;\n this.options.onCreate(data);\n } else {\n this.options.onUpdate(data);\n }\n}\n\n/**\n * Helper used to know if the given modifier is enabled.\n * @method\n * @memberof Popper.Utils\n * @returns {Boolean}\n */\nfunction isModifierEnabled(modifiers, modifierName) {\n return modifiers.some(function (_ref) {\n var name = _ref.name,\n enabled = _ref.enabled;\n return enabled && name === modifierName;\n });\n}\n\n/**\n * Get the prefixed supported property name\n * @method\n * @memberof Popper.Utils\n * @argument {String} property (camelCase)\n * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)\n */\nfunction getSupportedPropertyName(property) {\n var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];\n var upperProp = property.charAt(0).toUpperCase() + property.slice(1);\n\n for (var i = 0; i < prefixes.length; i++) {\n var prefix = prefixes[i];\n var toCheck = prefix ? '' + prefix + upperProp : property;\n if (typeof document.body.style[toCheck] !== 'undefined') {\n return toCheck;\n }\n }\n return null;\n}\n\n/**\n * Destroys the popper.\n * @method\n * @memberof Popper\n */\nfunction destroy() {\n this.state.isDestroyed = true;\n\n // touch DOM only if `applyStyle` modifier is enabled\n if (isModifierEnabled(this.modifiers, 'applyStyle')) {\n this.popper.removeAttribute('x-placement');\n this.popper.style.position = '';\n this.popper.style.top = '';\n this.popper.style.left = '';\n this.popper.style.right = '';\n this.popper.style.bottom = '';\n this.popper.style.willChange = '';\n this.popper.style[getSupportedPropertyName('transform')] = '';\n }\n\n this.disableEventListeners();\n\n // remove the popper if user explicitly asked for the deletion on destroy\n // do not use `remove` because IE11 doesn't support it\n if (this.options.removeOnDestroy) {\n this.popper.parentNode.removeChild(this.popper);\n }\n return this;\n}\n\n/**\n * Get the window associated with the element\n * @argument {Element} element\n * @returns {Window}\n */\nfunction getWindow(element) {\n var ownerDocument = element.ownerDocument;\n return ownerDocument ? ownerDocument.defaultView : window;\n}\n\nfunction attachToScrollParents(scrollParent, event, callback, scrollParents) {\n var isBody = scrollParent.nodeName === 'BODY';\n var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;\n target.addEventListener(event, callback, { passive: true });\n\n if (!isBody) {\n attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);\n }\n scrollParents.push(target);\n}\n\n/**\n * Setup needed event listeners used to update the popper position\n * @method\n * @memberof Popper.Utils\n * @private\n */\nfunction setupEventListeners(reference, options, state, updateBound) {\n // Resize event listener on window\n state.updateBound = updateBound;\n getWindow(reference).addEventListener('resize', state.updateBound, { passive: true });\n\n // Scroll event listener on scroll parents\n var scrollElement = getScrollParent(reference);\n attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);\n state.scrollElement = scrollElement;\n state.eventsEnabled = true;\n\n return state;\n}\n\n/**\n * It will add resize/scroll events and start recalculating\n * position of the popper element when they are triggered.\n * @method\n * @memberof Popper\n */\nfunction enableEventListeners() {\n if (!this.state.eventsEnabled) {\n this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);\n }\n}\n\n/**\n * Remove event listeners used to update the popper position\n * @method\n * @memberof Popper.Utils\n * @private\n */\nfunction removeEventListeners(reference, state) {\n // Remove resize event listener on window\n getWindow(reference).removeEventListener('resize', state.updateBound);\n\n // Remove scroll event listener on scroll parents\n state.scrollParents.forEach(function (target) {\n target.removeEventListener('scroll', state.updateBound);\n });\n\n // Reset state\n state.updateBound = null;\n state.scrollParents = [];\n state.scrollElement = null;\n state.eventsEnabled = false;\n return state;\n}\n\n/**\n * It will remove resize/scroll events and won't recalculate popper position\n * when they are triggered. It also won't trigger `onUpdate` callback anymore,\n * unless you call `update` method manually.\n * @method\n * @memberof Popper\n */\nfunction disableEventListeners() {\n if (this.state.eventsEnabled) {\n cancelAnimationFrame(this.scheduleUpdate);\n this.state = removeEventListeners(this.reference, this.state);\n }\n}\n\n/**\n * Tells if a given input is a number\n * @method\n * @memberof Popper.Utils\n * @param {*} input to check\n * @return {Boolean}\n */\nfunction isNumeric(n) {\n return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);\n}\n\n/**\n * Set the style to the given popper\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element - Element to apply the style to\n * @argument {Object} styles\n * Object with a list of properties and values which will be applied to the element\n */\nfunction setStyles(element, styles) {\n Object.keys(styles).forEach(function (prop) {\n var unit = '';\n // add unit if the value is numeric and is one of the following\n if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {\n unit = 'px';\n }\n element.style[prop] = styles[prop] + unit;\n });\n}\n\n/**\n * Set the attributes to the given popper\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element - Element to apply the attributes to\n * @argument {Object} styles\n * Object with a list of properties and values which will be applied to the element\n */\nfunction setAttributes(element, attributes) {\n Object.keys(attributes).forEach(function (prop) {\n var value = attributes[prop];\n if (value !== false) {\n element.setAttribute(prop, attributes[prop]);\n } else {\n element.removeAttribute(prop);\n }\n });\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} data.styles - List of style properties - values to apply to popper element\n * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The same data object\n */\nfunction applyStyle(data) {\n // any property present in `data.styles` will be applied to the popper,\n // in this way we can make the 3rd party modifiers add custom styles to it\n // Be aware, modifiers could override the properties defined in the previous\n // lines of this modifier!\n setStyles(data.instance.popper, data.styles);\n\n // any property present in `data.attributes` will be applied to the popper,\n // they will be set as HTML attributes of the element\n setAttributes(data.instance.popper, data.attributes);\n\n // if arrowElement is defined and arrowStyles has some properties\n if (data.arrowElement && Object.keys(data.arrowStyles).length) {\n setStyles(data.arrowElement, data.arrowStyles);\n }\n\n return data;\n}\n\n/**\n * Set the x-placement attribute before everything else because it could be used\n * to add margins to the popper margins needs to be calculated to get the\n * correct popper offsets.\n * @method\n * @memberof Popper.modifiers\n * @param {HTMLElement} reference - The reference element used to position the popper\n * @param {HTMLElement} popper - The HTML element used as popper\n * @param {Object} options - Popper.js options\n */\nfunction applyStyleOnLoad(reference, popper, options, modifierOptions, state) {\n // compute reference element offsets\n var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed);\n\n // compute auto placement, store placement inside the data object,\n // modifiers will be able to edit `placement` if needed\n // and refer to originalPlacement to know the original value\n var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);\n\n popper.setAttribute('x-placement', placement);\n\n // Apply `position` to popper before anything else because\n // without the position applied we can't guarantee correct computations\n setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' });\n\n return options;\n}\n\n/**\n * @function\n * @memberof Popper.Utils\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Boolean} shouldRound - If the offsets should be rounded at all\n * @returns {Object} The popper's position offsets rounded\n *\n * The tale of pixel-perfect positioning. It's still not 100% perfect, but as\n * good as it can be within reason.\n * Discussion here: https://github.com/FezVrasta/popper.js/pull/715\n *\n * Low DPI screens cause a popper to be blurry if not using full pixels (Safari\n * as well on High DPI screens).\n *\n * Firefox prefers no rounding for positioning and does not have blurriness on\n * high DPI screens.\n *\n * Only horizontal placement and left/right values need to be considered.\n */\nfunction getRoundedOffsets(data, shouldRound) {\n var _data$offsets = data.offsets,\n popper = _data$offsets.popper,\n reference = _data$offsets.reference;\n var round = Math.round,\n floor = Math.floor;\n\n var noRound = function noRound(v) {\n return v;\n };\n\n var referenceWidth = round(reference.width);\n var popperWidth = round(popper.width);\n\n var isVertical = ['left', 'right'].indexOf(data.placement) !== -1;\n var isVariation = data.placement.indexOf('-') !== -1;\n var sameWidthParity = referenceWidth % 2 === popperWidth % 2;\n var bothOddWidth = referenceWidth % 2 === 1 && popperWidth % 2 === 1;\n\n var horizontalToInteger = !shouldRound ? noRound : isVertical || isVariation || sameWidthParity ? round : floor;\n var verticalToInteger = !shouldRound ? noRound : round;\n\n return {\n left: horizontalToInteger(bothOddWidth && !isVariation && shouldRound ? popper.left - 1 : popper.left),\n top: verticalToInteger(popper.top),\n bottom: verticalToInteger(popper.bottom),\n right: horizontalToInteger(popper.right)\n };\n}\n\nvar isFirefox = isBrowser && /Firefox/i.test(navigator.userAgent);\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction computeStyle(data, options) {\n var x = options.x,\n y = options.y;\n var popper = data.offsets.popper;\n\n // Remove this legacy support in Popper.js v2\n\n var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {\n return modifier.name === 'applyStyle';\n }).gpuAcceleration;\n if (legacyGpuAccelerationOption !== undefined) {\n console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');\n }\n var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;\n\n var offsetParent = getOffsetParent(data.instance.popper);\n var offsetParentRect = getBoundingClientRect(offsetParent);\n\n // Styles\n var styles = {\n position: popper.position\n };\n\n var offsets = getRoundedOffsets(data, window.devicePixelRatio < 2 || !isFirefox);\n\n var sideA = x === 'bottom' ? 'top' : 'bottom';\n var sideB = y === 'right' ? 'left' : 'right';\n\n // if gpuAcceleration is set to `true` and transform is supported,\n // we use `translate3d` to apply the position to the popper we\n // automatically use the supported prefixed version if needed\n var prefixedProperty = getSupportedPropertyName('transform');\n\n // now, let's make a step back and look at this code closely (wtf?)\n // If the content of the popper grows once it's been positioned, it\n // may happen that the popper gets misplaced because of the new content\n // overflowing its reference element\n // To avoid this problem, we provide two options (x and y), which allow\n // the consumer to define the offset origin.\n // If we position a popper on top of a reference element, we can set\n // `x` to `top` to make the popper grow towards its top instead of\n // its bottom.\n var left = void 0,\n top = void 0;\n if (sideA === 'bottom') {\n // when offsetParent is the positioning is relative to the bottom of the screen (excluding the scrollbar)\n // and not the bottom of the html element\n if (offsetParent.nodeName === 'HTML') {\n top = -offsetParent.clientHeight + offsets.bottom;\n } else {\n top = -offsetParentRect.height + offsets.bottom;\n }\n } else {\n top = offsets.top;\n }\n if (sideB === 'right') {\n if (offsetParent.nodeName === 'HTML') {\n left = -offsetParent.clientWidth + offsets.right;\n } else {\n left = -offsetParentRect.width + offsets.right;\n }\n } else {\n left = offsets.left;\n }\n if (gpuAcceleration && prefixedProperty) {\n styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';\n styles[sideA] = 0;\n styles[sideB] = 0;\n styles.willChange = 'transform';\n } else {\n // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties\n var invertTop = sideA === 'bottom' ? -1 : 1;\n var invertLeft = sideB === 'right' ? -1 : 1;\n styles[sideA] = top * invertTop;\n styles[sideB] = left * invertLeft;\n styles.willChange = sideA + ', ' + sideB;\n }\n\n // Attributes\n var attributes = {\n 'x-placement': data.placement\n };\n\n // Update `data` attributes, styles and arrowStyles\n data.attributes = _extends({}, attributes, data.attributes);\n data.styles = _extends({}, styles, data.styles);\n data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);\n\n return data;\n}\n\n/**\n * Helper used to know if the given modifier depends from another one.
    \n * It checks if the needed modifier is listed and enabled.\n * @method\n * @memberof Popper.Utils\n * @param {Array} modifiers - list of modifiers\n * @param {String} requestingName - name of requesting modifier\n * @param {String} requestedName - name of requested modifier\n * @returns {Boolean}\n */\nfunction isModifierRequired(modifiers, requestingName, requestedName) {\n var requesting = find(modifiers, function (_ref) {\n var name = _ref.name;\n return name === requestingName;\n });\n\n var isRequired = !!requesting && modifiers.some(function (modifier) {\n return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;\n });\n\n if (!isRequired) {\n var _requesting = '`' + requestingName + '`';\n var requested = '`' + requestedName + '`';\n console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');\n }\n return isRequired;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction arrow(data, options) {\n var _data$offsets$arrow;\n\n // arrow depends on keepTogether in order to work\n if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {\n return data;\n }\n\n var arrowElement = options.element;\n\n // if arrowElement is a string, suppose it's a CSS selector\n if (typeof arrowElement === 'string') {\n arrowElement = data.instance.popper.querySelector(arrowElement);\n\n // if arrowElement is not found, don't run the modifier\n if (!arrowElement) {\n return data;\n }\n } else {\n // if the arrowElement isn't a query selector we must check that the\n // provided DOM node is child of its popper node\n if (!data.instance.popper.contains(arrowElement)) {\n console.warn('WARNING: `arrow.element` must be child of its popper element!');\n return data;\n }\n }\n\n var placement = data.placement.split('-')[0];\n var _data$offsets = data.offsets,\n popper = _data$offsets.popper,\n reference = _data$offsets.reference;\n\n var isVertical = ['left', 'right'].indexOf(placement) !== -1;\n\n var len = isVertical ? 'height' : 'width';\n var sideCapitalized = isVertical ? 'Top' : 'Left';\n var side = sideCapitalized.toLowerCase();\n var altSide = isVertical ? 'left' : 'top';\n var opSide = isVertical ? 'bottom' : 'right';\n var arrowElementSize = getOuterSizes(arrowElement)[len];\n\n //\n // extends keepTogether behavior making sure the popper and its\n // reference have enough pixels in conjunction\n //\n\n // top/left side\n if (reference[opSide] - arrowElementSize < popper[side]) {\n data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);\n }\n // bottom/right side\n if (reference[side] + arrowElementSize > popper[opSide]) {\n data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];\n }\n data.offsets.popper = getClientRect(data.offsets.popper);\n\n // compute center of the popper\n var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;\n\n // Compute the sideValue using the updated popper offsets\n // take popper margin in account because we don't have this info available\n var css = getStyleComputedProperty(data.instance.popper);\n var popperMarginSide = parseFloat(css['margin' + sideCapitalized]);\n var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width']);\n var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;\n\n // prevent arrowElement from being placed not contiguously to its popper\n sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);\n\n data.arrowElement = arrowElement;\n data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow);\n\n return data;\n}\n\n/**\n * Get the opposite placement variation of the given one\n * @method\n * @memberof Popper.Utils\n * @argument {String} placement variation\n * @returns {String} flipped placement variation\n */\nfunction getOppositeVariation(variation) {\n if (variation === 'end') {\n return 'start';\n } else if (variation === 'start') {\n return 'end';\n }\n return variation;\n}\n\n/**\n * List of accepted placements to use as values of the `placement` option.
    \n * Valid placements are:\n * - `auto`\n * - `top`\n * - `right`\n * - `bottom`\n * - `left`\n *\n * Each placement can have a variation from this list:\n * - `-start`\n * - `-end`\n *\n * Variations are interpreted easily if you think of them as the left to right\n * written languages. Horizontally (`top` and `bottom`), `start` is left and `end`\n * is right.
    \n * Vertically (`left` and `right`), `start` is top and `end` is bottom.\n *\n * Some valid examples are:\n * - `top-end` (on top of reference, right aligned)\n * - `right-start` (on right of reference, top aligned)\n * - `bottom` (on bottom, centered)\n * - `auto-end` (on the side with more space available, alignment depends by placement)\n *\n * @static\n * @type {Array}\n * @enum {String}\n * @readonly\n * @method placements\n * @memberof Popper\n */\nvar placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start'];\n\n// Get rid of `auto` `auto-start` and `auto-end`\nvar validPlacements = placements.slice(3);\n\n/**\n * Given an initial placement, returns all the subsequent placements\n * clockwise (or counter-clockwise).\n *\n * @method\n * @memberof Popper.Utils\n * @argument {String} placement - A valid placement (it accepts variations)\n * @argument {Boolean} counter - Set to true to walk the placements counterclockwise\n * @returns {Array} placements including their variations\n */\nfunction clockwise(placement) {\n var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n\n var index = validPlacements.indexOf(placement);\n var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));\n return counter ? arr.reverse() : arr;\n}\n\nvar BEHAVIORS = {\n FLIP: 'flip',\n CLOCKWISE: 'clockwise',\n COUNTERCLOCKWISE: 'counterclockwise'\n};\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction flip(data, options) {\n // if `inner` modifier is enabled, we can't use the `flip` modifier\n if (isModifierEnabled(data.instance.modifiers, 'inner')) {\n return data;\n }\n\n if (data.flipped && data.placement === data.originalPlacement) {\n // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides\n return data;\n }\n\n var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed);\n\n var placement = data.placement.split('-')[0];\n var placementOpposite = getOppositePlacement(placement);\n var variation = data.placement.split('-')[1] || '';\n\n var flipOrder = [];\n\n switch (options.behavior) {\n case BEHAVIORS.FLIP:\n flipOrder = [placement, placementOpposite];\n break;\n case BEHAVIORS.CLOCKWISE:\n flipOrder = clockwise(placement);\n break;\n case BEHAVIORS.COUNTERCLOCKWISE:\n flipOrder = clockwise(placement, true);\n break;\n default:\n flipOrder = options.behavior;\n }\n\n flipOrder.forEach(function (step, index) {\n if (placement !== step || flipOrder.length === index + 1) {\n return data;\n }\n\n placement = data.placement.split('-')[0];\n placementOpposite = getOppositePlacement(placement);\n\n var popperOffsets = data.offsets.popper;\n var refOffsets = data.offsets.reference;\n\n // using floor because the reference offsets may contain decimals we are not going to consider here\n var floor = Math.floor;\n var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom);\n\n var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);\n var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);\n var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);\n var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);\n\n var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;\n\n // flip the variation if required\n var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;\n\n // flips variation if reference element overflows boundaries\n var flippedVariationByRef = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom);\n\n // flips variation if popper content overflows boundaries\n var flippedVariationByContent = !!options.flipVariationsByContent && (isVertical && variation === 'start' && overflowsRight || isVertical && variation === 'end' && overflowsLeft || !isVertical && variation === 'start' && overflowsBottom || !isVertical && variation === 'end' && overflowsTop);\n\n var flippedVariation = flippedVariationByRef || flippedVariationByContent;\n\n if (overlapsRef || overflowsBoundaries || flippedVariation) {\n // this boolean to detect any flip loop\n data.flipped = true;\n\n if (overlapsRef || overflowsBoundaries) {\n placement = flipOrder[index + 1];\n }\n\n if (flippedVariation) {\n variation = getOppositeVariation(variation);\n }\n\n data.placement = placement + (variation ? '-' + variation : '');\n\n // this object contains `position`, we want to preserve it along with\n // any additional property we may add in the future\n data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));\n\n data = runModifiers(data.instance.modifiers, data, 'flip');\n }\n });\n return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction keepTogether(data) {\n var _data$offsets = data.offsets,\n popper = _data$offsets.popper,\n reference = _data$offsets.reference;\n\n var placement = data.placement.split('-')[0];\n var floor = Math.floor;\n var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;\n var side = isVertical ? 'right' : 'bottom';\n var opSide = isVertical ? 'left' : 'top';\n var measurement = isVertical ? 'width' : 'height';\n\n if (popper[side] < floor(reference[opSide])) {\n data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];\n }\n if (popper[opSide] > floor(reference[side])) {\n data.offsets.popper[opSide] = floor(reference[side]);\n }\n\n return data;\n}\n\n/**\n * Converts a string containing value + unit into a px value number\n * @function\n * @memberof {modifiers~offset}\n * @private\n * @argument {String} str - Value + unit string\n * @argument {String} measurement - `height` or `width`\n * @argument {Object} popperOffsets\n * @argument {Object} referenceOffsets\n * @returns {Number|String}\n * Value in pixels, or original string if no values were extracted\n */\nfunction toValue(str, measurement, popperOffsets, referenceOffsets) {\n // separate value from unit\n var split = str.match(/((?:\\-|\\+)?\\d*\\.?\\d*)(.*)/);\n var value = +split[1];\n var unit = split[2];\n\n // If it's not a number it's an operator, I guess\n if (!value) {\n return str;\n }\n\n if (unit.indexOf('%') === 0) {\n var element = void 0;\n switch (unit) {\n case '%p':\n element = popperOffsets;\n break;\n case '%':\n case '%r':\n default:\n element = referenceOffsets;\n }\n\n var rect = getClientRect(element);\n return rect[measurement] / 100 * value;\n } else if (unit === 'vh' || unit === 'vw') {\n // if is a vh or vw, we calculate the size based on the viewport\n var size = void 0;\n if (unit === 'vh') {\n size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);\n } else {\n size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);\n }\n return size / 100 * value;\n } else {\n // if is an explicit pixel unit, we get rid of the unit and keep the value\n // if is an implicit unit, it's px, and we return just the value\n return value;\n }\n}\n\n/**\n * Parse an `offset` string to extrapolate `x` and `y` numeric offsets.\n * @function\n * @memberof {modifiers~offset}\n * @private\n * @argument {String} offset\n * @argument {Object} popperOffsets\n * @argument {Object} referenceOffsets\n * @argument {String} basePlacement\n * @returns {Array} a two cells array with x and y offsets in numbers\n */\nfunction parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {\n var offsets = [0, 0];\n\n // Use height if placement is left or right and index is 0 otherwise use width\n // in this way the first offset will use an axis and the second one\n // will use the other one\n var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;\n\n // Split the offset string to obtain a list of values and operands\n // The regex addresses values with the plus or minus sign in front (+10, -20, etc)\n var fragments = offset.split(/(\\+|\\-)/).map(function (frag) {\n return frag.trim();\n });\n\n // Detect if the offset string contains a pair of values or a single one\n // they could be separated by comma or space\n var divider = fragments.indexOf(find(fragments, function (frag) {\n return frag.search(/,|\\s/) !== -1;\n }));\n\n if (fragments[divider] && fragments[divider].indexOf(',') === -1) {\n console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');\n }\n\n // If divider is found, we divide the list of values and operands to divide\n // them by ofset X and Y.\n var splitRegex = /\\s*,\\s*|\\s+/;\n var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments];\n\n // Convert the values with units to absolute pixels to allow our computations\n ops = ops.map(function (op, index) {\n // Most of the units rely on the orientation of the popper\n var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';\n var mergeWithPrevious = false;\n return op\n // This aggregates any `+` or `-` sign that aren't considered operators\n // e.g.: 10 + +5 => [10, +, +5]\n .reduce(function (a, b) {\n if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {\n a[a.length - 1] = b;\n mergeWithPrevious = true;\n return a;\n } else if (mergeWithPrevious) {\n a[a.length - 1] += b;\n mergeWithPrevious = false;\n return a;\n } else {\n return a.concat(b);\n }\n }, [])\n // Here we convert the string values into number values (in px)\n .map(function (str) {\n return toValue(str, measurement, popperOffsets, referenceOffsets);\n });\n });\n\n // Loop trough the offsets arrays and execute the operations\n ops.forEach(function (op, index) {\n op.forEach(function (frag, index2) {\n if (isNumeric(frag)) {\n offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);\n }\n });\n });\n return offsets;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @argument {Number|String} options.offset=0\n * The offset value as described in the modifier description\n * @returns {Object} The data object, properly modified\n */\nfunction offset(data, _ref) {\n var offset = _ref.offset;\n var placement = data.placement,\n _data$offsets = data.offsets,\n popper = _data$offsets.popper,\n reference = _data$offsets.reference;\n\n var basePlacement = placement.split('-')[0];\n\n var offsets = void 0;\n if (isNumeric(+offset)) {\n offsets = [+offset, 0];\n } else {\n offsets = parseOffset(offset, popper, reference, basePlacement);\n }\n\n if (basePlacement === 'left') {\n popper.top += offsets[0];\n popper.left -= offsets[1];\n } else if (basePlacement === 'right') {\n popper.top += offsets[0];\n popper.left += offsets[1];\n } else if (basePlacement === 'top') {\n popper.left += offsets[0];\n popper.top -= offsets[1];\n } else if (basePlacement === 'bottom') {\n popper.left += offsets[0];\n popper.top += offsets[1];\n }\n\n data.popper = popper;\n return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction preventOverflow(data, options) {\n var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);\n\n // If offsetParent is the reference element, we really want to\n // go one step up and use the next offsetParent as reference to\n // avoid to make this modifier completely useless and look like broken\n if (data.instance.reference === boundariesElement) {\n boundariesElement = getOffsetParent(boundariesElement);\n }\n\n // NOTE: DOM access here\n // resets the popper's position so that the document size can be calculated excluding\n // the size of the popper element itself\n var transformProp = getSupportedPropertyName('transform');\n var popperStyles = data.instance.popper.style; // assignment to help minification\n var top = popperStyles.top,\n left = popperStyles.left,\n transform = popperStyles[transformProp];\n\n popperStyles.top = '';\n popperStyles.left = '';\n popperStyles[transformProp] = '';\n\n var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed);\n\n // NOTE: DOM access here\n // restores the original style properties after the offsets have been computed\n popperStyles.top = top;\n popperStyles.left = left;\n popperStyles[transformProp] = transform;\n\n options.boundaries = boundaries;\n\n var order = options.priority;\n var popper = data.offsets.popper;\n\n var check = {\n primary: function primary(placement) {\n var value = popper[placement];\n if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {\n value = Math.max(popper[placement], boundaries[placement]);\n }\n return defineProperty({}, placement, value);\n },\n secondary: function secondary(placement) {\n var mainSide = placement === 'right' ? 'left' : 'top';\n var value = popper[mainSide];\n if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {\n value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));\n }\n return defineProperty({}, mainSide, value);\n }\n };\n\n order.forEach(function (placement) {\n var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';\n popper = _extends({}, popper, check[side](placement));\n });\n\n data.offsets.popper = popper;\n\n return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction shift(data) {\n var placement = data.placement;\n var basePlacement = placement.split('-')[0];\n var shiftvariation = placement.split('-')[1];\n\n // if shift shiftvariation is specified, run the modifier\n if (shiftvariation) {\n var _data$offsets = data.offsets,\n reference = _data$offsets.reference,\n popper = _data$offsets.popper;\n\n var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;\n var side = isVertical ? 'left' : 'top';\n var measurement = isVertical ? 'width' : 'height';\n\n var shiftOffsets = {\n start: defineProperty({}, side, reference[side]),\n end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])\n };\n\n data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);\n }\n\n return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction hide(data) {\n if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {\n return data;\n }\n\n var refRect = data.offsets.reference;\n var bound = find(data.instance.modifiers, function (modifier) {\n return modifier.name === 'preventOverflow';\n }).boundaries;\n\n if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {\n // Avoid unnecessary DOM access if visibility hasn't changed\n if (data.hide === true) {\n return data;\n }\n\n data.hide = true;\n data.attributes['x-out-of-boundaries'] = '';\n } else {\n // Avoid unnecessary DOM access if visibility hasn't changed\n if (data.hide === false) {\n return data;\n }\n\n data.hide = false;\n data.attributes['x-out-of-boundaries'] = false;\n }\n\n return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction inner(data) {\n var placement = data.placement;\n var basePlacement = placement.split('-')[0];\n var _data$offsets = data.offsets,\n popper = _data$offsets.popper,\n reference = _data$offsets.reference;\n\n var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;\n\n var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;\n\n popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);\n\n data.placement = getOppositePlacement(placement);\n data.offsets.popper = getClientRect(popper);\n\n return data;\n}\n\n/**\n * Modifier function, each modifier can have a function of this type assigned\n * to its `fn` property.
    \n * These functions will be called on each update, this means that you must\n * make sure they are performant enough to avoid performance bottlenecks.\n *\n * @function ModifierFn\n * @argument {dataObject} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {dataObject} The data object, properly modified\n */\n\n/**\n * Modifiers are plugins used to alter the behavior of your poppers.
    \n * Popper.js uses a set of 9 modifiers to provide all the basic functionalities\n * needed by the library.\n *\n * Usually you don't want to override the `order`, `fn` and `onLoad` props.\n * All the other properties are configurations that could be tweaked.\n * @namespace modifiers\n */\nvar modifiers = {\n /**\n * Modifier used to shift the popper on the start or end of its reference\n * element.
    \n * It will read the variation of the `placement` property.
    \n * It can be one either `-end` or `-start`.\n * @memberof modifiers\n * @inner\n */\n shift: {\n /** @prop {number} order=100 - Index used to define the order of execution */\n order: 100,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: shift\n },\n\n /**\n * The `offset` modifier can shift your popper on both its axis.\n *\n * It accepts the following units:\n * - `px` or unit-less, interpreted as pixels\n * - `%` or `%r`, percentage relative to the length of the reference element\n * - `%p`, percentage relative to the length of the popper element\n * - `vw`, CSS viewport width unit\n * - `vh`, CSS viewport height unit\n *\n * For length is intended the main axis relative to the placement of the popper.
    \n * This means that if the placement is `top` or `bottom`, the length will be the\n * `width`. In case of `left` or `right`, it will be the `height`.\n *\n * You can provide a single value (as `Number` or `String`), or a pair of values\n * as `String` divided by a comma or one (or more) white spaces.
    \n * The latter is a deprecated method because it leads to confusion and will be\n * removed in v2.
    \n * Additionally, it accepts additions and subtractions between different units.\n * Note that multiplications and divisions aren't supported.\n *\n * Valid examples are:\n * ```\n * 10\n * '10%'\n * '10, 10'\n * '10%, 10'\n * '10 + 10%'\n * '10 - 5vh + 3%'\n * '-10px + 5vh, 5px - 6%'\n * ```\n * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap\n * > with their reference element, unfortunately, you will have to disable the `flip` modifier.\n * > You can read more on this at this [issue](https://github.com/FezVrasta/popper.js/issues/373).\n *\n * @memberof modifiers\n * @inner\n */\n offset: {\n /** @prop {number} order=200 - Index used to define the order of execution */\n order: 200,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: offset,\n /** @prop {Number|String} offset=0\n * The offset value as described in the modifier description\n */\n offset: 0\n },\n\n /**\n * Modifier used to prevent the popper from being positioned outside the boundary.\n *\n * A scenario exists where the reference itself is not within the boundaries.
    \n * We can say it has \"escaped the boundaries\" — or just \"escaped\".
    \n * In this case we need to decide whether the popper should either:\n *\n * - detach from the reference and remain \"trapped\" in the boundaries, or\n * - if it should ignore the boundary and \"escape with its reference\"\n *\n * When `escapeWithReference` is set to`true` and reference is completely\n * outside its boundaries, the popper will overflow (or completely leave)\n * the boundaries in order to remain attached to the edge of the reference.\n *\n * @memberof modifiers\n * @inner\n */\n preventOverflow: {\n /** @prop {number} order=300 - Index used to define the order of execution */\n order: 300,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: preventOverflow,\n /**\n * @prop {Array} [priority=['left','right','top','bottom']]\n * Popper will try to prevent overflow following these priorities by default,\n * then, it could overflow on the left and on top of the `boundariesElement`\n */\n priority: ['left', 'right', 'top', 'bottom'],\n /**\n * @prop {number} padding=5\n * Amount of pixel used to define a minimum distance between the boundaries\n * and the popper. This makes sure the popper always has a little padding\n * between the edges of its container\n */\n padding: 5,\n /**\n * @prop {String|HTMLElement} boundariesElement='scrollParent'\n * Boundaries used by the modifier. Can be `scrollParent`, `window`,\n * `viewport` or any DOM element.\n */\n boundariesElement: 'scrollParent'\n },\n\n /**\n * Modifier used to make sure the reference and its popper stay near each other\n * without leaving any gap between the two. Especially useful when the arrow is\n * enabled and you want to ensure that it points to its reference element.\n * It cares only about the first axis. You can still have poppers with margin\n * between the popper and its reference element.\n * @memberof modifiers\n * @inner\n */\n keepTogether: {\n /** @prop {number} order=400 - Index used to define the order of execution */\n order: 400,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: keepTogether\n },\n\n /**\n * This modifier is used to move the `arrowElement` of the popper to make\n * sure it is positioned between the reference element and its popper element.\n * It will read the outer size of the `arrowElement` node to detect how many\n * pixels of conjunction are needed.\n *\n * It has no effect if no `arrowElement` is provided.\n * @memberof modifiers\n * @inner\n */\n arrow: {\n /** @prop {number} order=500 - Index used to define the order of execution */\n order: 500,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: arrow,\n /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */\n element: '[x-arrow]'\n },\n\n /**\n * Modifier used to flip the popper's placement when it starts to overlap its\n * reference element.\n *\n * Requires the `preventOverflow` modifier before it in order to work.\n *\n * **NOTE:** this modifier will interrupt the current update cycle and will\n * restart it if it detects the need to flip the placement.\n * @memberof modifiers\n * @inner\n */\n flip: {\n /** @prop {number} order=600 - Index used to define the order of execution */\n order: 600,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: flip,\n /**\n * @prop {String|Array} behavior='flip'\n * The behavior used to change the popper's placement. It can be one of\n * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid\n * placements (with optional variations)\n */\n behavior: 'flip',\n /**\n * @prop {number} padding=5\n * The popper will flip if it hits the edges of the `boundariesElement`\n */\n padding: 5,\n /**\n * @prop {String|HTMLElement} boundariesElement='viewport'\n * The element which will define the boundaries of the popper position.\n * The popper will never be placed outside of the defined boundaries\n * (except if `keepTogether` is enabled)\n */\n boundariesElement: 'viewport',\n /**\n * @prop {Boolean} flipVariations=false\n * The popper will switch placement variation between `-start` and `-end` when\n * the reference element overlaps its boundaries.\n *\n * The original placement should have a set variation.\n */\n flipVariations: false,\n /**\n * @prop {Boolean} flipVariationsByContent=false\n * The popper will switch placement variation between `-start` and `-end` when\n * the popper element overlaps its reference boundaries.\n *\n * The original placement should have a set variation.\n */\n flipVariationsByContent: false\n },\n\n /**\n * Modifier used to make the popper flow toward the inner of the reference element.\n * By default, when this modifier is disabled, the popper will be placed outside\n * the reference element.\n * @memberof modifiers\n * @inner\n */\n inner: {\n /** @prop {number} order=700 - Index used to define the order of execution */\n order: 700,\n /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */\n enabled: false,\n /** @prop {ModifierFn} */\n fn: inner\n },\n\n /**\n * Modifier used to hide the popper when its reference element is outside of the\n * popper boundaries. It will set a `x-out-of-boundaries` attribute which can\n * be used to hide with a CSS selector the popper when its reference is\n * out of boundaries.\n *\n * Requires the `preventOverflow` modifier before it in order to work.\n * @memberof modifiers\n * @inner\n */\n hide: {\n /** @prop {number} order=800 - Index used to define the order of execution */\n order: 800,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: hide\n },\n\n /**\n * Computes the style that will be applied to the popper element to gets\n * properly positioned.\n *\n * Note that this modifier will not touch the DOM, it just prepares the styles\n * so that `applyStyle` modifier can apply it. This separation is useful\n * in case you need to replace `applyStyle` with a custom implementation.\n *\n * This modifier has `850` as `order` value to maintain backward compatibility\n * with previous versions of Popper.js. Expect the modifiers ordering method\n * to change in future major versions of the library.\n *\n * @memberof modifiers\n * @inner\n */\n computeStyle: {\n /** @prop {number} order=850 - Index used to define the order of execution */\n order: 850,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: computeStyle,\n /**\n * @prop {Boolean} gpuAcceleration=true\n * If true, it uses the CSS 3D transformation to position the popper.\n * Otherwise, it will use the `top` and `left` properties\n */\n gpuAcceleration: true,\n /**\n * @prop {string} [x='bottom']\n * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.\n * Change this if your popper should grow in a direction different from `bottom`\n */\n x: 'bottom',\n /**\n * @prop {string} [x='left']\n * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.\n * Change this if your popper should grow in a direction different from `right`\n */\n y: 'right'\n },\n\n /**\n * Applies the computed styles to the popper element.\n *\n * All the DOM manipulations are limited to this modifier. This is useful in case\n * you want to integrate Popper.js inside a framework or view library and you\n * want to delegate all the DOM manipulations to it.\n *\n * Note that if you disable this modifier, you must make sure the popper element\n * has its position set to `absolute` before Popper.js can do its work!\n *\n * Just disable this modifier and define your own to achieve the desired effect.\n *\n * @memberof modifiers\n * @inner\n */\n applyStyle: {\n /** @prop {number} order=900 - Index used to define the order of execution */\n order: 900,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: applyStyle,\n /** @prop {Function} */\n onLoad: applyStyleOnLoad,\n /**\n * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier\n * @prop {Boolean} gpuAcceleration=true\n * If true, it uses the CSS 3D transformation to position the popper.\n * Otherwise, it will use the `top` and `left` properties\n */\n gpuAcceleration: undefined\n }\n};\n\n/**\n * The `dataObject` is an object containing all the information used by Popper.js.\n * This object is passed to modifiers and to the `onCreate` and `onUpdate` callbacks.\n * @name dataObject\n * @property {Object} data.instance The Popper.js instance\n * @property {String} data.placement Placement applied to popper\n * @property {String} data.originalPlacement Placement originally defined on init\n * @property {Boolean} data.flipped True if popper has been flipped by flip modifier\n * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper\n * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier\n * @property {Object} data.styles Any CSS property defined here will be applied to the popper. It expects the JavaScript nomenclature (eg. `marginBottom`)\n * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow. It expects the JavaScript nomenclature (eg. `marginBottom`)\n * @property {Object} data.boundaries Offsets of the popper boundaries\n * @property {Object} data.offsets The measurements of popper, reference and arrow elements\n * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values\n * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values\n * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0\n */\n\n/**\n * Default options provided to Popper.js constructor.
    \n * These can be overridden using the `options` argument of Popper.js.
    \n * To override an option, simply pass an object with the same\n * structure of the `options` object, as the 3rd argument. For example:\n * ```\n * new Popper(ref, pop, {\n * modifiers: {\n * preventOverflow: { enabled: false }\n * }\n * })\n * ```\n * @type {Object}\n * @static\n * @memberof Popper\n */\nvar Defaults = {\n /**\n * Popper's placement.\n * @prop {Popper.placements} placement='bottom'\n */\n placement: 'bottom',\n\n /**\n * Set this to true if you want popper to position it self in 'fixed' mode\n * @prop {Boolean} positionFixed=false\n */\n positionFixed: false,\n\n /**\n * Whether events (resize, scroll) are initially enabled.\n * @prop {Boolean} eventsEnabled=true\n */\n eventsEnabled: true,\n\n /**\n * Set to true if you want to automatically remove the popper when\n * you call the `destroy` method.\n * @prop {Boolean} removeOnDestroy=false\n */\n removeOnDestroy: false,\n\n /**\n * Callback called when the popper is created.
    \n * By default, it is set to no-op.
    \n * Access Popper.js instance with `data.instance`.\n * @prop {onCreate}\n */\n onCreate: function onCreate() {},\n\n /**\n * Callback called when the popper is updated. This callback is not called\n * on the initialization/creation of the popper, but only on subsequent\n * updates.
    \n * By default, it is set to no-op.
    \n * Access Popper.js instance with `data.instance`.\n * @prop {onUpdate}\n */\n onUpdate: function onUpdate() {},\n\n /**\n * List of modifiers used to modify the offsets before they are applied to the popper.\n * They provide most of the functionalities of Popper.js.\n * @prop {modifiers}\n */\n modifiers: modifiers\n};\n\n/**\n * @callback onCreate\n * @param {dataObject} data\n */\n\n/**\n * @callback onUpdate\n * @param {dataObject} data\n */\n\n// Utils\n// Methods\nvar Popper = function () {\n /**\n * Creates a new Popper.js instance.\n * @class Popper\n * @param {Element|referenceObject} reference - The reference element used to position the popper\n * @param {Element} popper - The HTML / XML element used as the popper\n * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)\n * @return {Object} instance - The generated Popper.js instance\n */\n function Popper(reference, popper) {\n var _this = this;\n\n var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n classCallCheck(this, Popper);\n\n this.scheduleUpdate = function () {\n return requestAnimationFrame(_this.update);\n };\n\n // make update() debounced, so that it only runs at most once-per-tick\n this.update = debounce(this.update.bind(this));\n\n // with {} we create a new object with the options inside it\n this.options = _extends({}, Popper.Defaults, options);\n\n // init state\n this.state = {\n isDestroyed: false,\n isCreated: false,\n scrollParents: []\n };\n\n // get reference and popper elements (allow jQuery wrappers)\n this.reference = reference && reference.jquery ? reference[0] : reference;\n this.popper = popper && popper.jquery ? popper[0] : popper;\n\n // Deep merge modifiers options\n this.options.modifiers = {};\n Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {\n _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});\n });\n\n // Refactoring modifiers' list (Object => Array)\n this.modifiers = Object.keys(this.options.modifiers).map(function (name) {\n return _extends({\n name: name\n }, _this.options.modifiers[name]);\n })\n // sort the modifiers by order\n .sort(function (a, b) {\n return a.order - b.order;\n });\n\n // modifiers have the ability to execute arbitrary code when Popper.js get inited\n // such code is executed in the same order of its modifier\n // they could add new properties to their options configuration\n // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!\n this.modifiers.forEach(function (modifierOptions) {\n if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {\n modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);\n }\n });\n\n // fire the first update to position the popper in the right place\n this.update();\n\n var eventsEnabled = this.options.eventsEnabled;\n if (eventsEnabled) {\n // setup event listeners, they will take care of update the position in specific situations\n this.enableEventListeners();\n }\n\n this.state.eventsEnabled = eventsEnabled;\n }\n\n // We can't use class properties because they don't get listed in the\n // class prototype and break stuff like Sinon stubs\n\n\n createClass(Popper, [{\n key: 'update',\n value: function update$$1() {\n return update.call(this);\n }\n }, {\n key: 'destroy',\n value: function destroy$$1() {\n return destroy.call(this);\n }\n }, {\n key: 'enableEventListeners',\n value: function enableEventListeners$$1() {\n return enableEventListeners.call(this);\n }\n }, {\n key: 'disableEventListeners',\n value: function disableEventListeners$$1() {\n return disableEventListeners.call(this);\n }\n\n /**\n * Schedules an update. It will run on the next UI update available.\n * @method scheduleUpdate\n * @memberof Popper\n */\n\n\n /**\n * Collection of utilities useful when writing custom modifiers.\n * Starting from version 1.7, this method is available only if you\n * include `popper-utils.js` before `popper.js`.\n *\n * **DEPRECATION**: This way to access PopperUtils is deprecated\n * and will be removed in v2! Use the PopperUtils module directly instead.\n * Due to the high instability of the methods contained in Utils, we can't\n * guarantee them to follow semver. Use them at your own risk!\n * @static\n * @private\n * @type {Object}\n * @deprecated since version 1.8\n * @member Utils\n * @memberof Popper\n */\n\n }]);\n return Popper;\n}();\n\n/**\n * The `referenceObject` is an object that provides an interface compatible with Popper.js\n * and lets you use it as replacement of a real DOM node.
    \n * You can use this method to position a popper relatively to a set of coordinates\n * in case you don't have a DOM node to use as reference.\n *\n * ```\n * new Popper(referenceObject, popperNode);\n * ```\n *\n * NB: This feature isn't supported in Internet Explorer 10.\n * @name referenceObject\n * @property {Function} data.getBoundingClientRect\n * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.\n * @property {number} data.clientWidth\n * An ES6 getter that will return the width of the virtual reference element.\n * @property {number} data.clientHeight\n * An ES6 getter that will return the height of the virtual reference element.\n */\n\n\nPopper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;\nPopper.placements = placements;\nPopper.Defaults = Defaults;\n\nexport default Popper;\n//# sourceMappingURL=popper.js.map\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.5.3): dropdown.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\nimport Popper from 'popper.js'\nimport Util from './util'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'dropdown'\nconst VERSION = '4.5.3'\nconst DATA_KEY = 'bs.dropdown'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\nconst ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key\nconst SPACE_KEYCODE = 32 // KeyboardEvent.which value for space key\nconst TAB_KEYCODE = 9 // KeyboardEvent.which value for tab key\nconst ARROW_UP_KEYCODE = 38 // KeyboardEvent.which value for up arrow key\nconst ARROW_DOWN_KEYCODE = 40 // KeyboardEvent.which value for down arrow key\nconst RIGHT_MOUSE_BUTTON_WHICH = 3 // MouseEvent.which value for the right button (assuming a right-handed mouse)\nconst REGEXP_KEYDOWN = new RegExp(`${ARROW_UP_KEYCODE}|${ARROW_DOWN_KEYCODE}|${ESCAPE_KEYCODE}`)\n\nconst EVENT_HIDE = `hide${EVENT_KEY}`\nconst EVENT_HIDDEN = `hidden${EVENT_KEY}`\nconst EVENT_SHOW = `show${EVENT_KEY}`\nconst EVENT_SHOWN = `shown${EVENT_KEY}`\nconst EVENT_CLICK = `click${EVENT_KEY}`\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\nconst EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY}${DATA_API_KEY}`\nconst EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`\n\nconst CLASS_NAME_DISABLED = 'disabled'\nconst CLASS_NAME_SHOW = 'show'\nconst CLASS_NAME_DROPUP = 'dropup'\nconst CLASS_NAME_DROPRIGHT = 'dropright'\nconst CLASS_NAME_DROPLEFT = 'dropleft'\nconst CLASS_NAME_MENURIGHT = 'dropdown-menu-right'\nconst CLASS_NAME_POSITION_STATIC = 'position-static'\n\nconst SELECTOR_DATA_TOGGLE = '[data-toggle=\"dropdown\"]'\nconst SELECTOR_FORM_CHILD = '.dropdown form'\nconst SELECTOR_MENU = '.dropdown-menu'\nconst SELECTOR_NAVBAR_NAV = '.navbar-nav'\nconst SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'\n\nconst PLACEMENT_TOP = 'top-start'\nconst PLACEMENT_TOPEND = 'top-end'\nconst PLACEMENT_BOTTOM = 'bottom-start'\nconst PLACEMENT_BOTTOMEND = 'bottom-end'\nconst PLACEMENT_RIGHT = 'right-start'\nconst PLACEMENT_LEFT = 'left-start'\n\nconst Default = {\n offset: 0,\n flip: true,\n boundary: 'scrollParent',\n reference: 'toggle',\n display: 'dynamic',\n popperConfig: null\n}\n\nconst DefaultType = {\n offset: '(number|string|function)',\n flip: 'boolean',\n boundary: '(string|element)',\n reference: '(string|element)',\n display: 'string',\n popperConfig: '(null|object)'\n}\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass Dropdown {\n constructor(element, config) {\n this._element = element\n this._popper = null\n this._config = this._getConfig(config)\n this._menu = this._getMenuElement()\n this._inNavbar = this._detectNavbar()\n\n this._addEventListeners()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n // Public\n\n toggle() {\n if (this._element.disabled || $(this._element).hasClass(CLASS_NAME_DISABLED)) {\n return\n }\n\n const isActive = $(this._menu).hasClass(CLASS_NAME_SHOW)\n\n Dropdown._clearMenus()\n\n if (isActive) {\n return\n }\n\n this.show(true)\n }\n\n show(usePopper = false) {\n if (this._element.disabled || $(this._element).hasClass(CLASS_NAME_DISABLED) || $(this._menu).hasClass(CLASS_NAME_SHOW)) {\n return\n }\n\n const relatedTarget = {\n relatedTarget: this._element\n }\n const showEvent = $.Event(EVENT_SHOW, relatedTarget)\n const parent = Dropdown._getParentFromElement(this._element)\n\n $(parent).trigger(showEvent)\n\n if (showEvent.isDefaultPrevented()) {\n return\n }\n\n // Disable totally Popper.js for Dropdown in Navbar\n if (!this._inNavbar && usePopper) {\n /**\n * Check for Popper dependency\n * Popper - https://popper.js.org\n */\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap\\'s dropdowns require Popper.js (https://popper.js.org/)')\n }\n\n let referenceElement = this._element\n\n if (this._config.reference === 'parent') {\n referenceElement = parent\n } else if (Util.isElement(this._config.reference)) {\n referenceElement = this._config.reference\n\n // Check if it's jQuery element\n if (typeof this._config.reference.jquery !== 'undefined') {\n referenceElement = this._config.reference[0]\n }\n }\n\n // If boundary is not `scrollParent`, then set position to `static`\n // to allow the menu to \"escape\" the scroll parent's boundaries\n // https://github.com/twbs/bootstrap/issues/24251\n if (this._config.boundary !== 'scrollParent') {\n $(parent).addClass(CLASS_NAME_POSITION_STATIC)\n }\n\n this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig())\n }\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement &&\n $(parent).closest(SELECTOR_NAVBAR_NAV).length === 0) {\n $(document.body).children().on('mouseover', null, $.noop)\n }\n\n this._element.focus()\n this._element.setAttribute('aria-expanded', true)\n\n $(this._menu).toggleClass(CLASS_NAME_SHOW)\n $(parent)\n .toggleClass(CLASS_NAME_SHOW)\n .trigger($.Event(EVENT_SHOWN, relatedTarget))\n }\n\n hide() {\n if (this._element.disabled || $(this._element).hasClass(CLASS_NAME_DISABLED) || !$(this._menu).hasClass(CLASS_NAME_SHOW)) {\n return\n }\n\n const relatedTarget = {\n relatedTarget: this._element\n }\n const hideEvent = $.Event(EVENT_HIDE, relatedTarget)\n const parent = Dropdown._getParentFromElement(this._element)\n\n $(parent).trigger(hideEvent)\n\n if (hideEvent.isDefaultPrevented()) {\n return\n }\n\n if (this._popper) {\n this._popper.destroy()\n }\n\n $(this._menu).toggleClass(CLASS_NAME_SHOW)\n $(parent)\n .toggleClass(CLASS_NAME_SHOW)\n .trigger($.Event(EVENT_HIDDEN, relatedTarget))\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n $(this._element).off(EVENT_KEY)\n this._element = null\n this._menu = null\n if (this._popper !== null) {\n this._popper.destroy()\n this._popper = null\n }\n }\n\n update() {\n this._inNavbar = this._detectNavbar()\n if (this._popper !== null) {\n this._popper.scheduleUpdate()\n }\n }\n\n // Private\n\n _addEventListeners() {\n $(this._element).on(EVENT_CLICK, event => {\n event.preventDefault()\n event.stopPropagation()\n this.toggle()\n })\n }\n\n _getConfig(config) {\n config = {\n ...this.constructor.Default,\n ...$(this._element).data(),\n ...config\n }\n\n Util.typeCheckConfig(\n NAME,\n config,\n this.constructor.DefaultType\n )\n\n return config\n }\n\n _getMenuElement() {\n if (!this._menu) {\n const parent = Dropdown._getParentFromElement(this._element)\n\n if (parent) {\n this._menu = parent.querySelector(SELECTOR_MENU)\n }\n }\n\n return this._menu\n }\n\n _getPlacement() {\n const $parentDropdown = $(this._element.parentNode)\n let placement = PLACEMENT_BOTTOM\n\n // Handle dropup\n if ($parentDropdown.hasClass(CLASS_NAME_DROPUP)) {\n placement = $(this._menu).hasClass(CLASS_NAME_MENURIGHT) ?\n PLACEMENT_TOPEND :\n PLACEMENT_TOP\n } else if ($parentDropdown.hasClass(CLASS_NAME_DROPRIGHT)) {\n placement = PLACEMENT_RIGHT\n } else if ($parentDropdown.hasClass(CLASS_NAME_DROPLEFT)) {\n placement = PLACEMENT_LEFT\n } else if ($(this._menu).hasClass(CLASS_NAME_MENURIGHT)) {\n placement = PLACEMENT_BOTTOMEND\n }\n\n return placement\n }\n\n _detectNavbar() {\n return $(this._element).closest('.navbar').length > 0\n }\n\n _getOffset() {\n const offset = {}\n\n if (typeof this._config.offset === 'function') {\n offset.fn = data => {\n data.offsets = {\n ...data.offsets,\n ...(this._config.offset(data.offsets, this._element) || {})\n }\n\n return data\n }\n } else {\n offset.offset = this._config.offset\n }\n\n return offset\n }\n\n _getPopperConfig() {\n const popperConfig = {\n placement: this._getPlacement(),\n modifiers: {\n offset: this._getOffset(),\n flip: {\n enabled: this._config.flip\n },\n preventOverflow: {\n boundariesElement: this._config.boundary\n }\n }\n }\n\n // Disable Popper.js if we have a static display\n if (this._config.display === 'static') {\n popperConfig.modifiers.applyStyle = {\n enabled: false\n }\n }\n\n return {\n ...popperConfig,\n ...this._config.popperConfig\n }\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = typeof config === 'object' ? config : null\n\n if (!data) {\n data = new Dropdown(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n }\n })\n }\n\n static _clearMenus(event) {\n if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH ||\n event.type === 'keyup' && event.which !== TAB_KEYCODE)) {\n return\n }\n\n const toggles = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLE))\n\n for (let i = 0, len = toggles.length; i < len; i++) {\n const parent = Dropdown._getParentFromElement(toggles[i])\n const context = $(toggles[i]).data(DATA_KEY)\n const relatedTarget = {\n relatedTarget: toggles[i]\n }\n\n if (event && event.type === 'click') {\n relatedTarget.clickEvent = event\n }\n\n if (!context) {\n continue\n }\n\n const dropdownMenu = context._menu\n if (!$(parent).hasClass(CLASS_NAME_SHOW)) {\n continue\n }\n\n if (event && (event.type === 'click' &&\n /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) &&\n $.contains(parent, event.target)) {\n continue\n }\n\n const hideEvent = $.Event(EVENT_HIDE, relatedTarget)\n $(parent).trigger(hideEvent)\n if (hideEvent.isDefaultPrevented()) {\n continue\n }\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n $(document.body).children().off('mouseover', null, $.noop)\n }\n\n toggles[i].setAttribute('aria-expanded', 'false')\n\n if (context._popper) {\n context._popper.destroy()\n }\n\n $(dropdownMenu).removeClass(CLASS_NAME_SHOW)\n $(parent)\n .removeClass(CLASS_NAME_SHOW)\n .trigger($.Event(EVENT_HIDDEN, relatedTarget))\n }\n }\n\n static _getParentFromElement(element) {\n let parent\n const selector = Util.getSelectorFromElement(element)\n\n if (selector) {\n parent = document.querySelector(selector)\n }\n\n return parent || element.parentNode\n }\n\n // eslint-disable-next-line complexity\n static _dataApiKeydownHandler(event) {\n // If not input/textarea:\n // - And not a key in REGEXP_KEYDOWN => not a dropdown command\n // If input/textarea:\n // - If space key => not a dropdown command\n // - If key is other than escape\n // - If key is not up or down => not a dropdown command\n // - If trigger inside the menu => not a dropdown command\n if (/input|textarea/i.test(event.target.tagName) ?\n event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE &&\n (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE ||\n $(event.target).closest(SELECTOR_MENU).length) : !REGEXP_KEYDOWN.test(event.which)) {\n return\n }\n\n if (this.disabled || $(this).hasClass(CLASS_NAME_DISABLED)) {\n return\n }\n\n const parent = Dropdown._getParentFromElement(this)\n const isActive = $(parent).hasClass(CLASS_NAME_SHOW)\n\n if (!isActive && event.which === ESCAPE_KEYCODE) {\n return\n }\n\n event.preventDefault()\n event.stopPropagation()\n\n if (!isActive || (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) {\n if (event.which === ESCAPE_KEYCODE) {\n $(parent.querySelector(SELECTOR_DATA_TOGGLE)).trigger('focus')\n }\n\n $(this).trigger('click')\n return\n }\n\n const items = [].slice.call(parent.querySelectorAll(SELECTOR_VISIBLE_ITEMS))\n .filter(item => $(item).is(':visible'))\n\n if (items.length === 0) {\n return\n }\n\n let index = items.indexOf(event.target)\n\n if (event.which === ARROW_UP_KEYCODE && index > 0) { // Up\n index--\n }\n\n if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) { // Down\n index++\n }\n\n if (index < 0) {\n index = 0\n }\n\n items[index].focus()\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n$(document)\n .on(EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE, Dropdown._dataApiKeydownHandler)\n .on(EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown._dataApiKeydownHandler)\n .on(`${EVENT_CLICK_DATA_API} ${EVENT_KEYUP_DATA_API}`, Dropdown._clearMenus)\n .on(EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {\n event.preventDefault()\n event.stopPropagation()\n Dropdown._jQueryInterface.call($(this), 'toggle')\n })\n .on(EVENT_CLICK_DATA_API, SELECTOR_FORM_CHILD, e => {\n e.stopPropagation()\n })\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Dropdown._jQueryInterface\n$.fn[NAME].Constructor = Dropdown\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Dropdown._jQueryInterface\n}\n\nexport default Dropdown\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.5.3): modal.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\nimport Util from './util'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'modal'\nconst VERSION = '4.5.3'\nconst DATA_KEY = 'bs.modal'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\nconst ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key\n\nconst Default = {\n backdrop: true,\n keyboard: true,\n focus: true,\n show: true\n}\n\nconst DefaultType = {\n backdrop: '(boolean|string)',\n keyboard: 'boolean',\n focus: 'boolean',\n show: 'boolean'\n}\n\nconst EVENT_HIDE = `hide${EVENT_KEY}`\nconst EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY}`\nconst EVENT_HIDDEN = `hidden${EVENT_KEY}`\nconst EVENT_SHOW = `show${EVENT_KEY}`\nconst EVENT_SHOWN = `shown${EVENT_KEY}`\nconst EVENT_FOCUSIN = `focusin${EVENT_KEY}`\nconst EVENT_RESIZE = `resize${EVENT_KEY}`\nconst EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`\nconst EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`\nconst EVENT_MOUSEUP_DISMISS = `mouseup.dismiss${EVENT_KEY}`\nconst EVENT_MOUSEDOWN_DISMISS = `mousedown.dismiss${EVENT_KEY}`\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\n\nconst CLASS_NAME_SCROLLABLE = 'modal-dialog-scrollable'\nconst CLASS_NAME_SCROLLBAR_MEASURER = 'modal-scrollbar-measure'\nconst CLASS_NAME_BACKDROP = 'modal-backdrop'\nconst CLASS_NAME_OPEN = 'modal-open'\nconst CLASS_NAME_FADE = 'fade'\nconst CLASS_NAME_SHOW = 'show'\nconst CLASS_NAME_STATIC = 'modal-static'\n\nconst SELECTOR_DIALOG = '.modal-dialog'\nconst SELECTOR_MODAL_BODY = '.modal-body'\nconst SELECTOR_DATA_TOGGLE = '[data-toggle=\"modal\"]'\nconst SELECTOR_DATA_DISMISS = '[data-dismiss=\"modal\"]'\nconst SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'\nconst SELECTOR_STICKY_CONTENT = '.sticky-top'\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass Modal {\n constructor(element, config) {\n this._config = this._getConfig(config)\n this._element = element\n this._dialog = element.querySelector(SELECTOR_DIALOG)\n this._backdrop = null\n this._isShown = false\n this._isBodyOverflowing = false\n this._ignoreBackdropClick = false\n this._isTransitioning = false\n this._scrollbarWidth = 0\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n toggle(relatedTarget) {\n return this._isShown ? this.hide() : this.show(relatedTarget)\n }\n\n show(relatedTarget) {\n if (this._isShown || this._isTransitioning) {\n return\n }\n\n if ($(this._element).hasClass(CLASS_NAME_FADE)) {\n this._isTransitioning = true\n }\n\n const showEvent = $.Event(EVENT_SHOW, {\n relatedTarget\n })\n\n $(this._element).trigger(showEvent)\n\n if (this._isShown || showEvent.isDefaultPrevented()) {\n return\n }\n\n this._isShown = true\n\n this._checkScrollbar()\n this._setScrollbar()\n\n this._adjustDialog()\n\n this._setEscapeEvent()\n this._setResizeEvent()\n\n $(this._element).on(\n EVENT_CLICK_DISMISS,\n SELECTOR_DATA_DISMISS,\n event => this.hide(event)\n )\n\n $(this._dialog).on(EVENT_MOUSEDOWN_DISMISS, () => {\n $(this._element).one(EVENT_MOUSEUP_DISMISS, event => {\n if ($(event.target).is(this._element)) {\n this._ignoreBackdropClick = true\n }\n })\n })\n\n this._showBackdrop(() => this._showElement(relatedTarget))\n }\n\n hide(event) {\n if (event) {\n event.preventDefault()\n }\n\n if (!this._isShown || this._isTransitioning) {\n return\n }\n\n const hideEvent = $.Event(EVENT_HIDE)\n\n $(this._element).trigger(hideEvent)\n\n if (!this._isShown || hideEvent.isDefaultPrevented()) {\n return\n }\n\n this._isShown = false\n const transition = $(this._element).hasClass(CLASS_NAME_FADE)\n\n if (transition) {\n this._isTransitioning = true\n }\n\n this._setEscapeEvent()\n this._setResizeEvent()\n\n $(document).off(EVENT_FOCUSIN)\n\n $(this._element).removeClass(CLASS_NAME_SHOW)\n\n $(this._element).off(EVENT_CLICK_DISMISS)\n $(this._dialog).off(EVENT_MOUSEDOWN_DISMISS)\n\n if (transition) {\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, event => this._hideModal(event))\n .emulateTransitionEnd(transitionDuration)\n } else {\n this._hideModal()\n }\n }\n\n dispose() {\n [window, this._element, this._dialog]\n .forEach(htmlElement => $(htmlElement).off(EVENT_KEY))\n\n /**\n * `document` has 2 events `EVENT_FOCUSIN` and `EVENT_CLICK_DATA_API`\n * Do not move `document` in `htmlElements` array\n * It will remove `EVENT_CLICK_DATA_API` event that should remain\n */\n $(document).off(EVENT_FOCUSIN)\n\n $.removeData(this._element, DATA_KEY)\n\n this._config = null\n this._element = null\n this._dialog = null\n this._backdrop = null\n this._isShown = null\n this._isBodyOverflowing = null\n this._ignoreBackdropClick = null\n this._isTransitioning = null\n this._scrollbarWidth = null\n }\n\n handleUpdate() {\n this._adjustDialog()\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _triggerBackdropTransition() {\n if (this._config.backdrop === 'static') {\n const hideEventPrevented = $.Event(EVENT_HIDE_PREVENTED)\n\n $(this._element).trigger(hideEventPrevented)\n if (hideEventPrevented.isDefaultPrevented()) {\n return\n }\n\n const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight\n\n if (!isModalOverflowing) {\n this._element.style.overflowY = 'hidden'\n }\n\n this._element.classList.add(CLASS_NAME_STATIC)\n\n const modalTransitionDuration = Util.getTransitionDurationFromElement(this._dialog)\n $(this._element).off(Util.TRANSITION_END)\n\n $(this._element).one(Util.TRANSITION_END, () => {\n this._element.classList.remove(CLASS_NAME_STATIC)\n if (!isModalOverflowing) {\n $(this._element).one(Util.TRANSITION_END, () => {\n this._element.style.overflowY = ''\n })\n .emulateTransitionEnd(this._element, modalTransitionDuration)\n }\n })\n .emulateTransitionEnd(modalTransitionDuration)\n this._element.focus()\n } else {\n this.hide()\n }\n }\n\n _showElement(relatedTarget) {\n const transition = $(this._element).hasClass(CLASS_NAME_FADE)\n const modalBody = this._dialog ? this._dialog.querySelector(SELECTOR_MODAL_BODY) : null\n\n if (!this._element.parentNode ||\n this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {\n // Don't move modal's DOM position\n document.body.appendChild(this._element)\n }\n\n this._element.style.display = 'block'\n this._element.removeAttribute('aria-hidden')\n this._element.setAttribute('aria-modal', true)\n this._element.setAttribute('role', 'dialog')\n\n if ($(this._dialog).hasClass(CLASS_NAME_SCROLLABLE) && modalBody) {\n modalBody.scrollTop = 0\n } else {\n this._element.scrollTop = 0\n }\n\n if (transition) {\n Util.reflow(this._element)\n }\n\n $(this._element).addClass(CLASS_NAME_SHOW)\n\n if (this._config.focus) {\n this._enforceFocus()\n }\n\n const shownEvent = $.Event(EVENT_SHOWN, {\n relatedTarget\n })\n\n const transitionComplete = () => {\n if (this._config.focus) {\n this._element.focus()\n }\n\n this._isTransitioning = false\n $(this._element).trigger(shownEvent)\n }\n\n if (transition) {\n const transitionDuration = Util.getTransitionDurationFromElement(this._dialog)\n\n $(this._dialog)\n .one(Util.TRANSITION_END, transitionComplete)\n .emulateTransitionEnd(transitionDuration)\n } else {\n transitionComplete()\n }\n }\n\n _enforceFocus() {\n $(document)\n .off(EVENT_FOCUSIN) // Guard against infinite focus loop\n .on(EVENT_FOCUSIN, event => {\n if (document !== event.target &&\n this._element !== event.target &&\n $(this._element).has(event.target).length === 0) {\n this._element.focus()\n }\n })\n }\n\n _setEscapeEvent() {\n if (this._isShown) {\n $(this._element).on(EVENT_KEYDOWN_DISMISS, event => {\n if (this._config.keyboard && event.which === ESCAPE_KEYCODE) {\n event.preventDefault()\n this.hide()\n } else if (!this._config.keyboard && event.which === ESCAPE_KEYCODE) {\n this._triggerBackdropTransition()\n }\n })\n } else if (!this._isShown) {\n $(this._element).off(EVENT_KEYDOWN_DISMISS)\n }\n }\n\n _setResizeEvent() {\n if (this._isShown) {\n $(window).on(EVENT_RESIZE, event => this.handleUpdate(event))\n } else {\n $(window).off(EVENT_RESIZE)\n }\n }\n\n _hideModal() {\n this._element.style.display = 'none'\n this._element.setAttribute('aria-hidden', true)\n this._element.removeAttribute('aria-modal')\n this._element.removeAttribute('role')\n this._isTransitioning = false\n this._showBackdrop(() => {\n $(document.body).removeClass(CLASS_NAME_OPEN)\n this._resetAdjustments()\n this._resetScrollbar()\n $(this._element).trigger(EVENT_HIDDEN)\n })\n }\n\n _removeBackdrop() {\n if (this._backdrop) {\n $(this._backdrop).remove()\n this._backdrop = null\n }\n }\n\n _showBackdrop(callback) {\n const animate = $(this._element).hasClass(CLASS_NAME_FADE) ?\n CLASS_NAME_FADE : ''\n\n if (this._isShown && this._config.backdrop) {\n this._backdrop = document.createElement('div')\n this._backdrop.className = CLASS_NAME_BACKDROP\n\n if (animate) {\n this._backdrop.classList.add(animate)\n }\n\n $(this._backdrop).appendTo(document.body)\n\n $(this._element).on(EVENT_CLICK_DISMISS, event => {\n if (this._ignoreBackdropClick) {\n this._ignoreBackdropClick = false\n return\n }\n\n if (event.target !== event.currentTarget) {\n return\n }\n\n this._triggerBackdropTransition()\n })\n\n if (animate) {\n Util.reflow(this._backdrop)\n }\n\n $(this._backdrop).addClass(CLASS_NAME_SHOW)\n\n if (!callback) {\n return\n }\n\n if (!animate) {\n callback()\n return\n }\n\n const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)\n\n $(this._backdrop)\n .one(Util.TRANSITION_END, callback)\n .emulateTransitionEnd(backdropTransitionDuration)\n } else if (!this._isShown && this._backdrop) {\n $(this._backdrop).removeClass(CLASS_NAME_SHOW)\n\n const callbackRemove = () => {\n this._removeBackdrop()\n if (callback) {\n callback()\n }\n }\n\n if ($(this._element).hasClass(CLASS_NAME_FADE)) {\n const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)\n\n $(this._backdrop)\n .one(Util.TRANSITION_END, callbackRemove)\n .emulateTransitionEnd(backdropTransitionDuration)\n } else {\n callbackRemove()\n }\n } else if (callback) {\n callback()\n }\n }\n\n // ----------------------------------------------------------------------\n // the following methods are used to handle overflowing modals\n // todo (fat): these should probably be refactored out of modal.js\n // ----------------------------------------------------------------------\n\n _adjustDialog() {\n const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight\n\n if (!this._isBodyOverflowing && isModalOverflowing) {\n this._element.style.paddingLeft = `${this._scrollbarWidth}px`\n }\n\n if (this._isBodyOverflowing && !isModalOverflowing) {\n this._element.style.paddingRight = `${this._scrollbarWidth}px`\n }\n }\n\n _resetAdjustments() {\n this._element.style.paddingLeft = ''\n this._element.style.paddingRight = ''\n }\n\n _checkScrollbar() {\n const rect = document.body.getBoundingClientRect()\n this._isBodyOverflowing = Math.round(rect.left + rect.right) < window.innerWidth\n this._scrollbarWidth = this._getScrollbarWidth()\n }\n\n _setScrollbar() {\n if (this._isBodyOverflowing) {\n // Note: DOMNode.style.paddingRight returns the actual value or '' if not set\n // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set\n const fixedContent = [].slice.call(document.querySelectorAll(SELECTOR_FIXED_CONTENT))\n const stickyContent = [].slice.call(document.querySelectorAll(SELECTOR_STICKY_CONTENT))\n\n // Adjust fixed content padding\n $(fixedContent).each((index, element) => {\n const actualPadding = element.style.paddingRight\n const calculatedPadding = $(element).css('padding-right')\n $(element)\n .data('padding-right', actualPadding)\n .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`)\n })\n\n // Adjust sticky content margin\n $(stickyContent).each((index, element) => {\n const actualMargin = element.style.marginRight\n const calculatedMargin = $(element).css('margin-right')\n $(element)\n .data('margin-right', actualMargin)\n .css('margin-right', `${parseFloat(calculatedMargin) - this._scrollbarWidth}px`)\n })\n\n // Adjust body padding\n const actualPadding = document.body.style.paddingRight\n const calculatedPadding = $(document.body).css('padding-right')\n $(document.body)\n .data('padding-right', actualPadding)\n .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`)\n }\n\n $(document.body).addClass(CLASS_NAME_OPEN)\n }\n\n _resetScrollbar() {\n // Restore fixed content padding\n const fixedContent = [].slice.call(document.querySelectorAll(SELECTOR_FIXED_CONTENT))\n $(fixedContent).each((index, element) => {\n const padding = $(element).data('padding-right')\n $(element).removeData('padding-right')\n element.style.paddingRight = padding ? padding : ''\n })\n\n // Restore sticky content\n const elements = [].slice.call(document.querySelectorAll(`${SELECTOR_STICKY_CONTENT}`))\n $(elements).each((index, element) => {\n const margin = $(element).data('margin-right')\n if (typeof margin !== 'undefined') {\n $(element).css('margin-right', margin).removeData('margin-right')\n }\n })\n\n // Restore body padding\n const padding = $(document.body).data('padding-right')\n $(document.body).removeData('padding-right')\n document.body.style.paddingRight = padding ? padding : ''\n }\n\n _getScrollbarWidth() { // thx d.walsh\n const scrollDiv = document.createElement('div')\n scrollDiv.className = CLASS_NAME_SCROLLBAR_MEASURER\n document.body.appendChild(scrollDiv)\n const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth\n document.body.removeChild(scrollDiv)\n return scrollbarWidth\n }\n\n // Static\n\n static _jQueryInterface(config, relatedTarget) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = {\n ...Default,\n ...$(this).data(),\n ...(typeof config === 'object' && config ? config : {})\n }\n\n if (!data) {\n data = new Modal(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config](relatedTarget)\n } else if (_config.show) {\n data.show(relatedTarget)\n }\n })\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n$(document).on(EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {\n let target\n const selector = Util.getSelectorFromElement(this)\n\n if (selector) {\n target = document.querySelector(selector)\n }\n\n const config = $(target).data(DATA_KEY) ?\n 'toggle' : {\n ...$(target).data(),\n ...$(this).data()\n }\n\n if (this.tagName === 'A' || this.tagName === 'AREA') {\n event.preventDefault()\n }\n\n const $target = $(target).one(EVENT_SHOW, showEvent => {\n if (showEvent.isDefaultPrevented()) {\n // Only register focus restorer if modal will actually get shown\n return\n }\n\n $target.one(EVENT_HIDDEN, () => {\n if ($(this).is(':visible')) {\n this.focus()\n }\n })\n })\n\n Modal._jQueryInterface.call($(target), config, this)\n})\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Modal._jQueryInterface\n$.fn[NAME].Constructor = Modal\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Modal._jQueryInterface\n}\n\nexport default Modal\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.5.3): tools/sanitizer.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst uriAttrs = [\n 'background',\n 'cite',\n 'href',\n 'itemtype',\n 'longdesc',\n 'poster',\n 'src',\n 'xlink:href'\n]\n\nconst ARIA_ATTRIBUTE_PATTERN = /^aria-[\\w-]*$/i\n\nexport const DefaultWhitelist = {\n // Global attributes allowed on any supplied element below.\n '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],\n a: ['target', 'href', 'title', 'rel'],\n area: [],\n b: [],\n br: [],\n col: [],\n code: [],\n div: [],\n em: [],\n hr: [],\n h1: [],\n h2: [],\n h3: [],\n h4: [],\n h5: [],\n h6: [],\n i: [],\n img: ['src', 'srcset', 'alt', 'title', 'width', 'height'],\n li: [],\n ol: [],\n p: [],\n pre: [],\n s: [],\n small: [],\n span: [],\n sub: [],\n sup: [],\n strong: [],\n u: [],\n ul: []\n}\n\n/**\n * A pattern that recognizes a commonly useful subset of URLs that are safe.\n *\n * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts\n */\nconst SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/gi\n\n/**\n * A pattern that matches safe data URLs. Only matches image, video and audio types.\n *\n * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts\n */\nconst DATA_URL_PATTERN = /^data:(?:image\\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\\/(?:mpeg|mp4|ogg|webm)|audio\\/(?:mp3|oga|ogg|opus));base64,[\\d+/a-z]+=*$/i\n\nfunction allowedAttribute(attr, allowedAttributeList) {\n const attrName = attr.nodeName.toLowerCase()\n\n if (allowedAttributeList.indexOf(attrName) !== -1) {\n if (uriAttrs.indexOf(attrName) !== -1) {\n return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN))\n }\n\n return true\n }\n\n const regExp = allowedAttributeList.filter(attrRegex => attrRegex instanceof RegExp)\n\n // Check if a regular expression validates the attribute.\n for (let i = 0, len = regExp.length; i < len; i++) {\n if (attrName.match(regExp[i])) {\n return true\n }\n }\n\n return false\n}\n\nexport function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {\n if (unsafeHtml.length === 0) {\n return unsafeHtml\n }\n\n if (sanitizeFn && typeof sanitizeFn === 'function') {\n return sanitizeFn(unsafeHtml)\n }\n\n const domParser = new window.DOMParser()\n const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html')\n const whitelistKeys = Object.keys(whiteList)\n const elements = [].slice.call(createdDocument.body.querySelectorAll('*'))\n\n for (let i = 0, len = elements.length; i < len; i++) {\n const el = elements[i]\n const elName = el.nodeName.toLowerCase()\n\n if (whitelistKeys.indexOf(el.nodeName.toLowerCase()) === -1) {\n el.parentNode.removeChild(el)\n\n continue\n }\n\n const attributeList = [].slice.call(el.attributes)\n const whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || [])\n\n attributeList.forEach(attr => {\n if (!allowedAttribute(attr, whitelistedAttributes)) {\n el.removeAttribute(attr.nodeName)\n }\n })\n }\n\n return createdDocument.body.innerHTML\n}\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.5.3): tooltip.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport {\n DefaultWhitelist,\n sanitizeHtml\n} from './tools/sanitizer'\nimport $ from 'jquery'\nimport Popper from 'popper.js'\nimport Util from './util'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'tooltip'\nconst VERSION = '4.5.3'\nconst DATA_KEY = 'bs.tooltip'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\nconst CLASS_PREFIX = 'bs-tooltip'\nconst BSCLS_PREFIX_REGEX = new RegExp(`(^|\\\\s)${CLASS_PREFIX}\\\\S+`, 'g')\nconst DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn']\n\nconst DefaultType = {\n animation: 'boolean',\n template: 'string',\n title: '(string|element|function)',\n trigger: 'string',\n delay: '(number|object)',\n html: 'boolean',\n selector: '(string|boolean)',\n placement: '(string|function)',\n offset: '(number|string|function)',\n container: '(string|element|boolean)',\n fallbackPlacement: '(string|array)',\n boundary: '(string|element)',\n sanitize: 'boolean',\n sanitizeFn: '(null|function)',\n whiteList: 'object',\n popperConfig: '(null|object)'\n}\n\nconst AttachmentMap = {\n AUTO: 'auto',\n TOP: 'top',\n RIGHT: 'right',\n BOTTOM: 'bottom',\n LEFT: 'left'\n}\n\nconst Default = {\n animation: true,\n template: '
    ' +\n '
    ' +\n '
    ',\n trigger: 'hover focus',\n title: '',\n delay: 0,\n html: false,\n selector: false,\n placement: 'top',\n offset: 0,\n container: false,\n fallbackPlacement: 'flip',\n boundary: 'scrollParent',\n sanitize: true,\n sanitizeFn: null,\n whiteList: DefaultWhitelist,\n popperConfig: null\n}\n\nconst HOVER_STATE_SHOW = 'show'\nconst HOVER_STATE_OUT = 'out'\n\nconst Event = {\n HIDE: `hide${EVENT_KEY}`,\n HIDDEN: `hidden${EVENT_KEY}`,\n SHOW: `show${EVENT_KEY}`,\n SHOWN: `shown${EVENT_KEY}`,\n INSERTED: `inserted${EVENT_KEY}`,\n CLICK: `click${EVENT_KEY}`,\n FOCUSIN: `focusin${EVENT_KEY}`,\n FOCUSOUT: `focusout${EVENT_KEY}`,\n MOUSEENTER: `mouseenter${EVENT_KEY}`,\n MOUSELEAVE: `mouseleave${EVENT_KEY}`\n}\n\nconst CLASS_NAME_FADE = 'fade'\nconst CLASS_NAME_SHOW = 'show'\n\nconst SELECTOR_TOOLTIP_INNER = '.tooltip-inner'\nconst SELECTOR_ARROW = '.arrow'\n\nconst TRIGGER_HOVER = 'hover'\nconst TRIGGER_FOCUS = 'focus'\nconst TRIGGER_CLICK = 'click'\nconst TRIGGER_MANUAL = 'manual'\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass Tooltip {\n constructor(element, config) {\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap\\'s tooltips require Popper.js (https://popper.js.org/)')\n }\n\n // private\n this._isEnabled = true\n this._timeout = 0\n this._hoverState = ''\n this._activeTrigger = {}\n this._popper = null\n\n // Protected\n this.element = element\n this.config = this._getConfig(config)\n this.tip = null\n\n this._setListeners()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n static get NAME() {\n return NAME\n }\n\n static get DATA_KEY() {\n return DATA_KEY\n }\n\n static get Event() {\n return Event\n }\n\n static get EVENT_KEY() {\n return EVENT_KEY\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n // Public\n\n enable() {\n this._isEnabled = true\n }\n\n disable() {\n this._isEnabled = false\n }\n\n toggleEnabled() {\n this._isEnabled = !this._isEnabled\n }\n\n toggle(event) {\n if (!this._isEnabled) {\n return\n }\n\n if (event) {\n const dataKey = this.constructor.DATA_KEY\n let context = $(event.currentTarget).data(dataKey)\n\n if (!context) {\n context = new this.constructor(\n event.currentTarget,\n this._getDelegateConfig()\n )\n $(event.currentTarget).data(dataKey, context)\n }\n\n context._activeTrigger.click = !context._activeTrigger.click\n\n if (context._isWithActiveTrigger()) {\n context._enter(null, context)\n } else {\n context._leave(null, context)\n }\n } else {\n if ($(this.getTipElement()).hasClass(CLASS_NAME_SHOW)) {\n this._leave(null, this)\n return\n }\n\n this._enter(null, this)\n }\n }\n\n dispose() {\n clearTimeout(this._timeout)\n\n $.removeData(this.element, this.constructor.DATA_KEY)\n\n $(this.element).off(this.constructor.EVENT_KEY)\n $(this.element).closest('.modal').off('hide.bs.modal', this._hideModalHandler)\n\n if (this.tip) {\n $(this.tip).remove()\n }\n\n this._isEnabled = null\n this._timeout = null\n this._hoverState = null\n this._activeTrigger = null\n if (this._popper) {\n this._popper.destroy()\n }\n\n this._popper = null\n this.element = null\n this.config = null\n this.tip = null\n }\n\n show() {\n if ($(this.element).css('display') === 'none') {\n throw new Error('Please use show on visible elements')\n }\n\n const showEvent = $.Event(this.constructor.Event.SHOW)\n if (this.isWithContent() && this._isEnabled) {\n $(this.element).trigger(showEvent)\n\n const shadowRoot = Util.findShadowRoot(this.element)\n const isInTheDom = $.contains(\n shadowRoot !== null ? shadowRoot : this.element.ownerDocument.documentElement,\n this.element\n )\n\n if (showEvent.isDefaultPrevented() || !isInTheDom) {\n return\n }\n\n const tip = this.getTipElement()\n const tipId = Util.getUID(this.constructor.NAME)\n\n tip.setAttribute('id', tipId)\n this.element.setAttribute('aria-describedby', tipId)\n\n this.setContent()\n\n if (this.config.animation) {\n $(tip).addClass(CLASS_NAME_FADE)\n }\n\n const placement = typeof this.config.placement === 'function' ?\n this.config.placement.call(this, tip, this.element) :\n this.config.placement\n\n const attachment = this._getAttachment(placement)\n this.addAttachmentClass(attachment)\n\n const container = this._getContainer()\n $(tip).data(this.constructor.DATA_KEY, this)\n\n if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) {\n $(tip).appendTo(container)\n }\n\n $(this.element).trigger(this.constructor.Event.INSERTED)\n\n this._popper = new Popper(this.element, tip, this._getPopperConfig(attachment))\n\n $(tip).addClass(CLASS_NAME_SHOW)\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement) {\n $(document.body).children().on('mouseover', null, $.noop)\n }\n\n const complete = () => {\n if (this.config.animation) {\n this._fixTransition()\n }\n\n const prevHoverState = this._hoverState\n this._hoverState = null\n\n $(this.element).trigger(this.constructor.Event.SHOWN)\n\n if (prevHoverState === HOVER_STATE_OUT) {\n this._leave(null, this)\n }\n }\n\n if ($(this.tip).hasClass(CLASS_NAME_FADE)) {\n const transitionDuration = Util.getTransitionDurationFromElement(this.tip)\n\n $(this.tip)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n } else {\n complete()\n }\n }\n }\n\n hide(callback) {\n const tip = this.getTipElement()\n const hideEvent = $.Event(this.constructor.Event.HIDE)\n const complete = () => {\n if (this._hoverState !== HOVER_STATE_SHOW && tip.parentNode) {\n tip.parentNode.removeChild(tip)\n }\n\n this._cleanTipClass()\n this.element.removeAttribute('aria-describedby')\n $(this.element).trigger(this.constructor.Event.HIDDEN)\n if (this._popper !== null) {\n this._popper.destroy()\n }\n\n if (callback) {\n callback()\n }\n }\n\n $(this.element).trigger(hideEvent)\n\n if (hideEvent.isDefaultPrevented()) {\n return\n }\n\n $(tip).removeClass(CLASS_NAME_SHOW)\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n $(document.body).children().off('mouseover', null, $.noop)\n }\n\n this._activeTrigger[TRIGGER_CLICK] = false\n this._activeTrigger[TRIGGER_FOCUS] = false\n this._activeTrigger[TRIGGER_HOVER] = false\n\n if ($(this.tip).hasClass(CLASS_NAME_FADE)) {\n const transitionDuration = Util.getTransitionDurationFromElement(tip)\n\n $(tip)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n } else {\n complete()\n }\n\n this._hoverState = ''\n }\n\n update() {\n if (this._popper !== null) {\n this._popper.scheduleUpdate()\n }\n }\n\n // Protected\n\n isWithContent() {\n return Boolean(this.getTitle())\n }\n\n addAttachmentClass(attachment) {\n $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`)\n }\n\n getTipElement() {\n this.tip = this.tip || $(this.config.template)[0]\n return this.tip\n }\n\n setContent() {\n const tip = this.getTipElement()\n this.setElementContent($(tip.querySelectorAll(SELECTOR_TOOLTIP_INNER)), this.getTitle())\n $(tip).removeClass(`${CLASS_NAME_FADE} ${CLASS_NAME_SHOW}`)\n }\n\n setElementContent($element, content) {\n if (typeof content === 'object' && (content.nodeType || content.jquery)) {\n // Content is a DOM node or a jQuery\n if (this.config.html) {\n if (!$(content).parent().is($element)) {\n $element.empty().append(content)\n }\n } else {\n $element.text($(content).text())\n }\n\n return\n }\n\n if (this.config.html) {\n if (this.config.sanitize) {\n content = sanitizeHtml(content, this.config.whiteList, this.config.sanitizeFn)\n }\n\n $element.html(content)\n } else {\n $element.text(content)\n }\n }\n\n getTitle() {\n let title = this.element.getAttribute('data-original-title')\n\n if (!title) {\n title = typeof this.config.title === 'function' ?\n this.config.title.call(this.element) :\n this.config.title\n }\n\n return title\n }\n\n // Private\n\n _getPopperConfig(attachment) {\n const defaultBsConfig = {\n placement: attachment,\n modifiers: {\n offset: this._getOffset(),\n flip: {\n behavior: this.config.fallbackPlacement\n },\n arrow: {\n element: SELECTOR_ARROW\n },\n preventOverflow: {\n boundariesElement: this.config.boundary\n }\n },\n onCreate: data => {\n if (data.originalPlacement !== data.placement) {\n this._handlePopperPlacementChange(data)\n }\n },\n onUpdate: data => this._handlePopperPlacementChange(data)\n }\n\n return {\n ...defaultBsConfig,\n ...this.config.popperConfig\n }\n }\n\n _getOffset() {\n const offset = {}\n\n if (typeof this.config.offset === 'function') {\n offset.fn = data => {\n data.offsets = {\n ...data.offsets,\n ...(this.config.offset(data.offsets, this.element) || {})\n }\n\n return data\n }\n } else {\n offset.offset = this.config.offset\n }\n\n return offset\n }\n\n _getContainer() {\n if (this.config.container === false) {\n return document.body\n }\n\n if (Util.isElement(this.config.container)) {\n return $(this.config.container)\n }\n\n return $(document).find(this.config.container)\n }\n\n _getAttachment(placement) {\n return AttachmentMap[placement.toUpperCase()]\n }\n\n _setListeners() {\n const triggers = this.config.trigger.split(' ')\n\n triggers.forEach(trigger => {\n if (trigger === 'click') {\n $(this.element).on(\n this.constructor.Event.CLICK,\n this.config.selector,\n event => this.toggle(event)\n )\n } else if (trigger !== TRIGGER_MANUAL) {\n const eventIn = trigger === TRIGGER_HOVER ?\n this.constructor.Event.MOUSEENTER :\n this.constructor.Event.FOCUSIN\n const eventOut = trigger === TRIGGER_HOVER ?\n this.constructor.Event.MOUSELEAVE :\n this.constructor.Event.FOCUSOUT\n\n $(this.element)\n .on(eventIn, this.config.selector, event => this._enter(event))\n .on(eventOut, this.config.selector, event => this._leave(event))\n }\n })\n\n this._hideModalHandler = () => {\n if (this.element) {\n this.hide()\n }\n }\n\n $(this.element).closest('.modal').on('hide.bs.modal', this._hideModalHandler)\n\n if (this.config.selector) {\n this.config = {\n ...this.config,\n trigger: 'manual',\n selector: ''\n }\n } else {\n this._fixTitle()\n }\n }\n\n _fixTitle() {\n const titleType = typeof this.element.getAttribute('data-original-title')\n\n if (this.element.getAttribute('title') || titleType !== 'string') {\n this.element.setAttribute(\n 'data-original-title',\n this.element.getAttribute('title') || ''\n )\n\n this.element.setAttribute('title', '')\n }\n }\n\n _enter(event, context) {\n const dataKey = this.constructor.DATA_KEY\n context = context || $(event.currentTarget).data(dataKey)\n\n if (!context) {\n context = new this.constructor(\n event.currentTarget,\n this._getDelegateConfig()\n )\n $(event.currentTarget).data(dataKey, context)\n }\n\n if (event) {\n context._activeTrigger[\n event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER\n ] = true\n }\n\n if ($(context.getTipElement()).hasClass(CLASS_NAME_SHOW) || context._hoverState === HOVER_STATE_SHOW) {\n context._hoverState = HOVER_STATE_SHOW\n return\n }\n\n clearTimeout(context._timeout)\n\n context._hoverState = HOVER_STATE_SHOW\n\n if (!context.config.delay || !context.config.delay.show) {\n context.show()\n return\n }\n\n context._timeout = setTimeout(() => {\n if (context._hoverState === HOVER_STATE_SHOW) {\n context.show()\n }\n }, context.config.delay.show)\n }\n\n _leave(event, context) {\n const dataKey = this.constructor.DATA_KEY\n context = context || $(event.currentTarget).data(dataKey)\n\n if (!context) {\n context = new this.constructor(\n event.currentTarget,\n this._getDelegateConfig()\n )\n $(event.currentTarget).data(dataKey, context)\n }\n\n if (event) {\n context._activeTrigger[\n event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER\n ] = false\n }\n\n if (context._isWithActiveTrigger()) {\n return\n }\n\n clearTimeout(context._timeout)\n\n context._hoverState = HOVER_STATE_OUT\n\n if (!context.config.delay || !context.config.delay.hide) {\n context.hide()\n return\n }\n\n context._timeout = setTimeout(() => {\n if (context._hoverState === HOVER_STATE_OUT) {\n context.hide()\n }\n }, context.config.delay.hide)\n }\n\n _isWithActiveTrigger() {\n for (const trigger in this._activeTrigger) {\n if (this._activeTrigger[trigger]) {\n return true\n }\n }\n\n return false\n }\n\n _getConfig(config) {\n const dataAttributes = $(this.element).data()\n\n Object.keys(dataAttributes)\n .forEach(dataAttr => {\n if (DISALLOWED_ATTRIBUTES.indexOf(dataAttr) !== -1) {\n delete dataAttributes[dataAttr]\n }\n })\n\n config = {\n ...this.constructor.Default,\n ...dataAttributes,\n ...(typeof config === 'object' && config ? config : {})\n }\n\n if (typeof config.delay === 'number') {\n config.delay = {\n show: config.delay,\n hide: config.delay\n }\n }\n\n if (typeof config.title === 'number') {\n config.title = config.title.toString()\n }\n\n if (typeof config.content === 'number') {\n config.content = config.content.toString()\n }\n\n Util.typeCheckConfig(\n NAME,\n config,\n this.constructor.DefaultType\n )\n\n if (config.sanitize) {\n config.template = sanitizeHtml(config.template, config.whiteList, config.sanitizeFn)\n }\n\n return config\n }\n\n _getDelegateConfig() {\n const config = {}\n\n if (this.config) {\n for (const key in this.config) {\n if (this.constructor.Default[key] !== this.config[key]) {\n config[key] = this.config[key]\n }\n }\n }\n\n return config\n }\n\n _cleanTipClass() {\n const $tip = $(this.getTipElement())\n const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX)\n if (tabClass !== null && tabClass.length) {\n $tip.removeClass(tabClass.join(''))\n }\n }\n\n _handlePopperPlacementChange(popperData) {\n this.tip = popperData.instance.popper\n this._cleanTipClass()\n this.addAttachmentClass(this._getAttachment(popperData.placement))\n }\n\n _fixTransition() {\n const tip = this.getTipElement()\n const initConfigAnimation = this.config.animation\n\n if (tip.getAttribute('x-placement') !== null) {\n return\n }\n\n $(tip).removeClass(CLASS_NAME_FADE)\n this.config.animation = false\n this.hide()\n this.show()\n this.config.animation = initConfigAnimation\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n const $element = $(this)\n let data = $element.data(DATA_KEY)\n const _config = typeof config === 'object' && config\n\n if (!data && /dispose|hide/.test(config)) {\n return\n }\n\n if (!data) {\n data = new Tooltip(this, _config)\n $element.data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n }\n })\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Tooltip._jQueryInterface\n$.fn[NAME].Constructor = Tooltip\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Tooltip._jQueryInterface\n}\n\nexport default Tooltip\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.5.3): popover.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\nimport Tooltip from './tooltip'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'popover'\nconst VERSION = '4.5.3'\nconst DATA_KEY = 'bs.popover'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\nconst CLASS_PREFIX = 'bs-popover'\nconst BSCLS_PREFIX_REGEX = new RegExp(`(^|\\\\s)${CLASS_PREFIX}\\\\S+`, 'g')\n\nconst Default = {\n ...Tooltip.Default,\n placement: 'right',\n trigger: 'click',\n content: '',\n template: '
    ' +\n '
    ' +\n '

    ' +\n '
    '\n}\n\nconst DefaultType = {\n ...Tooltip.DefaultType,\n content: '(string|element|function)'\n}\n\nconst CLASS_NAME_FADE = 'fade'\nconst CLASS_NAME_SHOW = 'show'\n\nconst SELECTOR_TITLE = '.popover-header'\nconst SELECTOR_CONTENT = '.popover-body'\n\nconst Event = {\n HIDE: `hide${EVENT_KEY}`,\n HIDDEN: `hidden${EVENT_KEY}`,\n SHOW: `show${EVENT_KEY}`,\n SHOWN: `shown${EVENT_KEY}`,\n INSERTED: `inserted${EVENT_KEY}`,\n CLICK: `click${EVENT_KEY}`,\n FOCUSIN: `focusin${EVENT_KEY}`,\n FOCUSOUT: `focusout${EVENT_KEY}`,\n MOUSEENTER: `mouseenter${EVENT_KEY}`,\n MOUSELEAVE: `mouseleave${EVENT_KEY}`\n}\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass Popover extends Tooltip {\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n static get NAME() {\n return NAME\n }\n\n static get DATA_KEY() {\n return DATA_KEY\n }\n\n static get Event() {\n return Event\n }\n\n static get EVENT_KEY() {\n return EVENT_KEY\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n // Overrides\n\n isWithContent() {\n return this.getTitle() || this._getContent()\n }\n\n addAttachmentClass(attachment) {\n $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`)\n }\n\n getTipElement() {\n this.tip = this.tip || $(this.config.template)[0]\n return this.tip\n }\n\n setContent() {\n const $tip = $(this.getTipElement())\n\n // We use append for html objects to maintain js events\n this.setElementContent($tip.find(SELECTOR_TITLE), this.getTitle())\n let content = this._getContent()\n if (typeof content === 'function') {\n content = content.call(this.element)\n }\n\n this.setElementContent($tip.find(SELECTOR_CONTENT), content)\n\n $tip.removeClass(`${CLASS_NAME_FADE} ${CLASS_NAME_SHOW}`)\n }\n\n // Private\n\n _getContent() {\n return this.element.getAttribute('data-content') ||\n this.config.content\n }\n\n _cleanTipClass() {\n const $tip = $(this.getTipElement())\n const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX)\n if (tabClass !== null && tabClass.length > 0) {\n $tip.removeClass(tabClass.join(''))\n }\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = typeof config === 'object' ? config : null\n\n if (!data && /dispose|hide/.test(config)) {\n return\n }\n\n if (!data) {\n data = new Popover(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n }\n })\n }\n}\n\n/**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n$.fn[NAME] = Popover._jQueryInterface\n$.fn[NAME].Constructor = Popover\n$.fn[NAME].noConflict = () => {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Popover._jQueryInterface\n}\n\nexport default Popover\n","/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.5.3): scrollspy.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport $ from 'jquery'\nimport Util from './util'\n\n/**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\nconst NAME = 'scrollspy'\nconst VERSION = '4.5.3'\nconst DATA_KEY = 'bs.scrollspy'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\nconst JQUERY_NO_CONFLICT = $.fn[NAME]\n\nconst Default = {\n offset: 10,\n method: 'auto',\n target: ''\n}\n\nconst DefaultType = {\n offset: 'number',\n method: 'string',\n target: '(string|element)'\n}\n\nconst EVENT_ACTIVATE = `activate${EVENT_KEY}`\nconst EVENT_SCROLL = `scroll${EVENT_KEY}`\nconst EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`\n\nconst CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item'\nconst CLASS_NAME_ACTIVE = 'active'\n\nconst SELECTOR_DATA_SPY = '[data-spy=\"scroll\"]'\nconst SELECTOR_NAV_LIST_GROUP = '.nav, .list-group'\nconst SELECTOR_NAV_LINKS = '.nav-link'\nconst SELECTOR_NAV_ITEMS = '.nav-item'\nconst SELECTOR_LIST_ITEMS = '.list-group-item'\nconst SELECTOR_DROPDOWN = '.dropdown'\nconst SELECTOR_DROPDOWN_ITEMS = '.dropdown-item'\nconst SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle'\n\nconst METHOD_OFFSET = 'offset'\nconst METHOD_POSITION = 'position'\n\n/**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\nclass ScrollSpy {\n constructor(element, config) {\n this._element = element\n this._scrollElement = element.tagName === 'BODY' ? window : element\n this._config = this._getConfig(config)\n this._selector = `${this._config.target} ${SELECTOR_NAV_LINKS},` +\n `${this._config.target} ${SELECTOR_LIST_ITEMS},` +\n `${this._config.target} ${SELECTOR_DROPDOWN_ITEMS}`\n this._offsets = []\n this._targets = []\n this._activeTarget = null\n this._scrollHeight = 0\n\n $(this._scrollElement).on(EVENT_SCROLL, event => this._process(event))\n\n this.refresh()\n this._process()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n refresh() {\n const autoMethod = this._scrollElement === this._scrollElement.window ?\n METHOD_OFFSET : METHOD_POSITION\n\n const offsetMethod = this._config.method === 'auto' ?\n autoMethod : this._config.method\n\n const offsetBase = offsetMethod === METHOD_POSITION ?\n this._getScrollTop() : 0\n\n this._offsets = []\n this._targets = []\n\n this._scrollHeight = this._getScrollHeight()\n\n const targets = [].slice.call(document.querySelectorAll(this._selector))\n\n targets\n .map(element => {\n let target\n const targetSelector = Util.getSelectorFromElement(element)\n\n if (targetSelector) {\n target = document.querySelector(targetSelector)\n }\n\n if (target) {\n const targetBCR = target.getBoundingClientRect()\n if (targetBCR.width || targetBCR.height) {\n // TODO (fat): remove sketch reliance on jQuery position/offset\n return [\n $(target)[offsetMethod]().top + offsetBase,\n targetSelector\n ]\n }\n }\n\n return null\n })\n .filter(item => item)\n .sort((a, b) => a[0] - b[0])\n .forEach(item => {\n this._offsets.push(item[0])\n this._targets.push(item[1])\n })\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n $(this._scrollElement).off(EVENT_KEY)\n\n this._element = null\n this._scrollElement = null\n this._config = null\n this._selector = null\n this._offsets = null\n this._targets = null\n this._activeTarget = null\n this._scrollHeight = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...(typeof config === 'object' && config ? config : {})\n }\n\n if (typeof config.target !== 'string' && Util.isElement(config.target)) {\n let id = $(config.target).attr('id')\n if (!id) {\n id = Util.getUID(NAME)\n $(config.target).attr('id', id)\n }\n\n config.target = `#${id}`\n }\n\n Util.typeCheckConfig(NAME, config, DefaultType)\n\n return config\n }\n\n _getScrollTop() {\n return this._scrollElement === window ?\n this._scrollElement.pageYOffset : this._scrollElement.scrollTop\n }\n\n _getScrollHeight() {\n return this._scrollElement.scrollHeight || Math.max(\n document.body.scrollHeight,\n document.documentElement.scrollHeight\n )\n }\n\n _getOffsetHeight() {\n return this._scrollElement === window ?\n window.innerHeight : this._scrollElement.getBoundingClientRect().height\n }\n\n _process() {\n const scrollTop = this._getScrollTop() + this._config.offset\n const scrollHeight = this._getScrollHeight()\n const maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight()\n\n if (this._scrollHeight !== scrollHeight) {\n this.refresh()\n }\n\n if (scrollTop >= maxScroll) {\n const target = this._targets[this._targets.length - 1]\n\n if (this._activeTarget !== target) {\n this._activate(target)\n }\n\n return\n }\n\n if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {\n this._activeTarget = null\n this._clear()\n return\n }\n\n for (let i = this._offsets.length; i--;) {\n const isActiveTarget = this._activeTarget !== this._targets[i] &&\n scrollTop >= this._offsets[i] &&\n (typeof this._offsets[i + 1] === 'undefined' ||\n scrollTop < this._offsets[i + 1])\n\n if (isActiveTarget) {\n this._activate(this._targets[i])\n }\n }\n }\n\n _activate(target) {\n this._activeTarget = target\n\n this._clear()\n\n const queries = this._selector\n .split(',')\n .map(selector => `${selector}[data-target=\"${target}\"],${selector}[href=\"${target}\"]`)\n\n const $link = $([].slice.call(document.querySelectorAll(queries.join(','))))\n\n if ($link.hasClass(CLASS_NAME_DROPDOWN_ITEM)) {\n $link.closest(SELECTOR_DROPDOWN)\n .find(SELECTOR_DROPDOWN_TOGGLE)\n .addClass(CLASS_NAME_ACTIVE)\n $link.addClass(CLASS_NAME_ACTIVE)\n } else {\n // Set triggered link as active\n $link.addClass(CLASS_NAME_ACTIVE)\n // Set triggered links parents as active\n // With both