From 857d1256bf13532456ee8a27762ab18a0d14aef2 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Tue, 10 Jan 2023 23:06:57 +0100 Subject: [PATCH 01/39] Add Tickets --- NetEvent/Server.Tests/EventModuleTest.cs | 84 +- NetEvent/Server/Data/ApplicationDbContext.cs | 2 + NetEvent/Server/Data/Events/EventManager.cs | 62 +- NetEvent/Server/Data/Events/IEventManager.cs | 6 + NetEvent/Server/Helpers/DtoMapper.cs | 4 + ...30110210613_AddEventTicketType.Designer.cs | 740 ++++++++++++++++++ .../Psql/20230110210613_AddEventTicketType.cs | 120 +++ .../PsqlApplicationDbContextModelSnapshot.cs | 86 +- ...30110210600_AddEventTicketType.Designer.cs | 725 +++++++++++++++++ .../20230110210600_AddEventTicketType.cs | 119 +++ ...SqliteApplicationDbContextModelSnapshot.cs | 84 +- NetEvent/Server/Models/Event.cs | 5 + NetEvent/Server/Models/Purchase.cs | 153 ++++ .../Events/Endpoints/DeleteEventTicketType.cs | 54 ++ .../Modules/Events/Endpoints/GetEvent.cs | 5 +- .../Events/Endpoints/PostEventTicketType.cs | 62 ++ .../Events/Endpoints/PutEventTicketType.cs | 61 ++ .../Server/Modules/Events/EventsModule.cs | 11 + NetEvent/Shared/Dto/Event/CurrencyDto.cs | 7 + NetEvent/Shared/Dto/Event/EventDto.cs | 4 + .../Shared/Dto/Event/EventTicketTypeDto.cs | 26 + NetEvent/TestHelper/Fakers.cs | 14 + 22 files changed, 2400 insertions(+), 34 deletions(-) create mode 100644 NetEvent/Server/Migrations/Psql/20230110210613_AddEventTicketType.Designer.cs create mode 100644 NetEvent/Server/Migrations/Psql/20230110210613_AddEventTicketType.cs create mode 100644 NetEvent/Server/Migrations/Sqlite/20230110210600_AddEventTicketType.Designer.cs create mode 100644 NetEvent/Server/Migrations/Sqlite/20230110210600_AddEventTicketType.cs create mode 100644 NetEvent/Server/Models/Purchase.cs create mode 100644 NetEvent/Server/Modules/Events/Endpoints/DeleteEventTicketType.cs create mode 100644 NetEvent/Server/Modules/Events/Endpoints/PostEventTicketType.cs create mode 100644 NetEvent/Server/Modules/Events/Endpoints/PutEventTicketType.cs create mode 100644 NetEvent/Shared/Dto/Event/CurrencyDto.cs create mode 100644 NetEvent/Shared/Dto/Event/EventTicketTypeDto.cs diff --git a/NetEvent/Server.Tests/EventModuleTest.cs b/NetEvent/Server.Tests/EventModuleTest.cs index 4a2288e1..c288bbeb 100644 --- a/NetEvent/Server.Tests/EventModuleTest.cs +++ b/NetEvent/Server.Tests/EventModuleTest.cs @@ -1,10 +1,13 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.Linq; using System.Net.Http; using System.Net.Http.Json; using System.Threading.Tasks; using Bogus; +using NetEvent.Shared; using NetEvent.Shared.Dto.Event; using NetEvent.TestHelper; using Xunit; @@ -138,5 +141,84 @@ public Task EventModuleTest_DeleteEventRoute_Test() }, true); } + + [Fact] + public Task EventModuleTest_PostEventTicketTypeRoute_Test() + { + // Arrange + return RunWithFakeEvents(async fakeEvents => + { + var fakeEventTicketType = Fakers.EventTicketTypeFaker(fakeEvents).Generate(); + + // Act + var postResult = await Client.PostAsJsonAsync($"/api/events/tickettype/{fakeEventTicketType.EventId}", fakeEventTicketType.ToEventTicketTypeDto()).ConfigureAwait(false); + postResult.EnsureSuccessStatusCode(); + var updatedEvent = await Client.GetFromJsonAsync($"/api/events/{fakeEventTicketType.EventId}").ConfigureAwait(false); + + // Assert + Assert.NotNull(updatedEvent?.TicketTypes); + Assert.Equal(1, updatedEvent.TicketTypes.Count); + Assert.Equal(fakeEventTicketType.Name, updatedEvent.TicketTypes.First().Name, StringComparer.Ordinal); + }, + true); + } + + [Fact] + public Task EventModuleTest_PutEventTicketTypeRoute_Test() + { + // Arrange + return RunWithFakeEvents(async fakeEvents => + { + var faker = new Faker(); + var fakeEventTicketType = Fakers.EventTicketTypeFaker(fakeEvents).Generate(); + + var postResult = await Client.PostAsJsonAsync($"/api/events/tickettype/{fakeEventTicketType.EventId}", fakeEventTicketType.ToEventTicketTypeDto()).ConfigureAwait(false); + postResult.EnsureSuccessStatusCode(); + if (int.TryParse(await postResult.Content.ReadAsStringAsync().ConfigureAwait(false), CultureInfo.InvariantCulture, out var newId)) + { + fakeEventTicketType.Id = newId; + } + + fakeEventTicketType.Name = faker.Name.FullName(); + + // Act + var putResult = await Client.PutAsJsonAsync($"/api/events/tickettype/{fakeEventTicketType.Id}", fakeEventTicketType.ToEventTicketTypeDto()).ConfigureAwait(false); + putResult.EnsureSuccessStatusCode(); + var updatedEvent = await Client.GetFromJsonAsync($"/api/events/{fakeEventTicketType.EventId}").ConfigureAwait(false); + + // Assert + Assert.NotNull(updatedEvent?.TicketTypes); + Assert.Equal(1, updatedEvent.TicketTypes.Count); + Assert.Equal(fakeEventTicketType.Name, updatedEvent.TicketTypes.First().Name, StringComparer.Ordinal); + }, + true); + } + + [Fact] + public Task EventModuleTest_DeleteEventTicketTypeRoute_Test() + { + // Arrange + return RunWithFakeEvents(async fakeEvents => + { + var fakeEventTicketType = Fakers.EventTicketTypeFaker(fakeEvents).Generate(); + + var postResult = await Client.PostAsJsonAsync($"/api/events/tickettype/{fakeEventTicketType.EventId}", fakeEventTicketType.ToEventTicketTypeDto()).ConfigureAwait(false); + postResult.EnsureSuccessStatusCode(); + if (int.TryParse(await postResult.Content.ReadAsStringAsync().ConfigureAwait(false), CultureInfo.InvariantCulture, out var newId)) + { + fakeEventTicketType.Id = newId; + } + + // Act + var deleteResult = await Client.DeleteAsync($"/api/events/tickettype/{fakeEventTicketType.Id}").ConfigureAwait(false); + deleteResult.EnsureSuccessStatusCode(); + var updatedEvent = await Client.GetFromJsonAsync($"/api/events/{fakeEventTicketType.EventId}").ConfigureAwait(false); + + // Assert + Assert.NotNull(updatedEvent?.TicketTypes); + Assert.Equal(0, updatedEvent.TicketTypes.Count); + }, + true); + } } } diff --git a/NetEvent/Server/Data/ApplicationDbContext.cs b/NetEvent/Server/Data/ApplicationDbContext.cs index b2c5a249..974d10db 100644 --- a/NetEvent/Server/Data/ApplicationDbContext.cs +++ b/NetEvent/Server/Data/ApplicationDbContext.cs @@ -34,6 +34,8 @@ public ApplicationDbContext(DbContextOptions options, IReadOnlyCollection Venues => Set(); + public virtual DbSet Tickets => Set(); + public override EntityEntry Add(TEntity entity) { return base.Add(entity); diff --git a/NetEvent/Server/Data/Events/EventManager.cs b/NetEvent/Server/Data/Events/EventManager.cs index a96727ae..109fca9f 100644 --- a/NetEvent/Server/Data/Events/EventManager.cs +++ b/NetEvent/Server/Data/Events/EventManager.cs @@ -1,4 +1,5 @@ -using System.Threading; +using System.Linq; +using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -152,5 +153,64 @@ public async Task UpdateVenueAsync(Venue venueToUpdate) _Logger.LogError("Error updating Venue {name}", venueToUpdate.Name); return EventResult.Failed(new EventError()); } + + public async Task CreateTicketAsync(EventTicketType ticketToCreate) + { + var maxId = await _DbContext.Tickets.MaxAsync(x => x.Id); + ticketToCreate.Id = maxId.HasValue ? maxId.Value + 1 : 1; + ticketToCreate.Slug = _SlugHelper.GenerateSlug(ticketToCreate.Name); + + var addResult = await _DbContext.Tickets.AddAsync(ticketToCreate, CancellationToken); + if (addResult.State == EntityState.Added) + { + await _DbContext.SaveChangesAsync(); + _Logger.LogInformation("Successfully created Ticket {name}", ticketToCreate.Name); + return EventResult.Success; + } + + _Logger.LogError("Error creating Ticket {name}", ticketToCreate.Name); + return EventResult.Failed(new EventError()); + } + + public async Task DeleteTicketAsync(long ticketId) + { + var ticketToDelete = await _DbContext.Tickets.FindAsync(ticketId); + if (ticketToDelete == null) + { + return EventResult.Failed(new EventError { Description = $"Ticket with Id '{ticketId}' was not found" }); + } + + _DbContext.Tickets.Remove(ticketToDelete); + await _DbContext.SaveChangesAsync(); + + return EventResult.Success; + } + + public async Task UpdateTicketAsync(EventTicketType ticketToUpdate) + { + var oldTicketType = await _DbContext.Tickets.Where(t => t.Id == ticketToUpdate.Id).Include(t => t.Event).FirstAsync(CancellationToken).ConfigureAwait(false); + if (oldTicketType == null) + { + _Logger.LogError("Error updating Ticket {name} with {id}. It was not found.", ticketToUpdate.Name, ticketToUpdate.Id); + return EventResult.Failed(new EventError()); + } + + ticketToUpdate.Slug = _SlugHelper.GenerateSlug(ticketToUpdate.Name); + ticketToUpdate.EventId = oldTicketType.EventId; + ticketToUpdate.Event = oldTicketType.Event; + _DbContext.Entry(oldTicketType).State = EntityState.Detached; + + var result = _DbContext.Tickets.Update(ticketToUpdate); + + if (result.State == EntityState.Modified) + { + await _DbContext.SaveChangesAsync(); + _Logger.LogInformation("Successfully updated Ticket {name}", ticketToUpdate.Name); + return EventResult.Success; + } + + _Logger.LogError("Error updating Ticket {name}", ticketToUpdate.Name); + return EventResult.Failed(new EventError()); + } } } diff --git a/NetEvent/Server/Data/Events/IEventManager.cs b/NetEvent/Server/Data/Events/IEventManager.cs index 6119a57a..ef9c70e0 100644 --- a/NetEvent/Server/Data/Events/IEventManager.cs +++ b/NetEvent/Server/Data/Events/IEventManager.cs @@ -21,5 +21,11 @@ public interface IEventManager Task DeleteVenueAsync(long venueId); Task UpdateVenueAsync(Venue venueToUpdate); + + Task CreateTicketAsync(EventTicketType ticketToCreate); + + Task DeleteTicketAsync(long ticketId); + + Task UpdateTicketAsync(EventTicketType ticketToUpdate); } } diff --git a/NetEvent/Server/Helpers/DtoMapper.cs b/NetEvent/Server/Helpers/DtoMapper.cs index 922aa24f..21de6bec 100644 --- a/NetEvent/Server/Helpers/DtoMapper.cs +++ b/NetEvent/Server/Helpers/DtoMapper.cs @@ -53,6 +53,10 @@ public static partial class DtoMapper public static partial Event ToEvent(this EventDto eventToConvert); + public static partial EventTicketTypeDto ToEventTicketTypeDto(this EventTicketType eventTicketTypeToConvert); + + public static partial EventTicketType ToEventTicketType(this EventTicketTypeDto eventTicketTypeToConvert); + public static partial VenueDto ToVenueDto(this Venue venue); public static partial Venue ToVenue(this VenueDto venue); diff --git a/NetEvent/Server/Migrations/Psql/20230110210613_AddEventTicketType.Designer.cs b/NetEvent/Server/Migrations/Psql/20230110210613_AddEventTicketType.Designer.cs new file mode 100644 index 00000000..15a7fa44 --- /dev/null +++ b/NetEvent/Server/Migrations/Psql/20230110210613_AddEventTicketType.Designer.cs @@ -0,0 +1,740 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NetEvent.Server.Data; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace NetEvent.Server.Migrations.Psql +{ + [DbContext(typeof(PsqlApplicationDbContext))] + [Migration("20230110210613_AddEventTicketType")] + partial class AddEventTicketType + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", (string)null); + + b.HasData( + new + { + Id = 1, + ClaimType = "Admin.Users.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 2, + ClaimType = "Admin.Users.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 3, + ClaimType = "Admin.Roles.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 4, + ClaimType = "Admin.Roles.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 5, + ClaimType = "Admin.System.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 6, + ClaimType = "Admin.System.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 7, + ClaimType = "Admin.Images.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 8, + ClaimType = "Admin.Images.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 9, + ClaimType = "Admin.Events.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 10, + ClaimType = "Admin.Events.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 11, + ClaimType = "Admin.Venues.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 12, + ClaimType = "Admin.Venues.Write", + ClaimValue = "", + RoleId = "admin" + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoles", (string)null); + + b.HasData( + new + { + UserId = "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + RoleId = "admin" + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserTokens", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.ApplicationRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("IsDefault") + .HasColumnType("boolean"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("Role", (string)null); + + b.HasData( + new + { + Id = "user", + IsDefault = true, + Name = "User", + NormalizedName = "USER" + }, + new + { + Id = "orga", + IsDefault = false, + Name = "Orga", + NormalizedName = "ORGA" + }, + new + { + Id = "admin", + IsDefault = false, + Name = "Admin", + NormalizedName = "ADMIN" + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("FirstName") + .HasColumnType("text"); + + b.Property("LastName") + .HasColumnType("text"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("ProfilePicture") + .HasColumnType("bytea"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("User", (string)null); + + b.HasData( + new + { + Id = "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + AccessFailedCount = 0, + ConcurrencyStamp = "f04ce91e-9530-4345-8cb6-ca7064b18f9e", + Email = "admin@admin.de", + EmailConfirmed = true, + FirstName = "Admin", + LastName = "istrator", + LockoutEnabled = false, + NormalizedEmail = "ADMIN@ADMIN.DE", + NormalizedUserName = "ADMIN", + PasswordHash = "AQAAAAIAAYagAAAAEBQZqmlKIsoqJXLPAEONrg4qS/LiDqczL05LikcpplHSrajOE+VxOsnzvK2Xq5bxig==", + PhoneNumberConfirmed = false, + SecurityStamp = "9529d94c-3a1d-4616-b977-af03e35856e8", + TwoFactorEnabled = false, + UserName = "admin" + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.EmailTemplate", b => + { + b.Property("TemplateId") + .HasColumnType("text"); + + b.Property("ContentTemplate") + .IsRequired() + .HasColumnType("text"); + + b.Property("SubjectTemplate") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("TemplateId"); + + b.ToTable("EmailTemplates", (string)null); + + b.HasData( + new + { + TemplateId = "UserEmailConfirmEmailTemplate", + ContentTemplate = "

@Model.TemplateVariables[\"firstName\"], welcome to NetEvent.

\n

Please confirm your E-Mail by clicking on the following link:

@Model.TemplateVariables[\"confirmUrl\"] ", + SubjectTemplate = "@Model.TemplateVariables[\"firstName\"], please confirm your E-Mail address." + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("EventFormat") + .HasColumnType("integer"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("ShortDescription") + .HasColumnType("text"); + + b.Property("Slug") + .HasColumnType("text"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("State") + .HasColumnType("integer"); + + b.Property("VenueId") + .HasColumnType("bigint"); + + b.Property("Visibility") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("Slug") + .IsUnique(); + + b.HasIndex("VenueId"); + + b.ToTable("Events", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.EventTicketType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AvailableTickets") + .HasColumnType("bigint"); + + b.Property("Currency") + .HasColumnType("integer"); + + b.Property("EventId") + .HasColumnType("bigint"); + + b.Property("IsGiftable") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("integer"); + + b.Property("SellEndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SellStartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Slug") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("EventId"); + + b.ToTable("EventTicketTypes", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.SystemImage", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Data") + .HasColumnType("bytea"); + + b.Property("Extension") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("UploadTime") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("SystemImages", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.SystemSettingValue", b => + { + b.Property("Key") + .HasColumnType("text"); + + b.Property("SerializedValue") + .HasColumnType("text"); + + b.HasKey("Key"); + + b.ToTable("SystemSettings", (string)null); + + b.HasData( + new + { + Key = "OrganizationName", + SerializedValue = "NetEvent" + }, + new + { + Key = "HideOrganizationNameInNavBar", + SerializedValue = "False" + }, + new + { + Key = "DataCultureInfo", + SerializedValue = "en-US" + }, + new + { + Key = "Favicon", + SerializedValue = "" + }, + new + { + Key = "Logo", + SerializedValue = "" + }, + new + { + Key = "AboutUs", + SerializedValue = "" + }, + new + { + Key = "LegalNotice", + SerializedValue = "" + }, + new + { + Key = "PrivacyPolicy", + SerializedValue = "" + }, + new + { + Key = "PrimaryColor", + SerializedValue = "" + }, + new + { + Key = "PrimaryTextColor", + SerializedValue = "" + }, + new + { + Key = "SecondaryColor", + SerializedValue = "" + }, + new + { + Key = "SecondaryTextColor", + SerializedValue = "" + }, + new + { + Key = "Background", + SerializedValue = "" + }, + new + { + Key = "AppbarBackground", + SerializedValue = "" + }, + new + { + Key = "AppbarText", + SerializedValue = "" + }, + new + { + Key = "CustomCss", + SerializedValue = "" + }, + new + { + Key = "Standard", + SerializedValue = "True" + }, + new + { + Key = "Steam", + SerializedValue = "False" + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Venue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("City") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("text"); + + b.Property("Slug") + .HasColumnType("text"); + + b.Property("Street") + .HasColumnType("text"); + + b.Property("ZipCode") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Venues", (string)null); + }); + + modelBuilder.Entity("NetEvent.Shared.Dto.ThemeDto", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ThemeData") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Themes", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.HasOne("NetEvent.Server.Models.Venue", "Venue") + .WithMany() + .HasForeignKey("VenueId"); + + b.Navigation("Venue"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.EventTicketType", b => + { + b.HasOne("NetEvent.Server.Models.Event", "Event") + .WithMany("TicketTypes") + .HasForeignKey("EventId"); + + b.Navigation("Event"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.Navigation("TicketTypes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/NetEvent/Server/Migrations/Psql/20230110210613_AddEventTicketType.cs b/NetEvent/Server/Migrations/Psql/20230110210613_AddEventTicketType.cs new file mode 100644 index 00000000..a62d414e --- /dev/null +++ b/NetEvent/Server/Migrations/Psql/20230110210613_AddEventTicketType.cs @@ -0,0 +1,120 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace NetEvent.Server.Migrations.Psql +{ + /// + public partial class AddEventTicketType : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "eventFormat", + table: "Events", + newName: "EventFormat"); + + migrationBuilder.CreateTable( + name: "EventTicketTypes", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Name = table.Column(type: "text", nullable: true), + Slug = table.Column(type: "text", nullable: true), + Price = table.Column(type: "integer", nullable: false), + Currency = table.Column(type: "integer", nullable: false), + AvailableTickets = table.Column(type: "bigint", nullable: false), + SellStartDate = table.Column(type: "timestamp with time zone", nullable: false), + SellEndDate = table.Column(type: "timestamp with time zone", nullable: false), + IsGiftable = table.Column(type: "boolean", nullable: false), + EventId = table.Column(type: "bigint", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EventTicketTypes", x => x.Id); + table.ForeignKey( + name: "FK_EventTicketTypes_Events_EventId", + column: x => x.EventId, + principalTable: "Events", + principalColumn: "Id"); + }); + + migrationBuilder.UpdateData( + table: "RoleClaims", + keyColumn: "Id", + keyValue: 8, + column: "ClaimType", + value: "Admin.Images.Write"); + + migrationBuilder.UpdateData( + table: "RoleClaims", + keyColumn: "Id", + keyValue: 10, + column: "ClaimType", + value: "Admin.Events.Write"); + + migrationBuilder.UpdateData( + table: "RoleClaims", + keyColumn: "Id", + keyValue: 12, + column: "ClaimType", + value: "Admin.Venues.Write"); + + migrationBuilder.UpdateData( + table: "User", + keyColumn: "Id", + keyValue: "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + columns: new[] { "ConcurrencyStamp", "PasswordHash", "SecurityStamp" }, + values: new object[] { "f04ce91e-9530-4345-8cb6-ca7064b18f9e", "AQAAAAIAAYagAAAAEBQZqmlKIsoqJXLPAEONrg4qS/LiDqczL05LikcpplHSrajOE+VxOsnzvK2Xq5bxig==", "9529d94c-3a1d-4616-b977-af03e35856e8" }); + + migrationBuilder.CreateIndex( + name: "IX_EventTicketTypes_EventId", + table: "EventTicketTypes", + column: "EventId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "EventTicketTypes"); + + migrationBuilder.RenameColumn( + name: "EventFormat", + table: "Events", + newName: "eventFormat"); + + migrationBuilder.UpdateData( + table: "RoleClaims", + keyColumn: "Id", + keyValue: 8, + column: "ClaimType", + value: "Admin.Images.Edit"); + + migrationBuilder.UpdateData( + table: "RoleClaims", + keyColumn: "Id", + keyValue: 10, + column: "ClaimType", + value: "Admin.Events.Edit"); + + migrationBuilder.UpdateData( + table: "RoleClaims", + keyColumn: "Id", + keyValue: 12, + column: "ClaimType", + value: "Admin.Venues.Edit"); + + migrationBuilder.UpdateData( + table: "User", + keyColumn: "Id", + keyValue: "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + columns: new[] { "ConcurrencyStamp", "PasswordHash", "SecurityStamp" }, + values: new object[] { "9b5238c9-c5a4-4790-8eb0-b78510682b41", "AQAAAAIAAYagAAAAEN5rDB2K6wk0FXO84PGiPx3h+VPc4QgpcSbFjQMFGAKW4SU+0nIM5Ee+5MXgDpZs1w==", "34e28843-865a-4bed-a77e-0d90d60b7547" }); + } + } +} diff --git a/NetEvent/Server/Migrations/Psql/PsqlApplicationDbContextModelSnapshot.cs b/NetEvent/Server/Migrations/Psql/PsqlApplicationDbContextModelSnapshot.cs index 109ac7d9..1417c170 100644 --- a/NetEvent/Server/Migrations/Psql/PsqlApplicationDbContextModelSnapshot.cs +++ b/NetEvent/Server/Migrations/Psql/PsqlApplicationDbContextModelSnapshot.cs @@ -17,7 +17,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "7.0.0") + .HasAnnotation("ProductVersion", "7.0.1") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); @@ -99,7 +99,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) new { Id = 8, - ClaimType = "Admin.Images.Edit", + ClaimType = "Admin.Images.Write", ClaimValue = "", RoleId = "admin" }, @@ -113,7 +113,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) new { Id = 10, - ClaimType = "Admin.Events.Edit", + ClaimType = "Admin.Events.Write", ClaimValue = "", RoleId = "admin" }, @@ -127,7 +127,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) new { Id = 12, - ClaimType = "Admin.Venues.Edit", + ClaimType = "Admin.Venues.Write", ClaimValue = "", RoleId = "admin" }); @@ -354,7 +354,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { Id = "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", AccessFailedCount = 0, - ConcurrencyStamp = "9b5238c9-c5a4-4790-8eb0-b78510682b41", + ConcurrencyStamp = "f04ce91e-9530-4345-8cb6-ca7064b18f9e", Email = "admin@admin.de", EmailConfirmed = true, FirstName = "Admin", @@ -362,9 +362,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) LockoutEnabled = false, NormalizedEmail = "ADMIN@ADMIN.DE", NormalizedUserName = "ADMIN", - PasswordHash = "AQAAAAIAAYagAAAAEN5rDB2K6wk0FXO84PGiPx3h+VPc4QgpcSbFjQMFGAKW4SU+0nIM5Ee+5MXgDpZs1w==", + PasswordHash = "AQAAAAIAAYagAAAAEBQZqmlKIsoqJXLPAEONrg4qS/LiDqczL05LikcpplHSrajOE+VxOsnzvK2Xq5bxig==", PhoneNumberConfirmed = false, - SecurityStamp = "34e28843-865a-4bed-a77e-0d90d60b7547", + SecurityStamp = "9529d94c-3a1d-4616-b977-af03e35856e8", TwoFactorEnabled = false, UserName = "admin" }); @@ -410,6 +410,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("EndDate") .HasColumnType("timestamp with time zone"); + b.Property("EventFormat") + .HasColumnType("integer"); + b.Property("Name") .HasColumnType("text"); @@ -431,9 +434,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Visibility") .HasColumnType("integer"); - b.Property("eventFormat") - .HasColumnType("integer"); - b.HasKey("Id"); b.HasIndex("Slug") @@ -444,6 +444,48 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("Events", (string)null); }); + modelBuilder.Entity("NetEvent.Server.Models.EventTicketType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AvailableTickets") + .HasColumnType("bigint"); + + b.Property("Currency") + .HasColumnType("integer"); + + b.Property("EventId") + .HasColumnType("bigint"); + + b.Property("IsGiftable") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("integer"); + + b.Property("SellEndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SellStartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Slug") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("EventId"); + + b.ToTable("EventTicketTypes", (string)null); + }); + modelBuilder.Entity("NetEvent.Server.Models.SystemImage", b => { b.Property("Id") @@ -485,6 +527,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) SerializedValue = "NetEvent" }, new + { + Key = "HideOrganizationNameInNavBar", + SerializedValue = "False" + }, + new { Key = "DataCultureInfo", SerializedValue = "en-US" @@ -500,11 +547,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) SerializedValue = "" }, new - { - Key = "HideOrganizationNameInNavBar", - SerializedValue = "False" - }, - new { Key = "AboutUs", SerializedValue = "" @@ -675,6 +717,20 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Venue"); }); + + modelBuilder.Entity("NetEvent.Server.Models.EventTicketType", b => + { + b.HasOne("NetEvent.Server.Models.Event", "Event") + .WithMany("TicketTypes") + .HasForeignKey("EventId"); + + b.Navigation("Event"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.Navigation("TicketTypes"); + }); #pragma warning restore 612, 618 } } diff --git a/NetEvent/Server/Migrations/Sqlite/20230110210600_AddEventTicketType.Designer.cs b/NetEvent/Server/Migrations/Sqlite/20230110210600_AddEventTicketType.Designer.cs new file mode 100644 index 00000000..fa880310 --- /dev/null +++ b/NetEvent/Server/Migrations/Sqlite/20230110210600_AddEventTicketType.Designer.cs @@ -0,0 +1,725 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NetEvent.Server.Data; + +#nullable disable + +namespace NetEvent.Server.Migrations.Sqlite +{ + [DbContext(typeof(SqliteApplicationDbContext))] + [Migration("20230110210600_AddEventTicketType")] + partial class AddEventTicketType + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.1"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", (string)null); + + b.HasData( + new + { + Id = 1, + ClaimType = "Admin.Users.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 2, + ClaimType = "Admin.Users.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 3, + ClaimType = "Admin.Roles.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 4, + ClaimType = "Admin.Roles.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 5, + ClaimType = "Admin.System.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 6, + ClaimType = "Admin.System.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 7, + ClaimType = "Admin.Images.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 8, + ClaimType = "Admin.Images.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 9, + ClaimType = "Admin.Events.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 10, + ClaimType = "Admin.Events.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 11, + ClaimType = "Admin.Venues.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 12, + ClaimType = "Admin.Venues.Write", + ClaimValue = "", + RoleId = "admin" + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoles", (string)null); + + b.HasData( + new + { + UserId = "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + RoleId = "admin" + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserTokens", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.ApplicationRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("IsDefault") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("Role", (string)null); + + b.HasData( + new + { + Id = "user", + IsDefault = true, + Name = "User", + NormalizedName = "USER" + }, + new + { + Id = "orga", + IsDefault = false, + Name = "Orga", + NormalizedName = "ORGA" + }, + new + { + Id = "admin", + IsDefault = false, + Name = "Admin", + NormalizedName = "ADMIN" + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("FirstName") + .HasColumnType("TEXT"); + + b.Property("LastName") + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProfilePicture") + .HasColumnType("BLOB"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("User", (string)null); + + b.HasData( + new + { + Id = "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + AccessFailedCount = 0, + ConcurrencyStamp = "26cbb106-629e-4b0f-b528-03e4fbaf148e", + Email = "admin@admin.de", + EmailConfirmed = true, + FirstName = "Admin", + LastName = "istrator", + LockoutEnabled = false, + NormalizedEmail = "ADMIN@ADMIN.DE", + NormalizedUserName = "ADMIN", + PasswordHash = "AQAAAAIAAYagAAAAEMVeCrEoGoqMFSa9mWv07gyORfXVq9Zash81NSc3Z4QmFWadfMKOABkphkaem7Q7nQ==", + PhoneNumberConfirmed = false, + SecurityStamp = "56b690d3-1bb2-4ef1-8fde-0397861a166b", + TwoFactorEnabled = false, + UserName = "admin" + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.EmailTemplate", b => + { + b.Property("TemplateId") + .HasColumnType("TEXT"); + + b.Property("ContentTemplate") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SubjectTemplate") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("TemplateId"); + + b.ToTable("EmailTemplates", (string)null); + + b.HasData( + new + { + TemplateId = "UserEmailConfirmEmailTemplate", + ContentTemplate = "

@Model.TemplateVariables[\"firstName\"], welcome to NetEvent.

\n

Please confirm your E-Mail by clicking on the following link:

@Model.TemplateVariables[\"confirmUrl\"] ", + SubjectTemplate = "@Model.TemplateVariables[\"firstName\"], please confirm your E-Mail address." + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("EventFormat") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("ShortDescription") + .HasColumnType("TEXT"); + + b.Property("Slug") + .HasColumnType("TEXT"); + + b.Property("StartDate") + .HasColumnType("TEXT"); + + b.Property("State") + .HasColumnType("INTEGER"); + + b.Property("VenueId") + .HasColumnType("INTEGER"); + + b.Property("Visibility") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("Slug") + .IsUnique(); + + b.HasIndex("VenueId"); + + b.ToTable("Events", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.EventTicketType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AvailableTickets") + .HasColumnType("INTEGER"); + + b.Property("Currency") + .HasColumnType("INTEGER"); + + b.Property("EventId") + .HasColumnType("INTEGER"); + + b.Property("IsGiftable") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("SellEndDate") + .HasColumnType("TEXT"); + + b.Property("SellStartDate") + .HasColumnType("TEXT"); + + b.Property("Slug") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EventId"); + + b.ToTable("EventTicketTypes", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.SystemImage", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Data") + .HasColumnType("BLOB"); + + b.Property("Extension") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("UploadTime") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("SystemImages", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.SystemSettingValue", b => + { + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("SerializedValue") + .HasColumnType("TEXT"); + + b.HasKey("Key"); + + b.ToTable("SystemSettings", (string)null); + + b.HasData( + new + { + Key = "OrganizationName", + SerializedValue = "NetEvent" + }, + new + { + Key = "HideOrganizationNameInNavBar", + SerializedValue = "False" + }, + new + { + Key = "DataCultureInfo", + SerializedValue = "en-US" + }, + new + { + Key = "Favicon", + SerializedValue = "" + }, + new + { + Key = "Logo", + SerializedValue = "" + }, + new + { + Key = "AboutUs", + SerializedValue = "" + }, + new + { + Key = "LegalNotice", + SerializedValue = "" + }, + new + { + Key = "PrivacyPolicy", + SerializedValue = "" + }, + new + { + Key = "PrimaryColor", + SerializedValue = "" + }, + new + { + Key = "PrimaryTextColor", + SerializedValue = "" + }, + new + { + Key = "SecondaryColor", + SerializedValue = "" + }, + new + { + Key = "SecondaryTextColor", + SerializedValue = "" + }, + new + { + Key = "Background", + SerializedValue = "" + }, + new + { + Key = "AppbarBackground", + SerializedValue = "" + }, + new + { + Key = "AppbarText", + SerializedValue = "" + }, + new + { + Key = "CustomCss", + SerializedValue = "" + }, + new + { + Key = "Standard", + SerializedValue = "True" + }, + new + { + Key = "Steam", + SerializedValue = "False" + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Venue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("City") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Number") + .HasColumnType("TEXT"); + + b.Property("Slug") + .HasColumnType("TEXT"); + + b.Property("Street") + .HasColumnType("TEXT"); + + b.Property("ZipCode") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Venues", (string)null); + }); + + modelBuilder.Entity("NetEvent.Shared.Dto.ThemeDto", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ThemeData") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Themes", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.HasOne("NetEvent.Server.Models.Venue", "Venue") + .WithMany() + .HasForeignKey("VenueId"); + + b.Navigation("Venue"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.EventTicketType", b => + { + b.HasOne("NetEvent.Server.Models.Event", "Event") + .WithMany("TicketTypes") + .HasForeignKey("EventId"); + + b.Navigation("Event"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.Navigation("TicketTypes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/NetEvent/Server/Migrations/Sqlite/20230110210600_AddEventTicketType.cs b/NetEvent/Server/Migrations/Sqlite/20230110210600_AddEventTicketType.cs new file mode 100644 index 00000000..ca54c478 --- /dev/null +++ b/NetEvent/Server/Migrations/Sqlite/20230110210600_AddEventTicketType.cs @@ -0,0 +1,119 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace NetEvent.Server.Migrations.Sqlite +{ + /// + public partial class AddEventTicketType : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "eventFormat", + table: "Events", + newName: "EventFormat"); + + migrationBuilder.CreateTable( + name: "EventTicketTypes", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Name = table.Column(type: "TEXT", nullable: true), + Slug = table.Column(type: "TEXT", nullable: true), + Price = table.Column(type: "INTEGER", nullable: false), + Currency = table.Column(type: "INTEGER", nullable: false), + AvailableTickets = table.Column(type: "INTEGER", nullable: false), + SellStartDate = table.Column(type: "TEXT", nullable: false), + SellEndDate = table.Column(type: "TEXT", nullable: false), + IsGiftable = table.Column(type: "INTEGER", nullable: false), + EventId = table.Column(type: "INTEGER", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EventTicketTypes", x => x.Id); + table.ForeignKey( + name: "FK_EventTicketTypes_Events_EventId", + column: x => x.EventId, + principalTable: "Events", + principalColumn: "Id"); + }); + + migrationBuilder.UpdateData( + table: "RoleClaims", + keyColumn: "Id", + keyValue: 8, + column: "ClaimType", + value: "Admin.Images.Write"); + + migrationBuilder.UpdateData( + table: "RoleClaims", + keyColumn: "Id", + keyValue: 10, + column: "ClaimType", + value: "Admin.Events.Write"); + + migrationBuilder.UpdateData( + table: "RoleClaims", + keyColumn: "Id", + keyValue: 12, + column: "ClaimType", + value: "Admin.Venues.Write"); + + migrationBuilder.UpdateData( + table: "User", + keyColumn: "Id", + keyValue: "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + columns: new[] { "ConcurrencyStamp", "PasswordHash", "SecurityStamp" }, + values: new object[] { "26cbb106-629e-4b0f-b528-03e4fbaf148e", "AQAAAAIAAYagAAAAEMVeCrEoGoqMFSa9mWv07gyORfXVq9Zash81NSc3Z4QmFWadfMKOABkphkaem7Q7nQ==", "56b690d3-1bb2-4ef1-8fde-0397861a166b" }); + + migrationBuilder.CreateIndex( + name: "IX_EventTicketTypes_EventId", + table: "EventTicketTypes", + column: "EventId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "EventTicketTypes"); + + migrationBuilder.RenameColumn( + name: "EventFormat", + table: "Events", + newName: "eventFormat"); + + migrationBuilder.UpdateData( + table: "RoleClaims", + keyColumn: "Id", + keyValue: 8, + column: "ClaimType", + value: "Admin.Images.Edit"); + + migrationBuilder.UpdateData( + table: "RoleClaims", + keyColumn: "Id", + keyValue: 10, + column: "ClaimType", + value: "Admin.Events.Edit"); + + migrationBuilder.UpdateData( + table: "RoleClaims", + keyColumn: "Id", + keyValue: 12, + column: "ClaimType", + value: "Admin.Venues.Edit"); + + migrationBuilder.UpdateData( + table: "User", + keyColumn: "Id", + keyValue: "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + columns: new[] { "ConcurrencyStamp", "PasswordHash", "SecurityStamp" }, + values: new object[] { "f205a4d6-cbab-4163-9427-32802498bc59", "AQAAAAIAAYagAAAAEF+OwzkcGgbWzhEmVd7Xy0iRHQU842tguftE2WfkQvSDLy8ZHNXzDqg57vVgrCdioA==", "a9023bf7-6259-40e8-a944-8aae466e9709" }); + } + } +} diff --git a/NetEvent/Server/Migrations/Sqlite/SqliteApplicationDbContextModelSnapshot.cs b/NetEvent/Server/Migrations/Sqlite/SqliteApplicationDbContextModelSnapshot.cs index ee970d15..73705028 100644 --- a/NetEvent/Server/Migrations/Sqlite/SqliteApplicationDbContextModelSnapshot.cs +++ b/NetEvent/Server/Migrations/Sqlite/SqliteApplicationDbContextModelSnapshot.cs @@ -15,7 +15,7 @@ partial class SqliteApplicationDbContextModelSnapshot : ModelSnapshot protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "7.0.0"); + modelBuilder.HasAnnotation("ProductVersion", "7.0.1"); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { @@ -92,7 +92,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) new { Id = 8, - ClaimType = "Admin.Images.Edit", + ClaimType = "Admin.Images.Write", ClaimValue = "", RoleId = "admin" }, @@ -106,7 +106,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) new { Id = 10, - ClaimType = "Admin.Events.Edit", + ClaimType = "Admin.Events.Write", ClaimValue = "", RoleId = "admin" }, @@ -120,7 +120,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) new { Id = 12, - ClaimType = "Admin.Venues.Edit", + ClaimType = "Admin.Venues.Write", ClaimValue = "", RoleId = "admin" }); @@ -345,7 +345,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { Id = "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", AccessFailedCount = 0, - ConcurrencyStamp = "f205a4d6-cbab-4163-9427-32802498bc59", + ConcurrencyStamp = "26cbb106-629e-4b0f-b528-03e4fbaf148e", Email = "admin@admin.de", EmailConfirmed = true, FirstName = "Admin", @@ -353,9 +353,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) LockoutEnabled = false, NormalizedEmail = "ADMIN@ADMIN.DE", NormalizedUserName = "ADMIN", - PasswordHash = "AQAAAAIAAYagAAAAEF+OwzkcGgbWzhEmVd7Xy0iRHQU842tguftE2WfkQvSDLy8ZHNXzDqg57vVgrCdioA==", + PasswordHash = "AQAAAAIAAYagAAAAEMVeCrEoGoqMFSa9mWv07gyORfXVq9Zash81NSc3Z4QmFWadfMKOABkphkaem7Q7nQ==", PhoneNumberConfirmed = false, - SecurityStamp = "a9023bf7-6259-40e8-a944-8aae466e9709", + SecurityStamp = "56b690d3-1bb2-4ef1-8fde-0397861a166b", TwoFactorEnabled = false, UserName = "admin" }); @@ -399,6 +399,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("EndDate") .HasColumnType("TEXT"); + b.Property("EventFormat") + .HasColumnType("INTEGER"); + b.Property("Name") .HasColumnType("TEXT"); @@ -420,9 +423,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Visibility") .HasColumnType("INTEGER"); - b.Property("eventFormat") - .HasColumnType("INTEGER"); - b.HasKey("Id"); b.HasIndex("Slug") @@ -433,6 +433,46 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("Events", (string)null); }); + modelBuilder.Entity("NetEvent.Server.Models.EventTicketType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AvailableTickets") + .HasColumnType("INTEGER"); + + b.Property("Currency") + .HasColumnType("INTEGER"); + + b.Property("EventId") + .HasColumnType("INTEGER"); + + b.Property("IsGiftable") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("SellEndDate") + .HasColumnType("TEXT"); + + b.Property("SellStartDate") + .HasColumnType("TEXT"); + + b.Property("Slug") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EventId"); + + b.ToTable("EventTicketTypes", (string)null); + }); + modelBuilder.Entity("NetEvent.Server.Models.SystemImage", b => { b.Property("Id") @@ -474,6 +514,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) SerializedValue = "NetEvent" }, new + { + Key = "HideOrganizationNameInNavBar", + SerializedValue = "False" + }, + new { Key = "DataCultureInfo", SerializedValue = "en-US" @@ -489,11 +534,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) SerializedValue = "" }, new - { - Key = "HideOrganizationNameInNavBar", - SerializedValue = "False" - }, - new { Key = "AboutUs", SerializedValue = "" @@ -662,6 +702,20 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Venue"); }); + + modelBuilder.Entity("NetEvent.Server.Models.EventTicketType", b => + { + b.HasOne("NetEvent.Server.Models.Event", "Event") + .WithMany("TicketTypes") + .HasForeignKey("EventId"); + + b.Navigation("Event"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.Navigation("TicketTypes"); + }); #pragma warning restore 612, 618 } } diff --git a/NetEvent/Server/Models/Event.cs b/NetEvent/Server/Models/Event.cs index 7136c029..84dd1e1f 100644 --- a/NetEvent/Server/Models/Event.cs +++ b/NetEvent/Server/Models/Event.cs @@ -1,7 +1,9 @@ using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Hosting; namespace NetEvent.Server.Models { @@ -33,5 +35,8 @@ public class Event [ForeignKey(nameof(VenueId))] public Venue? Venue { get; set; } + + [InverseProperty(nameof(EventTicketType.Event))] + public List? TicketTypes { get; set; } } } diff --git a/NetEvent/Server/Models/Purchase.cs b/NetEvent/Server/Models/Purchase.cs new file mode 100644 index 00000000..ca56e427 --- /dev/null +++ b/NetEvent/Server/Models/Purchase.cs @@ -0,0 +1,153 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace NetEvent.Server.Models; + +public class Payment +{ + [Key] + public long? Id { get; set; } + + public DateTime PaymentDate { get; set; } + + public long? PurchaseId { get; set; } + + [ForeignKey(nameof(PurchaseId))] + public Purchase? Purchase { get; set; } +} + +public enum PaymentStatus +{ + Pending, + Payed, +} + +public class Refund +{ + [Key] + public long? Id { get; set; } + + public DateTime RefundDate { get; set; } +} + +public enum RefundStatus +{ + Pending, + Refunded, +} + +public class TicketPurchaseRefund +{ + [Key] + public long? Id { get; set; } + + public long? RefundId { get; set; } + + [ForeignKey(nameof(RefundId))] + public Refund? Refund { get; set; } + + public long? TicketPurchaseId { get; set; } + + [ForeignKey(nameof(TicketPurchaseId))] + public TicketPurchase? TicketPurchase { get; set; } +} + +public class Purchase +{ + [Key] + public long? Id { get; set; } + + public DateTime? PurchaseTime { get; set; } + + public long? UserId { get; set; } + + [ForeignKey(nameof(UserId))] + public ApplicationUser? User { get; set; } +} + +public class TicketPurchase +{ + [Key] + public long? Id { get; set; } + + public long? TicketId { get; set; } + + [ForeignKey(nameof(TicketId))] + public EventTicketType? Ticket { get; set; } + + public long? PurchaseId { get; set; } + + [ForeignKey(nameof(PurchaseId))] + public Purchase? Purchase { get; set; } + + public int Price { get; set; } + + public Currency Currency { get; set; } +} + +public class EventTicketType +{ + [Key] + public long? Id { get; set; } + + public string? Name { get; set; } + + public string? Slug { get; set; } + + public int Price { get; set; } + + public Currency Currency { get; set; } + + public long AvailableTickets { get; set; } + + public DateTime SellStartDate { get; set; } + + public DateTime SellEndDate { get; set; } + + public bool IsGiftable { get; set; } + + public long? EventId { get; set; } + + [ForeignKey(nameof(EventId))] + public Event? Event { get; set; } +} + +public class EventTicket +{ + [Key] + public long? Id { get; set; } + + public long? UserId { get; set; } + + [ForeignKey(nameof(UserId))] + public ApplicationUser? User { get; set; } + + public long? TicketPurchaseId { get; set; } + + [ForeignKey(nameof(TicketPurchaseId))] + public TicketPurchase? TicketPurchase { get; set; } + + public long? GiftedTicketId { get; set; } + + [ForeignKey(nameof(GiftedTicketId))] + public EventTicket? GiftedTicket { get; set; } +} + +public class EventParticipant +{ + [Key] + public long? Id { get; set; } + + public DateTime Created { get; set; } + + public long? TicketId { get; set; } + + [ForeignKey(nameof(TicketId))] + public EventTicket? Ticket { get; set; } +} + +public enum Currency +{ + Euro, +} diff --git a/NetEvent/Server/Modules/Events/Endpoints/DeleteEventTicketType.cs b/NetEvent/Server/Modules/Events/Endpoints/DeleteEventTicketType.cs new file mode 100644 index 00000000..f4a449fa --- /dev/null +++ b/NetEvent/Server/Modules/Events/Endpoints/DeleteEventTicketType.cs @@ -0,0 +1,54 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using NetEvent.Server.Data.Events; + +namespace NetEvent.Server.Modules.Events.Endpoints +{ + + public static class DeleteEventTicketType + { + public sealed class Handler : IRequestHandler + { + private readonly IEventManager _EventManager; + + public Handler(IEventManager eventManager) + { + _EventManager = eventManager; + } + + public async Task Handle(Request request, CancellationToken cancellationToken) + { + var result = await _EventManager.DeleteTicketAsync(request.EventTicketTypeId).ConfigureAwait(false); + if (!result.Succeeded) + { + return new Response(ReturnType.Error, string.Join(Environment.NewLine, result.Errors)); + } + + return new Response(); + } + } + + public sealed class Request : IRequest + { + public Request(long eventTicketTypeId) + { + EventTicketTypeId = eventTicketTypeId; + } + + public long EventTicketTypeId { get; } + } + + public sealed class Response : ResponseBase + { + public Response() + { + } + + public Response(ReturnType returnType, string error) : base(returnType, error) + { + } + } + } +} diff --git a/NetEvent/Server/Modules/Events/Endpoints/GetEvent.cs b/NetEvent/Server/Modules/Events/Endpoints/GetEvent.cs index 2c6bfa50..ca93a343 100644 --- a/NetEvent/Server/Modules/Events/Endpoints/GetEvent.cs +++ b/NetEvent/Server/Modules/Events/Endpoints/GetEvent.cs @@ -3,6 +3,7 @@ using System.Threading; using System.Threading.Tasks; using MediatR; +using Microsoft.EntityFrameworkCore; using NetEvent.Server.Data; using NetEvent.Shared; using NetEvent.Shared.Dto.Event; @@ -25,11 +26,11 @@ public async Task Handle(Request request, CancellationToken cancellati Models.Event? eventModel; if (request.Slug != null) { - eventModel = _DbContext.Events.Where(e => e.Slug != null && e.Slug.Equals(request.Slug, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); + eventModel = await _DbContext.Events.Where(e => e.Slug != null && e.Slug.Equals(request.Slug, StringComparison.OrdinalIgnoreCase)).Include(e => e.TicketTypes).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); } else { - eventModel = await _DbContext.Events.FindAsync(new object[] { request.Id }, cancellationToken); + eventModel = await _DbContext.Events.Where(x => x.Id == request.Id).Include(e => e.TicketTypes).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); } if (eventModel == null) diff --git a/NetEvent/Server/Modules/Events/Endpoints/PostEventTicketType.cs b/NetEvent/Server/Modules/Events/Endpoints/PostEventTicketType.cs new file mode 100644 index 00000000..ebe0177e --- /dev/null +++ b/NetEvent/Server/Modules/Events/Endpoints/PostEventTicketType.cs @@ -0,0 +1,62 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using NetEvent.Server.Data.Events; +using NetEvent.Shared; +using NetEvent.Shared.Dto.Event; + +namespace NetEvent.Server.Modules.Events.Endpoints +{ + + public static class PostEventTicketType + { + public sealed class Handler : IRequestHandler + { + private readonly IEventManager _EventManager; + + public Handler(IEventManager eventManager) + { + _EventManager = eventManager; + } + + public async Task Handle(Request request, CancellationToken cancellationToken) + { + var newEventTicketType = request.EventTicketType.ToEventTicketType(); + newEventTicketType.EventId = request.EventId; + + var result = await _EventManager.CreateTicketAsync(newEventTicketType).ConfigureAwait(false); + if (!result.Succeeded || newEventTicketType.Id == null) + { + return new Response(ReturnType.Error, string.Join(Environment.NewLine, result.Errors)); + } + + return new Response(newEventTicketType.Id!.Value); + } + } + + public sealed class Request : IRequest + { + public Request(long eventId, EventTicketTypeDto eventTicketTypeDto) + { + EventId = eventId; + EventTicketType = eventTicketTypeDto; + } + + public long EventId { get; } + + public EventTicketTypeDto EventTicketType { get; } + } + + public sealed class Response : ResponseBase + { + public Response(long createdEventTicketTypeId) : base(createdEventTicketTypeId) + { + } + + public Response(ReturnType returnType, string error) : base(returnType, error) + { + } + } + } +} diff --git a/NetEvent/Server/Modules/Events/Endpoints/PutEventTicketType.cs b/NetEvent/Server/Modules/Events/Endpoints/PutEventTicketType.cs new file mode 100644 index 00000000..bf1e0903 --- /dev/null +++ b/NetEvent/Server/Modules/Events/Endpoints/PutEventTicketType.cs @@ -0,0 +1,61 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using NetEvent.Server.Data.Events; +using NetEvent.Shared; +using NetEvent.Shared.Dto.Event; + +namespace NetEvent.Server.Modules.Events.Endpoints +{ + public static class PutEventTicketType + { + public sealed class Handler : IRequestHandler + { + private readonly IEventManager _EventManager; + + public Handler(IEventManager eventManager) + { + _EventManager = eventManager; + } + + public async Task Handle(Request request, CancellationToken cancellationToken) + { + var newEventTicketType = request.EventTicketType.ToEventTicketType(); + var result = await _EventManager.UpdateTicketAsync(newEventTicketType).ConfigureAwait(false); + if (!result.Succeeded) + { + return new Response(ReturnType.Error, string.Join(Environment.NewLine, result.Errors)); + } + + return new Response(newEventTicketType.ToEventTicketTypeDto()); + } + } + + public sealed class Request : IRequest + { + public Request(long id, EventTicketTypeDto eventTicketTypeDto) + { + Guard.IsNotNull(eventTicketTypeDto, nameof(eventTicketTypeDto)); + + Id = id; + EventTicketType = eventTicketTypeDto; + } + + public long Id { get; } + + public EventTicketTypeDto EventTicketType { get; } + } + + public sealed class Response : ResponseBase + { + public Response(EventTicketTypeDto createdEventTicketType) : base(createdEventTicketType) + { + } + + public Response(ReturnType returnType, string error) : base(returnType, error) + { + } + } + } +} diff --git a/NetEvent/Server/Modules/Events/EventsModule.cs b/NetEvent/Server/Modules/Events/EventsModule.cs index 116a9d2c..755ddf17 100644 --- a/NetEvent/Server/Modules/Events/EventsModule.cs +++ b/NetEvent/Server/Modules/Events/EventsModule.cs @@ -24,10 +24,16 @@ public override IEndpointRouteBuilder MapModuleEndpoints(IEndpointRouteBuilder e public override IEndpointRouteBuilder MapModuleWriteAuthEndpoints(IEndpointRouteBuilder endpoints) { + // BaseRoute: /api/events endpoints.MapPost("/", async ([FromBody] EventDto eventDto, [FromServices] IMediator m) => ToApiResult(await m.Send(new PostEvent.Request(eventDto)))); endpoints.MapPut("/{eventId}", async ([FromRoute] long eventId, [FromBody] EventDto eventDto, [FromServices] IMediator m) => ToApiResult(await m.Send(new PutEvent.Request(eventId, eventDto)))); endpoints.MapDelete("/{eventId}", async ([FromRoute] long eventId, [FromServices] IMediator m) => ToApiResult(await m.Send(new DeleteEvent.Request(eventId)))); + var ticketTypeEndPoints = endpoints.MapGroup("/tickettype"); + ticketTypeEndPoints.MapPost("/{eventId}", async ([FromRoute] long eventId, [FromBody] EventTicketTypeDto eventTicketTypeDto, [FromServices] IMediator m) => ToApiResult(await m.Send(new PostEventTicketType.Request(eventId, eventTicketTypeDto)))); + ticketTypeEndPoints.MapPut("/{eventTicketTypeId}", async ([FromRoute] long eventTicketTypeId, [FromBody] EventTicketTypeDto eventTicketTypeDto, [FromServices] IMediator m) => ToApiResult(await m.Send(new PutEventTicketType.Request(eventTicketTypeId, eventTicketTypeDto)))); + ticketTypeEndPoints.MapDelete("/{eventTicketTypeId}", async ([FromRoute] long eventTicketTypeId, [FromServices] IMediator m) => ToApiResult(await m.Send(new DeleteEventTicketType.Request(eventTicketTypeId)))); + return base.MapModuleWriteAuthEndpoints(endpoints); } @@ -37,6 +43,11 @@ public override void OnModelCreating(ModelBuilder builder) { entity.ToTable(name: "Events"); }); + + builder.Entity(entity => + { + entity.ToTable(name: "EventTicketTypes"); + }); } } } diff --git a/NetEvent/Shared/Dto/Event/CurrencyDto.cs b/NetEvent/Shared/Dto/Event/CurrencyDto.cs new file mode 100644 index 00000000..c86b7736 --- /dev/null +++ b/NetEvent/Shared/Dto/Event/CurrencyDto.cs @@ -0,0 +1,7 @@ +namespace NetEvent.Shared.Dto.Event +{ + public enum CurrencyDto + { + Euro, + } +} diff --git a/NetEvent/Shared/Dto/Event/EventDto.cs b/NetEvent/Shared/Dto/Event/EventDto.cs index 19aa703b..d7d71c05 100644 --- a/NetEvent/Shared/Dto/Event/EventDto.cs +++ b/NetEvent/Shared/Dto/Event/EventDto.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; namespace NetEvent.Shared.Dto.Event { @@ -25,5 +27,7 @@ public class EventDto public string? Description { get; set; } public EventFormatDto EventFormat { get; set; } + + public ICollection TicketTypes { get; set; } = new Collection(); } } diff --git a/NetEvent/Shared/Dto/Event/EventTicketTypeDto.cs b/NetEvent/Shared/Dto/Event/EventTicketTypeDto.cs new file mode 100644 index 00000000..efe4df9a --- /dev/null +++ b/NetEvent/Shared/Dto/Event/EventTicketTypeDto.cs @@ -0,0 +1,26 @@ +using System; + +namespace NetEvent.Shared.Dto.Event +{ + + public class EventTicketTypeDto + { + public long? Id { get; set; } + + public string? Name { get; set; } + + public string? Slug { get; set; } + + public int Price { get; set; } + + public CurrencyDto Currency { get; set; } + + public long AvailableTickets { get; set; } + + public DateTime SellStartDate { get; set; } + + public DateTime SellEndDate { get; set; } + + public bool IsGiftable { get; set; } + } +} diff --git a/NetEvent/TestHelper/Fakers.cs b/NetEvent/TestHelper/Fakers.cs index 4e1dca5f..63de1f57 100644 --- a/NetEvent/TestHelper/Fakers.cs +++ b/NetEvent/TestHelper/Fakers.cs @@ -53,6 +53,20 @@ public static class Fakers .RuleFor(e => e.Venue, (f, e) => venues.ElementAtOrDefault(Random.Shared.Next(venues.Count() - 1))) .RuleFor(e => e.VenueId, (f, e) => e.Venue?.Id ?? 0); + public static Faker EventTicketTypeFaker(IEnumerable events) => new Faker() + .RuleFor(v => v.Id, (f, v) => f.IndexFaker) + .RuleFor(e => e.Name, (f, e) => f.Name.FirstName()) + .RuleFor(e => e.Slug, (f, e) => new SlugHelper().GenerateSlug(e.Name)) + .RuleFor(e => e.Price, (f, e) => f.Random.Int(0)) + .RuleFor(e => e.Currency, (f, e) => Currency.Euro) + .RuleFor(e => e.AvailableTickets, (f, e) => f.Random.Int(1)) + .RuleFor(e => e.SellStartDate, (f, e) => DateTime.UtcNow.AddDays(Random.Shared.Next(1, 30))) + .RuleFor(e => e.SellEndDate, (f, e) => e.SellStartDate.AddDays(Random.Shared.Next(1, 30))) + .RuleFor(e => e.IsGiftable, (f, e) => f.Random.Bool()) + .RuleFor(e => e.Event, (f, e) => events.ElementAtOrDefault(Random.Shared.Next(events.Count() - 1))) + .RuleFor(e => e.EventId, (f, e) => e.Event?.Id); + + public static Faker VenueFaker() => new Faker() .RuleFor(v => v.Id, (f, v) => f.IndexFaker) .RuleFor(v => v.Name, (f, v) => f.Name.FirstName()) From ff15ec56365e6038a24a1a9ad864c2f48496c3bc Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Thu, 12 Jan 2023 21:40:55 +0100 Subject: [PATCH 02/39] Tickets --- .editorconfig | 7 +- .../Pages/Administration/Events/Event.razor | 133 +----------------- .../Administration/Events/Event.razor.cs | 44 ------ .../Administration/Events/EventSettings.razor | 131 +++++++++++++++++ .../Events/EventSettings.razor.cs | 76 ++++++++++ .../Administration/Events/TicketTypes.razor | 13 ++ .../Events/TicketTypes.razor.cs | 19 +++ .../Client/Pages/Administration/Users.razor | 62 ++++---- .../Pages/Administration/Users.razor.cs | 34 ++--- NetEvent/Client/Resources/App.resx | 27 +++- NetEvent/Client/Services/EventService.cs | 72 +++++++++- .../Shared.Tests/NetEvent.Shared.Tests.csproj | 4 +- 12 files changed, 384 insertions(+), 238 deletions(-) create mode 100644 NetEvent/Client/Pages/Administration/Events/EventSettings.razor create mode 100644 NetEvent/Client/Pages/Administration/Events/EventSettings.razor.cs create mode 100644 NetEvent/Client/Pages/Administration/Events/TicketTypes.razor create mode 100644 NetEvent/Client/Pages/Administration/Events/TicketTypes.razor.cs diff --git a/.editorconfig b/.editorconfig index 72f96419..fbc1ec78 100644 --- a/.editorconfig +++ b/.editorconfig @@ -177,6 +177,11 @@ csharp_style_prefer_switch_expression = true:suggestion csharp_style_prefer_pattern_matching = true:silent csharp_style_prefer_not_pattern = true:suggestion csharp_style_prefer_extended_property_pattern = true:suggestion +csharp_style_prefer_top_level_statements = true:silent [**/Migrations/**/*.cs] -dotnet_analyzer_diagnostic.severity = none \ No newline at end of file +dotnet_analyzer_diagnostic.severity = none + +[*.razor] +dotnet_diagnostic.S927.severity = none +dotnet_diagnostic.S2696.severity = none \ No newline at end of file diff --git a/NetEvent/Client/Pages/Administration/Events/Event.razor b/NetEvent/Client/Pages/Administration/Events/Event.razor index 901a56f8..35b2c6b5 100644 --- a/NetEvent/Client/Pages/Administration/Events/Event.razor +++ b/NetEvent/Client/Pages/Administration/Events/Event.razor @@ -1,6 +1,5 @@ @page "/administration/event/{id}" @attribute [Authorize(Policy = "Admin.Events.*")] -@inject Microsoft.Extensions.Localization.IStringLocalizer Localize @using Microsoft.AspNetCore.Authorization @using NetEvent.Client.Components @@ -9,7 +8,6 @@ @using NetEvent.Shared.Config @using NetEvent.Shared.Dto @using NetEvent.Shared.Dto.Event -@using TinyMCE.Blazor @if (_Loading) { @@ -23,137 +21,12 @@ @if (_Event.Id > 0) { - + } - - - - - @Localize["Administration.Events.Event.Settings"] - - - - - @if (_Event.Id > 0) - { - - - - } - - - - - - - - @foreach (var eventFormat in Enum.GetValues()) - { - @Localize["Administration.Events.Event.EventFormat." + @eventFormat.ToString()] - } - - - - - @foreach (var publishState in Enum.GetValues()) - { - @Localize["Administration.Events.Event.PublishState." + @publishState.ToString()] - } - - - - - @foreach (var visibilityState in Enum.GetValues()) - { - @Localize["Administration.Events.Event.VisibilityState." + @visibilityState.ToString()] - } - - - - - - @foreach (var venue in _Venues) - { - @venue.Name - } - - - - - - - - - - - - - - - - - - - - - - - - @(_Event.Id >= 0 ? Localize["Administration.Events.Event.Save"] : Localize["Administration.Events.Event.Create"]) - - - + + } \ No newline at end of file diff --git a/NetEvent/Client/Pages/Administration/Events/Event.razor.cs b/NetEvent/Client/Pages/Administration/Events/Event.razor.cs index 8bb5dc2f..f07e6c73 100644 --- a/NetEvent/Client/Pages/Administration/Events/Event.razor.cs +++ b/NetEvent/Client/Pages/Administration/Events/Event.razor.cs @@ -6,10 +6,8 @@ using Microsoft.AspNetCore.Components; using Microsoft.Extensions.Localization; using MudBlazor; -using NetEvent.Client.Extensions; using NetEvent.Client.Services; using NetEvent.Shared.Dto.Event; -using NetEvent.Shared.Validators; namespace NetEvent.Client.Pages.Administration.Events { @@ -23,15 +21,9 @@ public partial class Event [Inject] private IVenueService VenueService { get; set; } = default!; - [Inject] - private ISnackbar Snackbar { get; set; } = default!; - [Inject] private IStringLocalizer Localizer { get; set; } = default!; - [Inject] - private NavigationManager NavigationManager { get; set; } = default!; - #endregion [Parameter] @@ -40,9 +32,7 @@ public partial class Event private const int _HourOffset = 12; private const int _DayOffset = 2; - private readonly EventModelFluentValidator _EventValidator = new(); private bool _Loading = true; - private MudForm? _Form = default!; private EventDto _Event = default!; private List _Venues = new(); @@ -66,39 +56,5 @@ protected override async Task OnInitializedAsync() _Loading = false; } - - private async Task SaveEvent() - { - if (_Form == null) - { - return; - } - - await _Form.Validate(); - - if (_Form.IsValid) - { - var cts = new CancellationTokenSource(); - ServiceResult result; - if (_Event.Id >= 0) - { - result = await EventService.UpdateEventAsync(_Event, cts.Token); - } - else - { - result = await EventService.CreateEventAsync(_Event, cts.Token); - - if (result.Successful && _Event?.Id != null) - { - NavigationManager.NavigateTo(UrlHelper.GetEventLink(_Event.Id, true)); - } - } - - if (!string.IsNullOrEmpty(result.MessageKey)) - { - Snackbar.Add(Localizer.GetString(result.MessageKey), result.Successful ? Severity.Success : Severity.Error); - } - } - } } } diff --git a/NetEvent/Client/Pages/Administration/Events/EventSettings.razor b/NetEvent/Client/Pages/Administration/Events/EventSettings.razor new file mode 100644 index 00000000..b11f56b0 --- /dev/null +++ b/NetEvent/Client/Pages/Administration/Events/EventSettings.razor @@ -0,0 +1,131 @@ +@using NetEvent.Shared.Dto.Event; +@using NetEvent.Shared.Dto; +@using TinyMCE.Blazor; + + + + + + @Localizer["Administration.Events.Event.Settings"] + + + + + @if (Event.Id > 0) + { + + + + } + + + + + + + + @foreach (var eventFormat in Enum.GetValues()) + { + @Localizer["Administration.Events.Event.EventFormat." + @eventFormat.ToString()] + } + + + + + @foreach (var publishState in Enum.GetValues()) + { + @Localizer["Administration.Events.Event.PublishState." + @publishState.ToString()] + } + + + + + @foreach (var visibilityState in Enum.GetValues()) + { + @Localizer["Administration.Events.Event.VisibilityState." + @visibilityState.ToString()] + } + + + + + + @foreach (var venue in Venues) + { + @venue.Name + } + + + + + + + + + + + + + + + + + + + + + + + + @(Event.Id >= 0 ? Localizer["Administration.Events.Event.Save"] : Localizer["Administration.Events.Event.Create"]) + + + diff --git a/NetEvent/Client/Pages/Administration/Events/EventSettings.razor.cs b/NetEvent/Client/Pages/Administration/Events/EventSettings.razor.cs new file mode 100644 index 00000000..da35b0d8 --- /dev/null +++ b/NetEvent/Client/Pages/Administration/Events/EventSettings.razor.cs @@ -0,0 +1,76 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.Localization; +using MudBlazor; +using NetEvent.Client.Extensions; +using NetEvent.Client.Services; +using NetEvent.Shared.Dto.Event; +using NetEvent.Shared.Validators; + +namespace NetEvent.Client.Pages.Administration.Events +{ + public partial class EventSettings + { + #region Injects + + [Inject] + private IEventService EventService { get; set; } = default!; + + [Inject] + private ISnackbar Snackbar { get; set; } = default!; + + [Inject] + private IStringLocalizer Localizer { get; set; } = default!; + + [Inject] + private NavigationManager NavigationManager { get; set; } = default!; + + #endregion + + [Parameter] + public EventDto Event { get; set; } = default!; + + [Parameter] + public List Venues { get; set; } = default!; + + private readonly EventModelFluentValidator _EventValidator = new(); + + private MudForm? _Form = default!; + + private async Task SaveEvent() + { + if (_Form == null) + { + return; + } + + await _Form.Validate(); + + if (_Form.IsValid) + { + var cts = new CancellationTokenSource(); + ServiceResult result; + if (Event.Id >= 0) + { + result = await EventService.UpdateEventAsync(Event, cts.Token); + } + else + { + result = await EventService.CreateEventAsync(Event, cts.Token); + + if (result.Successful && Event?.Id != null) + { + NavigationManager.NavigateTo(UrlHelper.GetEventLink(Event.Id, true)); + } + } + + if (!string.IsNullOrEmpty(result.MessageKey)) + { + Snackbar.Add(Localizer.GetString(result.MessageKey), result.Successful ? Severity.Success : Severity.Error); + } + } + } + } +} diff --git a/NetEvent/Client/Pages/Administration/Events/TicketTypes.razor b/NetEvent/Client/Pages/Administration/Events/TicketTypes.razor new file mode 100644 index 00000000..ad2fb25e --- /dev/null +++ b/NetEvent/Client/Pages/Administration/Events/TicketTypes.razor @@ -0,0 +1,13 @@ + + + + @Localizer["Administration.Events.Event.Tickets"] + + + + @foreach (var ticketType in Event.TicketTypes) + { + + } + + \ No newline at end of file diff --git a/NetEvent/Client/Pages/Administration/Events/TicketTypes.razor.cs b/NetEvent/Client/Pages/Administration/Events/TicketTypes.razor.cs new file mode 100644 index 00000000..6b28b2ef --- /dev/null +++ b/NetEvent/Client/Pages/Administration/Events/TicketTypes.razor.cs @@ -0,0 +1,19 @@ +using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.Localization; +using NetEvent.Shared.Dto.Event; + +namespace NetEvent.Client.Pages.Administration.Events +{ + public partial class TicketTypes + { + #region Injects + + [Inject] + private IStringLocalizer Localizer { get; set; } = default!; + + #endregion + + [Parameter] + public EventDto Event { get; set; } = default!; + } +} diff --git a/NetEvent/Client/Pages/Administration/Users.razor b/NetEvent/Client/Pages/Administration/Users.razor index 2aa0b80b..92d8bba7 100644 --- a/NetEvent/Client/Pages/Administration/Users.razor +++ b/NetEvent/Client/Pages/Administration/Users.razor @@ -1,17 +1,15 @@ @page "/administration/users" @attribute [Authorize(Policy = "Admin.Users.*")] -@using Microsoft.AspNetCore.Authorization -@using Microsoft.AspNetCore.Identity -@using NetEvent.Client.Components -@using NetEvent.Shared.Dto -@using NetEvent.Shared.Dto.Administration -@using NetEvent.Shared.Policy - -@inject Microsoft.Extensions.Localization.IStringLocalizer Localize +@using Microsoft.AspNetCore.Authorization; +@using Microsoft.AspNetCore.Identity; +@using NetEvent.Client.Components; +@using NetEvent.Shared.Dto; +@using NetEvent.Shared.Dto.Administration; +@using NetEvent.Shared.Policy; - + - @Localize["Administration.Users.Title"] + @Localizer["Administration.Users.Title"] - - - - - - + + + + + - + - + @context.Item.Role?.Name @@ -52,7 +50,7 @@ - + @foreach (var role in AllRoles) { @role.Name @@ -66,15 +64,15 @@ - + - @Localize["Administration.Users.Roles.Title"] + @Localizer["Administration.Users.Roles.Title"] - - - - + + + - + - + @if (@context.Item.Claims != null) { @@ -113,10 +111,10 @@ @foreach (var policy in Policies.AvailablePolicies) diff --git a/NetEvent/Client/Pages/Administration/Users.razor.cs b/NetEvent/Client/Pages/Administration/Users.razor.cs index 0b2c5388..00aeb283 100644 --- a/NetEvent/Client/Pages/Administration/Users.razor.cs +++ b/NetEvent/Client/Pages/Administration/Users.razor.cs @@ -15,16 +15,16 @@ namespace NetEvent.Client.Pages.Administration public partial class Users { [Inject] - private IUserService _UserService { get; set; } = default!; + private IUserService UserService { get; set; } = default!; [Inject] - private IRoleService _RoleService { get; set; } = default!; + private IRoleService RoleService { get; set; } = default!; [Inject] - private ISnackbar _Snackbar { get; set; } = default!; + private ISnackbar Snackbar { get; set; } = default!; [Inject] - private IStringLocalizer _Localizer { get; set; } = default!; + private IStringLocalizer Localizer { get; set; } = default!; private NetEventDataGrid? RolesDataGrid; @@ -32,13 +32,13 @@ protected override async Task OnInitializedAsync() { using var cancellationTokenSource = new CancellationTokenSource(); - AllUsers = await _UserService.GetUsersAsync(cancellationTokenSource.Token); + AllUsers = await UserService.GetUsersAsync(cancellationTokenSource.Token); await LoadRoles(cancellationTokenSource.Token); } private async Task LoadRoles(CancellationToken cancellationToken) { - AllRoles = await _RoleService.GetRolesAsync(cancellationToken); + AllRoles = await RoleService.GetRolesAsync(cancellationToken); } #region Users @@ -82,16 +82,16 @@ private async Task CommittedUserChangesAsync(AdminUserDto updatedUser) { using var cancellationTokenSource = new CancellationTokenSource(); - var result = await _UserService.UpdateUserAsync(updatedUser, cancellationTokenSource.Token).ConfigureAwait(false); + var result = await UserService.UpdateUserAsync(updatedUser, cancellationTokenSource.Token).ConfigureAwait(false); if (result.Successful) { - result = await _UserService.UpdateUserRoleAsync(updatedUser.Id, updatedUser.Role.Id, cancellationTokenSource.Token).ConfigureAwait(false); + result = await UserService.UpdateUserRoleAsync(updatedUser.Id, updatedUser.Role.Id, cancellationTokenSource.Token).ConfigureAwait(false); } if (!string.IsNullOrEmpty(result.MessageKey) && !string.IsNullOrEmpty(updatedUser.Email)) { - _Snackbar.Add(_Localizer.GetString(result.MessageKey, updatedUser.Email), result.Successful ? Severity.Success : Severity.Error); + Snackbar.Add(Localizer.GetString(result.MessageKey, updatedUser.Email), result.Successful ? Severity.Success : Severity.Error); } } #endregion @@ -129,16 +129,16 @@ private async Task CommittedRoleChangesAsync(RoleDto updatedRole) ServiceResult result; if (string.IsNullOrEmpty(updatedRole.Id)) { - result = await _RoleService.AddRoleAsync(updatedRole, cancellationTokenSource.Token).ConfigureAwait(false); + result = await RoleService.AddRoleAsync(updatedRole, cancellationTokenSource.Token).ConfigureAwait(false); } else { - result = await _RoleService.UpdateRoleAsync(updatedRole, cancellationTokenSource.Token).ConfigureAwait(false); + result = await RoleService.UpdateRoleAsync(updatedRole, cancellationTokenSource.Token).ConfigureAwait(false); } if (!string.IsNullOrEmpty(result.MessageKey)) { - _Snackbar.Add(_Localizer.GetString(result.MessageKey, updatedRole.Name), result.Successful ? Severity.Success : Severity.Error); + Snackbar.Add(Localizer.GetString(result.MessageKey, updatedRole.Name), result.Successful ? Severity.Success : Severity.Error); } await LoadRoles(cancellationTokenSource.Token); @@ -147,11 +147,11 @@ private async Task CommittedRoleChangesAsync(RoleDto updatedRole) private async Task DeletedItemChanges(EventCallbackArgs deletedRoleArgs) { using var cancellationTokenSource = new CancellationTokenSource(); - var result = await _RoleService.DeleteRoleAsync(deletedRoleArgs.Value, cancellationTokenSource.Token).ConfigureAwait(false); + var result = await RoleService.DeleteRoleAsync(deletedRoleArgs.Value, cancellationTokenSource.Token).ConfigureAwait(false); if (!string.IsNullOrEmpty(result.MessageKey)) { - _Snackbar.Add(_Localizer.GetString(result.MessageKey, deletedRoleArgs.Value.Name), result.Successful ? Severity.Success : Severity.Error); + Snackbar.Add(Localizer.GetString(result.MessageKey, deletedRoleArgs.Value.Name), result.Successful ? Severity.Success : Severity.Error); } if (!result.Successful) @@ -164,9 +164,9 @@ private string CreateSelectionLabel(List selectedValues) { return selectedValues.Count switch { - int n when n == 1 => $"{selectedValues.Count} {_Localizer["Administration.Users.Roles.SelectPermissionSingular"]}", - int n when n > 1 => $"{selectedValues.Count} {_Localizer["Administration.Users.Roles.SelectPermissionPlural"]}", - _ => (string)_Localizer["Administration.Users.Roles.NothingSelected"], + int n when n == 1 => $"{selectedValues.Count} {Localizer["Administration.Users.Roles.SelectPermissionSingular"]}", + int n when n > 1 => $"{selectedValues.Count} {Localizer["Administration.Users.Roles.SelectPermissionPlural"]}", + _ => (string)Localizer["Administration.Users.Roles.NothingSelected"], }; } #endregion diff --git a/NetEvent/Client/Resources/App.resx b/NetEvent/Client/Resources/App.resx index f56c55f8..9615bc0c 100644 --- a/NetEvent/Client/Resources/App.resx +++ b/NetEvent/Client/Resources/App.resx @@ -471,12 +471,6 @@ Start date - - Error deleting event - - - Event deleted successfully - Edit @@ -675,4 +669,25 @@ Hide name of organization in navbar + + Error creating + + + Created successfully + + + Error deleting + + + Deleted successfully + + + Error updating + + + Updated successfully + + + Tickets + \ No newline at end of file diff --git a/NetEvent/Client/Services/EventService.cs b/NetEvent/Client/Services/EventService.cs index 0a630fe4..9a25ae97 100644 --- a/NetEvent/Client/Services/EventService.cs +++ b/NetEvent/Client/Services/EventService.cs @@ -35,14 +35,14 @@ public async Task CreateEventAsync(EventDto eventDto, Cancellatio eventDto.Id = long.Parse(await response.Content.ReadAsStringAsync(cancellationToken), CultureInfo.InvariantCulture); - return ServiceResult.Success("EventService.AddEventAsync.Success"); + return ServiceResult.Success("EventService.AddAsync.Success"); } catch (Exception ex) { _Logger.LogError(ex, "Unable to create event in backend."); } - return ServiceResult.Error("EventService.AddEventAsync.Error"); + return ServiceResult.Error("EventService.AddAsync.Error"); } public async Task GetEventAsync(string slug, CancellationToken cancellationToken) @@ -128,14 +128,14 @@ public async Task UpdateEventAsync(EventDto eventDto, Cancellatio response.EnsureSuccessStatusCode(); - return ServiceResult.Success("EventService.UpdateEventAsync.Success"); + return ServiceResult.Success("EventService.UpdateAsync.Success"); } catch (Exception ex) { _Logger.LogError(ex, "Unable to update event in backend."); } - return ServiceResult.Error("EventService.UpdateEventAsync.Error"); + return ServiceResult.Error("EventService.UpdateAsync.Error"); } public async Task DeleteEventAsync(long id, CancellationToken cancellationToken) @@ -148,14 +148,74 @@ public async Task DeleteEventAsync(long id, CancellationToken can response.EnsureSuccessStatusCode(); - return ServiceResult.Success("EventService.DeleteEventAsync.Success"); + return ServiceResult.Success("EventService.DeleteAsync.Success"); } catch (Exception ex) { _Logger.LogError(ex, "Unable to delete event in backend."); } - return ServiceResult.Error("EventService.DeleteEventAsync.Error"); + return ServiceResult.Error("EventService.DeleteAsync.Error"); } + + public async Task CreateEventTicketTypeAsync(long eventId, EventTicketTypeDto eventTicketTypeDto, CancellationToken cancellationToken) + { + try + { + var client = _HttpClientFactory.CreateClient(Constants.BackendApiHttpClientName); + + var response = await client.PostAsJsonAsync($"api/events/tickettype/{eventId}", eventTicketTypeDto, cancellationToken); + response.EnsureSuccessStatusCode(); + + eventTicketTypeDto.Id = long.Parse(await response.Content.ReadAsStringAsync(cancellationToken), CultureInfo.InvariantCulture); + + return ServiceResult.Success("EventService.AddAsync.Success"); + } + catch (Exception ex) + { + _Logger.LogError(ex, "Unable to create eventTicketType in backend."); + } + + return ServiceResult.Error("EventService.AddAsync.Error"); + } + + public async Task UpdateEventTicketTypeAsync(EventTicketTypeDto eventTicketTypeDto, CancellationToken cancellationToken) + { + try + { + var client = _HttpClientFactory.CreateClient(Constants.BackendApiHttpClientName); + + var response = await client.PutAsJsonAsync($"api/events/tickettype/{eventTicketTypeDto.Id}", eventTicketTypeDto, cancellationToken); + response.EnsureSuccessStatusCode(); + + return ServiceResult.Success("EventService.UpdateAsync.Success"); + } + catch (Exception ex) + { + _Logger.LogError(ex, "Unable to update eventTicketType in backend."); + } + + return ServiceResult.Error("EventService.UpdateAsync.Error"); + } + + public async Task DeleteEventTicketTypeAsync(long id, CancellationToken cancellationToken) + { + try + { + var client = _HttpClientFactory.CreateClient(Constants.BackendApiHttpClientName); + + var response = await client.DeleteAsync($"api/events/tickettype/{id}", cancellationToken); + response.EnsureSuccessStatusCode(); + + return ServiceResult.Success("EventService.DeleteAsync.Success"); + } + catch (Exception ex) + { + _Logger.LogError(ex, "Unable to delete eventTicketType in backend."); + } + + return ServiceResult.Error("EventService.DeleteAsync.Error"); + } + } } diff --git a/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj b/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj index a4e68b0c..4b1a56e7 100644 --- a/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj +++ b/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj @@ -8,13 +8,13 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all From b5bbafa2abb0554e09a1b4b76968d547745063b1 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Thu, 12 Jan 2023 21:52:31 +0100 Subject: [PATCH 03/39] SQ Update --- .sonarlint/NetEvent.slconfig | 2 +- .sonarlint/lan2play_custom.ruleset | 5 +++++ .sonarlint/lan2play_netevent_js_settings.json | 6 +++--- .sonarlint/lan2play_netevent_ts_settings.json | 8 ++++---- .sonarlint/sonar.settings.json | 2 +- NetEvent/Client/Pages/Administration/Users.razor | 8 ++++---- NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj | 5 +++++ NetEvent/TestHelper/NetEvent.TestHelper.csproj | 5 +++++ 8 files changed, 28 insertions(+), 13 deletions(-) diff --git a/.sonarlint/NetEvent.slconfig b/.sonarlint/NetEvent.slconfig index b75b5218..ddd40732 100644 --- a/.sonarlint/NetEvent.slconfig +++ b/.sonarlint/NetEvent.slconfig @@ -9,7 +9,7 @@ "Profiles": { "CSharp": { "ProfileKey": "AYCLMpKIxLjXNqYUY9ar", - "ProfileTimestamp": "2022-12-21T10:43:07Z" + "ProfileTimestamp": "2023-01-12T20:47:45Z" }, "Js": { "ProfileKey": "AYBnUIIyux-I6QpYqqPJ", diff --git a/.sonarlint/lan2play_custom.ruleset b/.sonarlint/lan2play_custom.ruleset index 144994c3..eed4f3d8 100644 --- a/.sonarlint/lan2play_custom.ruleset +++ b/.sonarlint/lan2play_custom.ruleset @@ -45,4 +45,9 @@ + + + + + \ No newline at end of file diff --git a/.sonarlint/lan2play_netevent_js_settings.json b/.sonarlint/lan2play_netevent_js_settings.json index d554e442..bf00a390 100644 --- a/.sonarlint/lan2play_netevent_js_settings.json +++ b/.sonarlint/lan2play_netevent_js_settings.json @@ -968,6 +968,9 @@ "level": "On", "severity": "Major" }, + "javascript:S100": { + "level": "Off" + }, "javascript:S4787": { "level": "Off" }, @@ -1076,9 +1079,6 @@ "javascript:S138": { "level": "Off" }, - "javascript:S100": { - "level": "Off" - }, "javascript:S117": { "level": "Off" }, diff --git a/.sonarlint/lan2play_netevent_ts_settings.json b/.sonarlint/lan2play_netevent_ts_settings.json index 2e859ea0..3f927345 100644 --- a/.sonarlint/lan2play_netevent_ts_settings.json +++ b/.sonarlint/lan2play_netevent_ts_settings.json @@ -1,5 +1,9 @@ { "sonarlint.rules": { + "typescript:S6480": { + "level": "On", + "severity": "Major" + }, "typescript:S4123": { "level": "On", "severity": "Critical" @@ -286,10 +290,6 @@ "level": "On", "severity": "Major" }, - "typescript:S6480": { - "level": "On", - "severity": "Major" - }, "typescript:S6481": { "level": "On", "severity": "Major" diff --git a/.sonarlint/sonar.settings.json b/.sonarlint/sonar.settings.json index f71cb051..f2909265 100644 --- a/.sonarlint/sonar.settings.json +++ b/.sonarlint/sonar.settings.json @@ -1 +1 @@ -{"sonar.exclusions":["Server/Migrations/**/*"],"sonar.global.exclusions":["**/build-wrapper-dump.json"],"sonar.inclusions":[]} \ No newline at end of file +{"sonar.exclusions":["**/Migrations/**/*"],"sonar.global.exclusions":["**/build-wrapper-dump.json"],"sonar.inclusions":[]} \ No newline at end of file diff --git a/NetEvent/Client/Pages/Administration/Users.razor b/NetEvent/Client/Pages/Administration/Users.razor index 92d8bba7..dd4c1567 100644 --- a/NetEvent/Client/Pages/Administration/Users.razor +++ b/NetEvent/Client/Pages/Administration/Users.razor @@ -47,7 +47,7 @@ - + @@ -84,7 +84,7 @@ - + @@ -126,8 +126,8 @@ - - + + diff --git a/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj b/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj index 4b1a56e7..1ea16ae9 100644 --- a/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj +++ b/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj @@ -4,9 +4,14 @@ net7.0 enable + ..\..\.sonarlint\lan2play_custom.ruleset false + + + + diff --git a/NetEvent/TestHelper/NetEvent.TestHelper.csproj b/NetEvent/TestHelper/NetEvent.TestHelper.csproj index ea178346..a9c4912f 100644 --- a/NetEvent/TestHelper/NetEvent.TestHelper.csproj +++ b/NetEvent/TestHelper/NetEvent.TestHelper.csproj @@ -4,8 +4,13 @@ net7.0 enable enable + ..\..\.sonarlint\lan2play_custom.ruleset + + + + From f58e3446ddb428471c95c13243265825e229b0e2 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Fri, 20 Jan 2023 00:20:50 +0100 Subject: [PATCH 04/39] Start add Tickets View --- NetEvent/Client/Extensions/UrlHelper.cs | 5 + .../Pages/Administration/Events/Event.razor | 5 +- .../Administration/Events/TicketType.razor | 107 ++++++++++++++++ .../Administration/Events/TicketType.razor.cs | 120 ++++++++++++++++++ .../Administration/Events/TicketTypes.razor | 7 +- NetEvent/Client/Services/EventService.cs | 23 ++++ NetEvent/Client/Services/IEventService.cs | 3 + .../Events/Endpoints/GetEventTicketType.cs | 75 +++++++++++ .../Server/Modules/Events/EventsModule.cs | 1 + .../Shared/Dto/Event/EventTicketTypeDto.cs | 4 +- .../EventTicketTypeModelFluentValidator.cs | 42 ++++++ 11 files changed, 387 insertions(+), 5 deletions(-) create mode 100644 NetEvent/Client/Pages/Administration/Events/TicketType.razor create mode 100644 NetEvent/Client/Pages/Administration/Events/TicketType.razor.cs create mode 100644 NetEvent/Server/Modules/Events/Endpoints/GetEventTicketType.cs create mode 100644 NetEvent/Shared/Validators/EventTicketTypeModelFluentValidator.cs diff --git a/NetEvent/Client/Extensions/UrlHelper.cs b/NetEvent/Client/Extensions/UrlHelper.cs index db408a32..433f73fd 100644 --- a/NetEvent/Client/Extensions/UrlHelper.cs +++ b/NetEvent/Client/Extensions/UrlHelper.cs @@ -21,5 +21,10 @@ public static string GetVenueLink(object id, bool edit) return $"/venue/{id}"; } + + public static string GetTicketTypesLink(object eventId, object id) + { + return $"/administration/event/{eventId}/tickettype/{id}"; + } } } diff --git a/NetEvent/Client/Pages/Administration/Events/Event.razor b/NetEvent/Client/Pages/Administration/Events/Event.razor index 35b2c6b5..02000dbb 100644 --- a/NetEvent/Client/Pages/Administration/Events/Event.razor +++ b/NetEvent/Client/Pages/Administration/Events/Event.razor @@ -28,5 +28,8 @@ - + @if(_Event.Id > 0) + { + + } } \ No newline at end of file diff --git a/NetEvent/Client/Pages/Administration/Events/TicketType.razor b/NetEvent/Client/Pages/Administration/Events/TicketType.razor new file mode 100644 index 00000000..89847ae8 --- /dev/null +++ b/NetEvent/Client/Pages/Administration/Events/TicketType.razor @@ -0,0 +1,107 @@ +@page "/administration/event/{eventId}/tickettype/{ticketTypeId}" +@using NetEvent.Shared.Dto.Event; + +@if (_Loading) +{ + +} +else if (_EventTicketType != null) +{ + + + + @Localizer["Administration.Events.Event.Settings"] + + + + + @if (_EventTicketType.Id > 0) + { + + + + } + + + + + + + + + + + @foreach (var publishState in Enum.GetValues()) + { + @Localizer["Administration.Events.EventTicketType.CurrencyDto." + @publishState.ToString()] + } + + + + + + + + + + + + + + + + + + + + @(_EventTicketType.Id >= 0 ? Localizer["Administration.Events.EventTicketType.Save"] : Localizer["Administration.Events.EventTicketType.Create"]) + + +} + diff --git a/NetEvent/Client/Pages/Administration/Events/TicketType.razor.cs b/NetEvent/Client/Pages/Administration/Events/TicketType.razor.cs new file mode 100644 index 00000000..7276823e --- /dev/null +++ b/NetEvent/Client/Pages/Administration/Events/TicketType.razor.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; +using System.Net.Http; +using System.Net.Http.Json; +using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.AspNetCore.Components.Forms; +using Microsoft.AspNetCore.Components.Routing; +using Microsoft.AspNetCore.Components.Web; +using Microsoft.AspNetCore.Components.Web.Virtualization; +using Microsoft.AspNetCore.Components.WebAssembly.Http; +using Microsoft.JSInterop; +using MudBlazor; +using NetEvent.Client; +using NetEvent.Client.Shared; +using NetEvent.Client.Components; +using NetEvent.Shared.Dto.Event; +using NetEvent.Client.Services; +using System.Globalization; +using System.Threading; +using NetEvent.Shared.Validators; +using Microsoft.Extensions.Localization; +using NetEvent.Client.Extensions; + +namespace NetEvent.Client.Pages.Administration.Events +{ + public partial class TicketType + { + private const int _DayOffset = 2; + + #region Injects + + [Inject] + private IEventService EventService { get; set; } = default!; + + [Inject] + private IStringLocalizer Localizer { get; set; } = default!; + + [Inject] + private NavigationManager NavigationManager { get; set; } = default!; + + [Inject] + private ISnackbar Snackbar { get; set; } = default!; + + #endregion + + [Parameter] + public string? EventId { get; set; } + + [Parameter] + public string? TicketTypeId { get; set; } + + private readonly EventTicketTypeModelFluentValidator _EventTicketTypeValidator = new(); + private bool _Loading = true; + private EventTicketTypeDto _EventTicketType = default!; + private MudForm? _Form = default!; + private long _EventId; + + protected override async Task OnInitializedAsync() + { + var cts = new CancellationTokenSource(); + + if (!long.TryParse(EventId, CultureInfo.InvariantCulture, out _EventId)) + { + Snackbar.Add("No event defined!", Severity.Error); + } + + if (long.TryParse(TicketTypeId, CultureInfo.InvariantCulture, out var id)) + { + _EventTicketType = (await EventService.GetEventTicketTypeAsync(id, cts.Token).ConfigureAwait(false)) ?? new EventTicketTypeDto(); + } + else + { + _EventTicketType = new EventTicketTypeDto + { + SellStartDate = DateTime.Today.AddDays(_DayOffset - 1).AddHours(24 - DateTime.Today.Hour), + SellEndDate = DateTime.Today.AddDays(_DayOffset).AddHours(24 - DateTime.Today.Hour), + }; + } + + _Loading = false; + } + + private async Task SaveEventTicketType() + { + if (_Form == null) + { + return; + } + + await _Form.Validate(); + + if (_Form.IsValid) + { + var cts = new CancellationTokenSource(); + ServiceResult result; + if (_EventTicketType.Id >= 0) + { + result = await EventService.UpdateEventTicketTypeAsync(_EventTicketType, cts.Token); + } + else + { + result = await EventService.CreateEventTicketTypeAsync(_EventId, _EventTicketType, cts.Token); + + if (result.Successful && _EventTicketType?.Id != null) + { + NavigationManager.NavigateTo(UrlHelper.GetEventLink(_EventTicketType.Id, true)); + } + } + + if (!string.IsNullOrEmpty(result.MessageKey)) + { + Snackbar.Add(Localizer.GetString(result.MessageKey), result.Successful ? Severity.Success : Severity.Error); + } + } + } + } +} diff --git a/NetEvent/Client/Pages/Administration/Events/TicketTypes.razor b/NetEvent/Client/Pages/Administration/Events/TicketTypes.razor index ad2fb25e..39fd8517 100644 --- a/NetEvent/Client/Pages/Administration/Events/TicketTypes.razor +++ b/NetEvent/Client/Pages/Administration/Events/TicketTypes.razor @@ -1,13 +1,16 @@ - +@using NetEvent.Client.Extensions; + @Localizer["Administration.Events.Event.Tickets"] + + @Localizer["Administration.Events.EventTicketType.Create"] @foreach (var ticketType in Event.TicketTypes) { - +
@ticketType.Name
}
\ No newline at end of file diff --git a/NetEvent/Client/Services/EventService.cs b/NetEvent/Client/Services/EventService.cs index 9a25ae97..971ed0fa 100644 --- a/NetEvent/Client/Services/EventService.cs +++ b/NetEvent/Client/Services/EventService.cs @@ -217,5 +217,28 @@ public async Task DeleteEventTicketTypeAsync(long id, Cancellatio return ServiceResult.Error("EventService.DeleteAsync.Error"); } + public async Task GetEventTicketTypeAsync(long id, CancellationToken cancellationToken) + { + try + { + var client = _HttpClientFactory.CreateClient(Constants.BackendApiHttpClientName); + + var eventTicketTypeDto = await client.GetFromJsonAsync($"/api/events/tickettype/{id}", cancellationToken).ConfigureAwait(false); + + if (eventTicketTypeDto == null) + { + _Logger.LogError("Unable to get eventtickettype data from backend"); + return null; + } + + return eventTicketTypeDto; + } + catch (Exception ex) + { + _Logger.LogError(ex, "Unable to get eventtickettype data from backend"); + return null; + } + } + } } diff --git a/NetEvent/Client/Services/IEventService.cs b/NetEvent/Client/Services/IEventService.cs index 4e5ef235..f2c2c295 100644 --- a/NetEvent/Client/Services/IEventService.cs +++ b/NetEvent/Client/Services/IEventService.cs @@ -20,5 +20,8 @@ public interface IEventService Task UpdateEventAsync(EventDto eventDto, CancellationToken cancellationToken); Task CreateEventAsync(EventDto eventDto, CancellationToken cancellationToken); + Task GetEventTicketTypeAsync(long id, CancellationToken cancellationToken); + Task UpdateEventTicketTypeAsync(EventTicketTypeDto eventTicketTypeDto, CancellationToken cancellationToken); + Task CreateEventTicketTypeAsync(long eventId, EventTicketTypeDto eventTicketTypeDto, CancellationToken cancellationToken); } } diff --git a/NetEvent/Server/Modules/Events/Endpoints/GetEventTicketType.cs b/NetEvent/Server/Modules/Events/Endpoints/GetEventTicketType.cs new file mode 100644 index 00000000..e700f7c1 --- /dev/null +++ b/NetEvent/Server/Modules/Events/Endpoints/GetEventTicketType.cs @@ -0,0 +1,75 @@ +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Microsoft.EntityFrameworkCore; +using NetEvent.Server.Data; +using NetEvent.Shared; +using NetEvent.Shared.Dto.Event; + +namespace NetEvent.Server.Modules.Events.Endpoints +{ + public static class GetEventTicketType + { + public sealed class Handler : IRequestHandler + { + private readonly ApplicationDbContext _DbContext; + + public Handler(ApplicationDbContext dbContext) + { + _DbContext = dbContext; + } + + public async Task Handle(Request request, CancellationToken cancellationToken) + { + Models.EventTicketType? eventTicketTypeModel; + if (request.Slug != null) + { + eventTicketTypeModel = await _DbContext.Tickets.Where(e => e.Slug != null && e.Slug.Equals(request.Slug, StringComparison.OrdinalIgnoreCase)).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); + } + else + { + eventTicketTypeModel = await _DbContext.Tickets.Where(x => x.Id == request.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); + } + + if (eventTicketTypeModel == null) + { + return new Response(ReturnType.NotFound, "Event for Id not found!"); + } + + var convertedEventTicketType = eventTicketTypeModel.ToEventTicketTypeDto(); + + return new Response(convertedEventTicketType); + } + } + + public sealed class Request : IRequest + { + public Request(long id) + { + Id = id; + } + + public Request(string slug) + { + Slug = slug; + } + + public long Id { get; } + + public string? Slug { get; } + } + + public sealed class Response : ResponseBase + { + public Response(EventTicketTypeDto? value) : base(value) + { + } + + public Response(ReturnType returnType, string error) : base(returnType, error) + { + } + } + } +} diff --git a/NetEvent/Server/Modules/Events/EventsModule.cs b/NetEvent/Server/Modules/Events/EventsModule.cs index 755ddf17..2f627914 100644 --- a/NetEvent/Server/Modules/Events/EventsModule.cs +++ b/NetEvent/Server/Modules/Events/EventsModule.cs @@ -33,6 +33,7 @@ public override IEndpointRouteBuilder MapModuleWriteAuthEndpoints(IEndpointRoute ticketTypeEndPoints.MapPost("/{eventId}", async ([FromRoute] long eventId, [FromBody] EventTicketTypeDto eventTicketTypeDto, [FromServices] IMediator m) => ToApiResult(await m.Send(new PostEventTicketType.Request(eventId, eventTicketTypeDto)))); ticketTypeEndPoints.MapPut("/{eventTicketTypeId}", async ([FromRoute] long eventTicketTypeId, [FromBody] EventTicketTypeDto eventTicketTypeDto, [FromServices] IMediator m) => ToApiResult(await m.Send(new PutEventTicketType.Request(eventTicketTypeId, eventTicketTypeDto)))); ticketTypeEndPoints.MapDelete("/{eventTicketTypeId}", async ([FromRoute] long eventTicketTypeId, [FromServices] IMediator m) => ToApiResult(await m.Send(new DeleteEventTicketType.Request(eventTicketTypeId)))); + ticketTypeEndPoints.MapGet("/{eventTicketTypeId}", async ([FromRoute] long eventTicketTypeId, [FromServices] IMediator m) => ToApiResult(await m.Send(new GetEventTicketType.Request(eventTicketTypeId)))); return base.MapModuleWriteAuthEndpoints(endpoints); } diff --git a/NetEvent/Shared/Dto/Event/EventTicketTypeDto.cs b/NetEvent/Shared/Dto/Event/EventTicketTypeDto.cs index efe4df9a..9a0ca023 100644 --- a/NetEvent/Shared/Dto/Event/EventTicketTypeDto.cs +++ b/NetEvent/Shared/Dto/Event/EventTicketTypeDto.cs @@ -17,9 +17,9 @@ public class EventTicketTypeDto public long AvailableTickets { get; set; } - public DateTime SellStartDate { get; set; } + public DateTime? SellStartDate { get; set; } - public DateTime SellEndDate { get; set; } + public DateTime? SellEndDate { get; set; } public bool IsGiftable { get; set; } } diff --git a/NetEvent/Shared/Validators/EventTicketTypeModelFluentValidator.cs b/NetEvent/Shared/Validators/EventTicketTypeModelFluentValidator.cs new file mode 100644 index 00000000..75b98f2f --- /dev/null +++ b/NetEvent/Shared/Validators/EventTicketTypeModelFluentValidator.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using FluentValidation; +using NetEvent.Shared.Dto.Event; + +namespace NetEvent.Shared.Validators +{ + public class EventTicketTypeModelFluentValidator : AbstractValidator + { + public EventTicketTypeModelFluentValidator() + { + RuleFor(x => x.Name) + .NotEmpty() + .Length(1, 100); + + RuleFor(x => x.Price) + .GreaterThanOrEqualTo(0); + + RuleFor(x => x.AvailableTickets) + .GreaterThan(0); + + RuleFor(x => x.SellEndDate) + .GreaterThan(x => x.SellStartDate); + + RuleFor(x => x.SellStartDate) + .GreaterThan(DateTime.UtcNow); + } + + public Func>> ValidateValue => async (model, propertyName) => + { + var result = await ValidateAsync(ValidationContext.CreateWithOptions((EventTicketTypeDto)model, x => x.IncludeProperties(propertyName))); + if (result.IsValid) + { + return Array.Empty(); + } + + return result.Errors.Select(e => e.ErrorMessage); + }; + } +} From 1322c1a63120bdbad985ed6ee5760bb6e9cb19d0 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Fri, 20 Jan 2023 22:41:41 +0100 Subject: [PATCH 05/39] . --- .../Administration/Events/EventSettings.razor | 55 ++--- .../Administration/Events/TicketType.razor | 191 +++++++++--------- NetEvent/Client/Resources/App.resx | 27 +++ 3 files changed, 152 insertions(+), 121 deletions(-) diff --git a/NetEvent/Client/Pages/Administration/Events/EventSettings.razor b/NetEvent/Client/Pages/Administration/Events/EventSettings.razor index b11f56b0..9d258599 100644 --- a/NetEvent/Client/Pages/Administration/Events/EventSettings.razor +++ b/NetEvent/Client/Pages/Administration/Events/EventSettings.razor @@ -15,13 +15,13 @@ { + For="@(() => Event.Id)" + Margin="Margin.Dense" + ReadOnly="true" + Disabled="true" + Immediate="true" + Variant="Variant.Outlined" + Label="@Localizer["Administration.Events.Event.Id"]" /> } @@ -34,6 +34,26 @@ Variant="Variant.Outlined" Label="@Localizer["Administration.Events.Event.Name"]" /> + + + + + + @@ -86,26 +107,6 @@ } - - - - - - - - - @Localizer["Administration.Events.Event.Settings"] - - - - - @if (_EventTicketType.Id > 0) - { - - - - } + + + + + + @Localizer["Administration.Events.Event.Settings"] + + + + + @if (_EventTicketType.Id > 0) + { + + + + } - + - - - - - - - - @foreach (var publishState in Enum.GetValues()) - { - @Localizer["Administration.Events.EventTicketType.CurrencyDto." + @publishState.ToString()] - } - - - - - - - - - - - - - - - - - - - - @(_EventTicketType.Id >= 0 ? Localizer["Administration.Events.EventTicketType.Save"] : Localizer["Administration.Events.EventTicketType.Create"]) - - + + + + + + + + + + + @foreach (var publishState in Enum.GetValues()) + { + @Localizer["Administration.Events.EventTicketType.Currency." + @publishState.ToString()] + } + + + + + + + + + + + + + + + + + @(_EventTicketType.Id >= 0 ? Localizer["Administration.Events.EventTicketType.Save"] : Localizer["Administration.Events.EventTicketType.Create"]) + + +
} diff --git a/NetEvent/Client/Resources/App.resx b/NetEvent/Client/Resources/App.resx index 9615bc0c..c00db4db 100644 --- a/NetEvent/Client/Resources/App.resx +++ b/NetEvent/Client/Resources/App.resx @@ -690,4 +690,31 @@ Tickets + + Available Tickets + + + Create Ticket Type + + + Currency + + + Euro (€) + + + Is giftable + + + Name + + + Price + + + Sell End + + + Sell Start + \ No newline at end of file From a71a360db67358327097431447ba61acd0c2fbcc Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Fri, 20 Jan 2023 22:44:11 +0100 Subject: [PATCH 06/39] Nuget Updates --- NetEvent/Client/NetEvent.Client.csproj | 8 +++--- .../Server.Tests/NetEvent.Server.Tests.csproj | 4 +-- NetEvent/Server/NetEvent.Server.csproj | 26 +++++++++---------- NetEvent/Shared/NetEvent.Shared.csproj | 4 +-- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/NetEvent/Client/NetEvent.Client.csproj b/NetEvent/Client/NetEvent.Client.csproj index 5500df61..973679a2 100644 --- a/NetEvent/Client/NetEvent.Client.csproj +++ b/NetEvent/Client/NetEvent.Client.csproj @@ -29,13 +29,13 @@ - - - + + + - + diff --git a/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj b/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj index a9071efd..d3dd8750 100644 --- a/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj +++ b/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj @@ -15,8 +15,8 @@ - - + + diff --git a/NetEvent/Server/NetEvent.Server.csproj b/NetEvent/Server/NetEvent.Server.csproj index ae69a3f1..d1edecfb 100644 --- a/NetEvent/Server/NetEvent.Server.csproj +++ b/NetEvent/Server/NetEvent.Server.csproj @@ -21,30 +21,30 @@ - - - - - - - - + + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + diff --git a/NetEvent/Shared/NetEvent.Shared.csproj b/NetEvent/Shared/NetEvent.Shared.csproj index 5305d566..8abf59c0 100644 --- a/NetEvent/Shared/NetEvent.Shared.csproj +++ b/NetEvent/Shared/NetEvent.Shared.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive From 1bbb4bddfb71a0d1339f32a9e6c8f39fe052ddb3 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Tue, 24 Jan 2023 21:36:33 +0100 Subject: [PATCH 07/39] Add TicketType Table --- .../Administration/Events/TicketType.razor | 5 +- .../Administration/Events/TicketType.razor.cs | 4 +- .../Administration/Events/TicketTypes.razor | 30 +++++- NetEvent/Client/Program.cs | 2 + NetEvent/Client/Resources/App.resx | 33 +++++++ NetEvent/Client/Services/NavigationService.cs | 97 +++++++++++++++++++ .../Services/NavigationServiceExtension.cs | 21 ++++ .../Shared/Dto/Event/CurrencyExtension.cs | 16 +++ 8 files changed, 201 insertions(+), 7 deletions(-) create mode 100644 NetEvent/Client/Services/NavigationService.cs create mode 100644 NetEvent/Client/Services/NavigationServiceExtension.cs create mode 100644 NetEvent/Shared/Dto/Event/CurrencyExtension.cs diff --git a/NetEvent/Client/Pages/Administration/Events/TicketType.razor b/NetEvent/Client/Pages/Administration/Events/TicketType.razor index 5b66d8cb..62e3cd50 100644 --- a/NetEvent/Client/Pages/Administration/Events/TicketType.razor +++ b/NetEvent/Client/Pages/Administration/Events/TicketType.razor @@ -101,7 +101,10 @@ else if (_EventTicketType != null) - + + @Localizer["Administration.Events.EventTicketType.Cancel"] + + @(_EventTicketType.Id >= 0 ? Localizer["Administration.Events.EventTicketType.Save"] : Localizer["Administration.Events.EventTicketType.Create"]) diff --git a/NetEvent/Client/Pages/Administration/Events/TicketType.razor.cs b/NetEvent/Client/Pages/Administration/Events/TicketType.razor.cs index 7276823e..f6cc0dd3 100644 --- a/NetEvent/Client/Pages/Administration/Events/TicketType.razor.cs +++ b/NetEvent/Client/Pages/Administration/Events/TicketType.razor.cs @@ -39,7 +39,7 @@ public partial class TicketType private IStringLocalizer Localizer { get; set; } = default!; [Inject] - private NavigationManager NavigationManager { get; set; } = default!; + private NavigationService NavigationService { get; set; } = default!; [Inject] private ISnackbar Snackbar { get; set; } = default!; @@ -106,7 +106,7 @@ private async Task SaveEventTicketType() if (result.Successful && _EventTicketType?.Id != null) { - NavigationManager.NavigateTo(UrlHelper.GetEventLink(_EventTicketType.Id, true)); + NavigationService.NavigateTo(UrlHelper.GetEventLink(_EventTicketType.Id, true)); } } diff --git a/NetEvent/Client/Pages/Administration/Events/TicketTypes.razor b/NetEvent/Client/Pages/Administration/Events/TicketTypes.razor index 39fd8517..32993947 100644 --- a/NetEvent/Client/Pages/Administration/Events/TicketTypes.razor +++ b/NetEvent/Client/Pages/Administration/Events/TicketTypes.razor @@ -1,4 +1,6 @@ @using NetEvent.Client.Extensions; +@using NetEvent.Shared.Dto.Event; + @@ -8,9 +10,29 @@ @Localizer["Administration.Events.EventTicketType.Create"] - @foreach (var ticketType in Event.TicketTypes) - { -
@ticketType.Name
- } + + + + @Localizer["Administration.Events.Event.Tickets.Name"] + @Localizer["Administration.Events.Event.Tickets.SellStartDate"] + @Localizer["Administration.Events.Event.Tickets.SellEndDate"] + @Localizer["Administration.Events.Event.Tickets.AvailableTickets"] + @Localizer["Administration.Events.Event.Tickets.Price"] + @Localizer["Administration.Events.Event.Tickets.IsGiftable"] + + + + @context.Name + @context.SellStartDate + @context.SellEndDate + @context.AvailableTickets + @context.Price @context.Currency.ToSymbol() + @context.IsGiftable + + @Localizer["Administration.Events.EventTicketType.Edit"] + @*@Localizer["Administration.Events.EventTicketType.Create"]*@ + + +
\ No newline at end of file diff --git a/NetEvent/Client/Program.cs b/NetEvent/Client/Program.cs index d02e6986..dbc2b332 100644 --- a/NetEvent/Client/Program.cs +++ b/NetEvent/Client/Program.cs @@ -39,6 +39,7 @@ private static async Task Main(string[] args) builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddSingleton(); builder.Services.AddHttpClient(Constants.BackendApiHttpClientName) .ConfigureHttpClient(client => @@ -73,6 +74,7 @@ private static async Task Main(string[] args) var app = builder.Build(); await app.SetDefaultCultureAsync(); + await app.InitializeNavigationService(); await app.RunAsync(); } diff --git a/NetEvent/Client/Resources/App.resx b/NetEvent/Client/Resources/App.resx index c00db4db..c9c314e8 100644 --- a/NetEvent/Client/Resources/App.resx +++ b/NetEvent/Client/Resources/App.resx @@ -717,4 +717,37 @@ Sell Start + + Available Tickets + + + Is Giftable + + + Name + + + Price + + + Sell End + + + Sell Start + + + Sort by + + + Cancel + + + Edit + + + Id + + + Save + \ No newline at end of file diff --git a/NetEvent/Client/Services/NavigationService.cs b/NetEvent/Client/Services/NavigationService.cs new file mode 100644 index 00000000..a8e903f9 --- /dev/null +++ b/NetEvent/Client/Services/NavigationService.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Threading.Tasks; +using System.Threading; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Routing; +using Microsoft.AspNetCore.Components.WebAssembly.Hosting; +using Microsoft.Extensions.Logging; +using NetEvent.Shared.Config; +using Microsoft.Extensions.DependencyInjection; + +namespace NetEvent.Client.Services +{ + public class NavigationService : IDisposable + { + private const int MinHistorySize = 256; + private const int AdditionalHistorySize = 64; + + private readonly NavigationManager _NavigationManager; + private readonly List _History; + + public NavigationService(NavigationManager navigationManager) + { + _NavigationManager = navigationManager; + _History = new List(MinHistorySize + AdditionalHistorySize) + { + _NavigationManager.Uri + }; + _NavigationManager.LocationChanged += OnLocationChanged; + } + + /// + /// Navigates to the specified url. + /// + /// The destination url (relative or absolute). + public void NavigateTo(string url) + { + _NavigationManager.NavigateTo(url); + } + + /// + /// Returns true if it is possible to navigate to the previous url. + /// + public bool CanNavigateBack => _History.Count >= 2; + + /// + /// Navigates to the previous url if possible or does nothing if it is not. + /// + public void NavigateBack() + { + if (!CanNavigateBack) + { + return; + } + + var backPageUrl = _History[^2]; + _History.RemoveRange(_History.Count - 2, 2); + _NavigationManager.NavigateTo(backPageUrl); + } + + // .. All other navigation methods. + + private void OnLocationChanged(object sender, LocationChangedEventArgs e) + { + EnsureSize(); + _History.Add(e.Location); + } + + private void EnsureSize() + { + if (_History.Count < MinHistorySize + AdditionalHistorySize) + { + return; + } + + _History.RemoveRange(0, _History.Count - MinHistorySize); + } + + #region Implementation of Dispose + + private void Dispose(bool disposing) + { + if (disposing) + { + _NavigationManager.LocationChanged -= OnLocationChanged; + } + } + + public void Dispose() + { + Dispose(true); + } + + #endregion + } +} diff --git a/NetEvent/Client/Services/NavigationServiceExtension.cs b/NetEvent/Client/Services/NavigationServiceExtension.cs new file mode 100644 index 00000000..116c62a7 --- /dev/null +++ b/NetEvent/Client/Services/NavigationServiceExtension.cs @@ -0,0 +1,21 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components.WebAssembly.Hosting; +using Microsoft.Extensions.DependencyInjection; + +namespace NetEvent.Client.Services +{ + public static class NavigationServiceExtension + { + public static Task InitializeNavigationService(this WebAssemblyHost app) + { + var navigationService = app.Services.GetRequiredService(); + if (navigationService == null) + { + throw new NotSupportedException("Start without NavigationServce is not possible!"); + } + + return Task.CompletedTask; + } + } +} diff --git a/NetEvent/Shared/Dto/Event/CurrencyExtension.cs b/NetEvent/Shared/Dto/Event/CurrencyExtension.cs new file mode 100644 index 00000000..bab7703c --- /dev/null +++ b/NetEvent/Shared/Dto/Event/CurrencyExtension.cs @@ -0,0 +1,16 @@ +using System; + +namespace NetEvent.Shared.Dto.Event +{ + public static class CurrencyExtension + { + public static string ToSymbol(this CurrencyDto currency) + { + return currency switch + { + CurrencyDto.Euro => "€", + _ => throw new NotSupportedException($"The Currency {currency} is not implemented!"), + }; + } + } +} From 43721a4d8302850a8de454414849646b55a90b54 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Wed, 25 Jan 2023 23:35:36 +0100 Subject: [PATCH 08/39] Events --- NetEvent/Client/Pages/Events/Event.razor | 46 ++++++++++++++++++++++++ NetEvent/Client/Resources/App.resx | 12 +++++++ NetEvent/Server/NetEvent.Server.csproj | 2 +- 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/NetEvent/Client/Pages/Events/Event.razor b/NetEvent/Client/Pages/Events/Event.razor index 5f7adcb0..64db28c2 100644 --- a/NetEvent/Client/Pages/Events/Event.razor +++ b/NetEvent/Client/Pages/Events/Event.razor @@ -9,6 +9,7 @@ @using NetEvent.Shared.Config @using NetEvent.Shared.Dto @using System.Globalization +@using NetEvent.Shared.Dto.Event; @using TinyMCE.Blazor
@@ -51,6 +52,51 @@ } + @if (_Event.TicketTypes != null && _Event.TicketTypes.Any()) + { + @Localize["Administration.Events.Event.Tickets"] + +
+ + @foreach (var ticketType in _Event.TicketTypes.Where(t => t.SellEndDate < DateTime.Now)) + { + + + + @ticketType.Name + + + @ticketType.Price @ticketType.Currency.ToSymbol() + + + + + + + TODO remainingTickets / @ticketType.AvailableTickets @Localize["Administration.Events.Event.Tickets.Available"] + + + + @if (ticketType.SellStartDate >= DateTime.Now) + { + @Localize["Administration.Events.Event.Tickets.AvailableFrom", ticketType.SellStartDate] + } + else + { + @Localize["Administration.Events.Event.Tickets.AvailableUntil", ticketType.SellEndDate] + } + + + @Localize["Administration.Events.Event.Tickets.Buy"] + + + } + +
+ + + } + @if (_Event.Description != null) { @((MarkupString)_Event.Description) diff --git a/NetEvent/Client/Resources/App.resx b/NetEvent/Client/Resources/App.resx index c9c314e8..ee11d23e 100644 --- a/NetEvent/Client/Resources/App.resx +++ b/NetEvent/Client/Resources/App.resx @@ -750,4 +750,16 @@ Save + + available + + + Buy + + + Available from {0} + + + Available until {0} + \ No newline at end of file diff --git a/NetEvent/Server/NetEvent.Server.csproj b/NetEvent/Server/NetEvent.Server.csproj index d1edecfb..28bad44e 100644 --- a/NetEvent/Server/NetEvent.Server.csproj +++ b/NetEvent/Server/NetEvent.Server.csproj @@ -35,7 +35,7 @@ - + From bb203cdb112065b6042897867121868ca9acf705 Mon Sep 17 00:00:00 2001 From: Alexander Volz Date: Thu, 26 Jan 2023 22:49:50 +0100 Subject: [PATCH 09/39] add temporary build --- .github/workflows/test_and_build.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 3976b527..2562289e 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -4,6 +4,7 @@ on: branches: - main - develop + - 'feature/Andy_Tickets' tags: [ v**] paths: - '**' @@ -109,7 +110,7 @@ jobs: with: submodules: recursive - name: Set up QEMU - uses: docker/setup-qemu-action@v2.0.0 + uses: docker/setup-qemu-action@v2.1.0 - name: Pull Latest Linux Base Image run: docker pull lan2play/netevent - name: set Version @@ -119,12 +120,13 @@ jobs: if: ${{ !(startsWith(github.ref, 'refs/tags/v')) }} run: echo "NETEVENTNETVER=0.0.1" >> $GITHUB_ENV - name: Build Linux Image - uses: docker/build-push-action@v3.1.1 + uses: docker/build-push-action@v3.3.0 with: context: . file: ./Dockerfile tags: | lan2play/netevent:latest + lan2play/netevent:tickets build-args: | BUILDNODE=GitHub (Run Number: ${{ github.run_number }} Run ID: ${{ github.run_id }}) BUILDID=${{ github.run_id }} @@ -135,11 +137,14 @@ jobs: # - name: Test Linux Image # run: docker run --rm lan2play/netevent:latest /docker/test.sh - name: Login to DockerHub - if: ${{ (startsWith(github.ref, 'refs/tags/v')) }} - uses: docker/login-action@v2.0.0 + if: ${{ (startsWith(github.ref, 'refs/tags/v')) || ( github.event_name == 'push' && (github.ref_name == 'feature/Andy_Tickets' || github.base_ref == 'feature/Andy_Tickets') ) }} + uses: docker/login-action@v2.1.0 with: username: ${{ secrets.NETEVENT_DOCKERHUB_USERNAME }} password: ${{ secrets.NETEVENT_DOCKERHUB_TOKEN }} + - name: Push to Docker HUB Tickets + if: ${{ github.event_name == 'push' && (github.ref_name == 'feature/Andy_Tickets' || github.base_ref == 'feature/Andy_Tickets') }} + run: docker push lan2play/netevent:tickets - name: Push to Docker HUB if: ${{ (startsWith(github.ref, 'refs/tags/v')) }} run: docker push lan2play/netevent:latest From b3edd416601a9ffee6554c7b070406536d2224f0 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Thu, 26 Jan 2023 23:39:02 +0100 Subject: [PATCH 10/39] Start Add TicketPurchase --- NetEvent/Server/Data/ApplicationDbContext.cs | 4 + NetEvent/Server/Data/IPaymentManager.cs | 12 + NetEvent/Server/Data/PaymentManager.cs | 140 +++ NetEvent/Server/Helpers/DtoMapper.cs | 2 + .../20230126222513_AddTickets.Designer.cs | 834 ++++++++++++++++++ .../Psql/20230126222513_AddTickets.cs | 127 +++ .../PsqlApplicationDbContextModelSnapshot.cs | 102 ++- .../20230126222503_AddTickets.Designer.cs | 815 +++++++++++++++++ .../Sqlite/20230126222503_AddTickets.cs | 126 +++ ...SqliteApplicationDbContextModelSnapshot.cs | 98 +- NetEvent/Server/Models/Purchase.cs | 9 +- NetEvent/Server/Modules/ModuleExtensions.cs | 1 - .../Modules/Payment/Endpoints/DeleteVenue.cs | 53 ++ .../Modules/Payment/Endpoints/GetVenue.cs | 74 ++ .../Modules/Payment/Endpoints/GetVenues.cs | 47 + .../Modules/Payment/Endpoints/PostCart.cs | 63 ++ .../Modules/Payment/Endpoints/PutVenue.cs | 62 ++ .../Server/Modules/Payment/PaymentModule.cs | 43 + NetEvent/Server/NetEvent.Server.csproj | 1 + NetEvent/Server/Program.cs | 1 + NetEvent/Shared/Config/SystemSettingGroup.cs | 1 + NetEvent/Shared/Config/SystemSettings.cs | 17 +- NetEvent/Shared/Dto/CartDto.cs | 11 + NetEvent/Shared/Dto/CartEntryDto.cs | 13 + .../Shared/Dto/Event/CurrencyExtension.cs | 9 + NetEvent/Shared/Dto/Event/EventDto.cs | 2 +- 26 files changed, 2655 insertions(+), 12 deletions(-) create mode 100644 NetEvent/Server/Data/IPaymentManager.cs create mode 100644 NetEvent/Server/Data/PaymentManager.cs create mode 100644 NetEvent/Server/Migrations/Psql/20230126222513_AddTickets.Designer.cs create mode 100644 NetEvent/Server/Migrations/Psql/20230126222513_AddTickets.cs create mode 100644 NetEvent/Server/Migrations/Sqlite/20230126222503_AddTickets.Designer.cs create mode 100644 NetEvent/Server/Migrations/Sqlite/20230126222503_AddTickets.cs create mode 100644 NetEvent/Server/Modules/Payment/Endpoints/DeleteVenue.cs create mode 100644 NetEvent/Server/Modules/Payment/Endpoints/GetVenue.cs create mode 100644 NetEvent/Server/Modules/Payment/Endpoints/GetVenues.cs create mode 100644 NetEvent/Server/Modules/Payment/Endpoints/PostCart.cs create mode 100644 NetEvent/Server/Modules/Payment/Endpoints/PutVenue.cs create mode 100644 NetEvent/Server/Modules/Payment/PaymentModule.cs create mode 100644 NetEvent/Shared/Dto/CartDto.cs create mode 100644 NetEvent/Shared/Dto/CartEntryDto.cs diff --git a/NetEvent/Server/Data/ApplicationDbContext.cs b/NetEvent/Server/Data/ApplicationDbContext.cs index 974d10db..81b2372c 100644 --- a/NetEvent/Server/Data/ApplicationDbContext.cs +++ b/NetEvent/Server/Data/ApplicationDbContext.cs @@ -34,6 +34,10 @@ public ApplicationDbContext(DbContextOptions options, IReadOnlyCollection Venues => Set(); + public virtual DbSet Purchases => Set(); + + public virtual DbSet TicketPurchases => Set(); + public virtual DbSet Tickets => Set(); public override EntityEntry Add(TEntity entity) diff --git a/NetEvent/Server/Data/IPaymentManager.cs b/NetEvent/Server/Data/IPaymentManager.cs new file mode 100644 index 00000000..1609a713 --- /dev/null +++ b/NetEvent/Server/Data/IPaymentManager.cs @@ -0,0 +1,12 @@ +using System.Security.Claims; +using System.Threading.Tasks; +using Adyen.Model.Checkout; +using NetEvent.Shared.Dto; + +namespace NetEvent.Server.Data +{ + public interface IPaymentManager + { + Task PayAsync(CartDto cart, ClaimsPrincipal claimsPrincipal); + } +} diff --git a/NetEvent/Server/Data/PaymentManager.cs b/NetEvent/Server/Data/PaymentManager.cs new file mode 100644 index 00000000..bd4737cc --- /dev/null +++ b/NetEvent/Server/Data/PaymentManager.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Adyen.Model.Checkout; +using Adyen.Service; +using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using NetEvent.Server.Helpers; +using NetEvent.Server.Models; +using NetEvent.Server.Modules; +using NetEvent.Shared; +using NetEvent.Shared.Config; +using NetEvent.Shared.Dto; +using NetEvent.Shared.Dto.Event; + +namespace NetEvent.Server.Data +{ + public class PaymentManager : IPaymentManager + { + private readonly ApplicationDbContext _DbContext; + + private readonly NetEventUserManager _UserManager; + + private readonly ILogger _Logger; + + public PaymentManager(ApplicationDbContext dbContext, NetEventUserManager userManager, ILogger logger) + { + _DbContext = dbContext; + _UserManager = userManager; + _Logger = logger; + } + + public async Task PayAsync(CartDto cart, ClaimsPrincipal claimsPrincipal) + { + var paymentId = Guid.NewGuid(); + + var merchantAccount = await _DbContext.SystemSettingValues.FindAsync(SystemSettings.PaymentData.AdyenMerchantAccount).ConfigureAwait(false); + var apiKey = await _DbContext.SystemSettingValues.FindAsync(SystemSettings.PaymentData.AdyenApiKey).ConfigureAwait(false); + + if (string.IsNullOrEmpty(merchantAccount?.SerializedValue)) + { + // TODO Error + return null; + } + + if (string.IsNullOrEmpty(apiKey?.SerializedValue)) + { + // TODO Error + return null; + } + + + var purchase = await CreatePurchaseAsync(cart, claimsPrincipal).ConfigureAwait(false); + + if (purchase == null) + { + return null; + } + + var currencyGroup = purchase.TicketPurchases.GroupBy(x => x.Currency); + if (currencyGroup.Count() > 1) + { + return null; + } + + var checkoutSessionRequest = new CreateCheckoutSessionRequest + { + MerchantAccount = merchantAccount.SerializedValue, + Reference = paymentId.ToString(), + ReturnUrl = "https://your-company.com/checkout?shopperOrder=12xy..", // TODO Checkout Seite mit Polling/Events/... + Amount = new Amount(currencyGroup.First().Key.ToCurrencyDto().To3DigitIso(), purchase.Price), + CountryCode = CultureInfo.CurrentCulture.ToString(), + }; + var client = new Adyen.Client(apiKey.SerializedValue, Adyen.Model.Enum.Environment.Test); + var checkout = new Checkout(client); + return checkout.Sessions(checkoutSessionRequest); + } + + private async Task CreatePurchaseAsync(CartDto cart, ClaimsPrincipal claimsPrincipal) + { + var userId = claimsPrincipal.Id(); + var user = await _UserManager.FindByIdAsync(userId); + + if (user == null) + { + const string errorMessage = "User not found."; + _Logger.LogError(errorMessage); + return null; + } + + var maxPurchaseId = await _DbContext.Purchases.MaxAsync(x => x.Id).ConfigureAwait(false); + + var purchase = new Purchase + { + Id = maxPurchaseId + 1, + PurchaseTime = DateTime.UtcNow, + User = user, + UserId = user.Id, + }; + + await CreateTicketPurchasesAsync(cart, purchase).ConfigureAwait(false); + + return purchase; + } + + private async Task CreateTicketPurchasesAsync(CartDto cart, Purchase purchase) + { + var maxTicketPurchaseId = await _DbContext.TicketPurchases.MaxAsync(x => x.Id).ConfigureAwait(false); + var ticketPurchases = new List(); + foreach (var cartTicket in cart.CartEntries.Where(e => e.TicketId != null)) + { + var ticketType = await _DbContext.Tickets.FindAsync(cartTicket.TicketId).ConfigureAwait(false); + if (ticketType == null) + { + throw new NotSupportedException($"TicketId {cartTicket.TicketId} not found!"); + } + + ticketPurchases.AddRange(Enumerable.Repeat(null, cartTicket.Amount).Select(_ => new TicketPurchase + { + Id = ++maxTicketPurchaseId, + Currency = ticketType.Currency, + Price = ticketType.Price, + Purchase = purchase, + PurchaseId = purchase.Id, + Ticket = ticketType, + TicketId = ticketType.Id + })); + } + + if (ticketPurchases.Any()) + { + purchase.TicketPurchases = ticketPurchases; + } + } + } +} diff --git a/NetEvent/Server/Helpers/DtoMapper.cs b/NetEvent/Server/Helpers/DtoMapper.cs index 21de6bec..7748e334 100644 --- a/NetEvent/Server/Helpers/DtoMapper.cs +++ b/NetEvent/Server/Helpers/DtoMapper.cs @@ -57,6 +57,8 @@ public static partial class DtoMapper public static partial EventTicketType ToEventTicketType(this EventTicketTypeDto eventTicketTypeToConvert); + public static partial CurrencyDto ToCurrencyDto(this Currency currency); + public static partial VenueDto ToVenueDto(this Venue venue); public static partial Venue ToVenue(this VenueDto venue); diff --git a/NetEvent/Server/Migrations/Psql/20230126222513_AddTickets.Designer.cs b/NetEvent/Server/Migrations/Psql/20230126222513_AddTickets.Designer.cs new file mode 100644 index 00000000..fc091a2b --- /dev/null +++ b/NetEvent/Server/Migrations/Psql/20230126222513_AddTickets.Designer.cs @@ -0,0 +1,834 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NetEvent.Server.Data; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace NetEvent.Server.Migrations.Psql +{ + [DbContext(typeof(PsqlApplicationDbContext))] + [Migration("20230126222513_AddTickets")] + partial class AddTickets + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", (string)null); + + b.HasData( + new + { + Id = 1, + ClaimType = "Admin.Users.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 2, + ClaimType = "Admin.Users.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 3, + ClaimType = "Admin.Roles.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 4, + ClaimType = "Admin.Roles.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 5, + ClaimType = "Admin.System.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 6, + ClaimType = "Admin.System.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 7, + ClaimType = "Admin.Images.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 8, + ClaimType = "Admin.Images.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 9, + ClaimType = "Admin.Events.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 10, + ClaimType = "Admin.Events.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 11, + ClaimType = "Admin.Venues.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 12, + ClaimType = "Admin.Venues.Write", + ClaimValue = "", + RoleId = "admin" + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoles", (string)null); + + b.HasData( + new + { + UserId = "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + RoleId = "admin" + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserTokens", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.ApplicationRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("IsDefault") + .HasColumnType("boolean"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("Role", (string)null); + + b.HasData( + new + { + Id = "user", + IsDefault = true, + Name = "User", + NormalizedName = "USER" + }, + new + { + Id = "orga", + IsDefault = false, + Name = "Orga", + NormalizedName = "ORGA" + }, + new + { + Id = "admin", + IsDefault = false, + Name = "Admin", + NormalizedName = "ADMIN" + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("FirstName") + .HasColumnType("text"); + + b.Property("LastName") + .HasColumnType("text"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("ProfilePicture") + .HasColumnType("bytea"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("User", (string)null); + + b.HasData( + new + { + Id = "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + AccessFailedCount = 0, + ConcurrencyStamp = "eef6f288-f1da-41c2-81fa-95eae2e69410", + Email = "admin@admin.de", + EmailConfirmed = true, + FirstName = "Admin", + LastName = "istrator", + LockoutEnabled = false, + NormalizedEmail = "ADMIN@ADMIN.DE", + NormalizedUserName = "ADMIN", + PasswordHash = "AQAAAAIAAYagAAAAEK8gPOw/LRS1KOMtItdcM8BTgCAcUcbU/Vdonq1PDSC5X/SPhWNjh6eRCVI/eqRktw==", + PhoneNumberConfirmed = false, + SecurityStamp = "3806018a-661d-427c-8601-3ee04c4cc6a3", + TwoFactorEnabled = false, + UserName = "admin" + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.EmailTemplate", b => + { + b.Property("TemplateId") + .HasColumnType("text"); + + b.Property("ContentTemplate") + .IsRequired() + .HasColumnType("text"); + + b.Property("SubjectTemplate") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("TemplateId"); + + b.ToTable("EmailTemplates", (string)null); + + b.HasData( + new + { + TemplateId = "UserEmailConfirmEmailTemplate", + ContentTemplate = "

@Model.TemplateVariables[\"firstName\"], welcome to NetEvent.

\n

Please confirm your E-Mail by clicking on the following link:

@Model.TemplateVariables[\"confirmUrl\"] ", + SubjectTemplate = "@Model.TemplateVariables[\"firstName\"], please confirm your E-Mail address." + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("EventFormat") + .HasColumnType("integer"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("ShortDescription") + .HasColumnType("text"); + + b.Property("Slug") + .HasColumnType("text"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("State") + .HasColumnType("integer"); + + b.Property("VenueId") + .HasColumnType("bigint"); + + b.Property("Visibility") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("Slug") + .IsUnique(); + + b.HasIndex("VenueId"); + + b.ToTable("Events", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.EventTicketType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AvailableTickets") + .HasColumnType("bigint"); + + b.Property("Currency") + .HasColumnType("integer"); + + b.Property("EventId") + .HasColumnType("bigint"); + + b.Property("IsGiftable") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("integer"); + + b.Property("SellEndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SellStartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Slug") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("EventId"); + + b.ToTable("EventTicketTypes", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PurchaseTime") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Purchases", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.SystemImage", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Data") + .HasColumnType("bytea"); + + b.Property("Extension") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("UploadTime") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("SystemImages", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.SystemSettingValue", b => + { + b.Property("Key") + .HasColumnType("text"); + + b.Property("SerializedValue") + .HasColumnType("text"); + + b.HasKey("Key"); + + b.ToTable("SystemSettings", (string)null); + + b.HasData( + new + { + Key = "OrganizationName", + SerializedValue = "NetEvent" + }, + new + { + Key = "HideOrganizationNameInNavBar", + SerializedValue = "False" + }, + new + { + Key = "DataCultureInfo", + SerializedValue = "en-US" + }, + new + { + Key = "Favicon", + SerializedValue = "" + }, + new + { + Key = "Logo", + SerializedValue = "" + }, + new + { + Key = "AboutUs", + SerializedValue = "" + }, + new + { + Key = "LegalNotice", + SerializedValue = "" + }, + new + { + Key = "PrivacyPolicy", + SerializedValue = "" + }, + new + { + Key = "PrimaryColor", + SerializedValue = "" + }, + new + { + Key = "PrimaryTextColor", + SerializedValue = "" + }, + new + { + Key = "SecondaryColor", + SerializedValue = "" + }, + new + { + Key = "SecondaryTextColor", + SerializedValue = "" + }, + new + { + Key = "Background", + SerializedValue = "" + }, + new + { + Key = "AppbarBackground", + SerializedValue = "" + }, + new + { + Key = "AppbarText", + SerializedValue = "" + }, + new + { + Key = "CustomCss", + SerializedValue = "" + }, + new + { + Key = "Standard", + SerializedValue = "True" + }, + new + { + Key = "Steam", + SerializedValue = "False" + }, + new + { + Key = "AdyenApiKey ", + SerializedValue = "" + }, + new + { + Key = "AdyenClientKey ", + SerializedValue = "" + }, + new + { + Key = "AdyenMerchantAccount ", + SerializedValue = "" + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.TicketPurchase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Currency") + .HasColumnType("integer"); + + b.Property("Price") + .HasColumnType("integer"); + + b.Property("PurchaseId") + .HasColumnType("bigint"); + + b.Property("TicketId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("PurchaseId"); + + b.HasIndex("TicketId"); + + b.ToTable("TicketPurchases", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Venue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("City") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("text"); + + b.Property("Slug") + .HasColumnType("text"); + + b.Property("Street") + .HasColumnType("text"); + + b.Property("ZipCode") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Venues", (string)null); + }); + + modelBuilder.Entity("NetEvent.Shared.Dto.ThemeDto", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ThemeData") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Themes", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.HasOne("NetEvent.Server.Models.Venue", "Venue") + .WithMany() + .HasForeignKey("VenueId"); + + b.Navigation("Venue"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.EventTicketType", b => + { + b.HasOne("NetEvent.Server.Models.Event", "Event") + .WithMany("TicketTypes") + .HasForeignKey("EventId"); + + b.Navigation("Event"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.TicketPurchase", b => + { + b.HasOne("NetEvent.Server.Models.Purchase", "Purchase") + .WithMany("TicketPurchases") + .HasForeignKey("PurchaseId"); + + b.HasOne("NetEvent.Server.Models.EventTicketType", "Ticket") + .WithMany() + .HasForeignKey("TicketId"); + + b.Navigation("Purchase"); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.Navigation("TicketTypes"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => + { + b.Navigation("TicketPurchases"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/NetEvent/Server/Migrations/Psql/20230126222513_AddTickets.cs b/NetEvent/Server/Migrations/Psql/20230126222513_AddTickets.cs new file mode 100644 index 00000000..cf405d2e --- /dev/null +++ b/NetEvent/Server/Migrations/Psql/20230126222513_AddTickets.cs @@ -0,0 +1,127 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace NetEvent.Server.Migrations.Psql +{ + /// + public partial class AddTickets : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Purchases", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + PurchaseTime = table.Column(type: "timestamp with time zone", nullable: true), + UserId = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Purchases", x => x.Id); + table.ForeignKey( + name: "FK_Purchases_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "TicketPurchases", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + TicketId = table.Column(type: "bigint", nullable: true), + PurchaseId = table.Column(type: "bigint", nullable: true), + Price = table.Column(type: "integer", nullable: false), + Currency = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_TicketPurchases", x => x.Id); + table.ForeignKey( + name: "FK_TicketPurchases_EventTicketTypes_TicketId", + column: x => x.TicketId, + principalTable: "EventTicketTypes", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_TicketPurchases_Purchases_PurchaseId", + column: x => x.PurchaseId, + principalTable: "Purchases", + principalColumn: "Id"); + }); + + migrationBuilder.InsertData( + table: "SystemSettings", + columns: new[] { "Key", "SerializedValue" }, + values: new object[,] + { + { "AdyenApiKey ", "" }, + { "AdyenClientKey ", "" }, + { "AdyenMerchantAccount ", "" } + }); + + migrationBuilder.UpdateData( + table: "User", + keyColumn: "Id", + keyValue: "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + columns: new[] { "ConcurrencyStamp", "PasswordHash", "SecurityStamp" }, + values: new object[] { "eef6f288-f1da-41c2-81fa-95eae2e69410", "AQAAAAIAAYagAAAAEK8gPOw/LRS1KOMtItdcM8BTgCAcUcbU/Vdonq1PDSC5X/SPhWNjh6eRCVI/eqRktw==", "3806018a-661d-427c-8601-3ee04c4cc6a3" }); + + migrationBuilder.CreateIndex( + name: "IX_Purchases_UserId", + table: "Purchases", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_TicketPurchases_PurchaseId", + table: "TicketPurchases", + column: "PurchaseId"); + + migrationBuilder.CreateIndex( + name: "IX_TicketPurchases_TicketId", + table: "TicketPurchases", + column: "TicketId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "TicketPurchases"); + + migrationBuilder.DropTable( + name: "Purchases"); + + migrationBuilder.DeleteData( + table: "SystemSettings", + keyColumn: "Key", + keyValue: "AdyenApiKey "); + + migrationBuilder.DeleteData( + table: "SystemSettings", + keyColumn: "Key", + keyValue: "AdyenClientKey "); + + migrationBuilder.DeleteData( + table: "SystemSettings", + keyColumn: "Key", + keyValue: "AdyenMerchantAccount "); + + migrationBuilder.UpdateData( + table: "User", + keyColumn: "Id", + keyValue: "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + columns: new[] { "ConcurrencyStamp", "PasswordHash", "SecurityStamp" }, + values: new object[] { "f04ce91e-9530-4345-8cb6-ca7064b18f9e", "AQAAAAIAAYagAAAAEBQZqmlKIsoqJXLPAEONrg4qS/LiDqczL05LikcpplHSrajOE+VxOsnzvK2Xq5bxig==", "9529d94c-3a1d-4616-b977-af03e35856e8" }); + } + } +} diff --git a/NetEvent/Server/Migrations/Psql/PsqlApplicationDbContextModelSnapshot.cs b/NetEvent/Server/Migrations/Psql/PsqlApplicationDbContextModelSnapshot.cs index 1417c170..2d8f1ba9 100644 --- a/NetEvent/Server/Migrations/Psql/PsqlApplicationDbContextModelSnapshot.cs +++ b/NetEvent/Server/Migrations/Psql/PsqlApplicationDbContextModelSnapshot.cs @@ -17,7 +17,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "7.0.1") + .HasAnnotation("ProductVersion", "7.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); @@ -354,7 +354,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { Id = "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", AccessFailedCount = 0, - ConcurrencyStamp = "f04ce91e-9530-4345-8cb6-ca7064b18f9e", + ConcurrencyStamp = "eef6f288-f1da-41c2-81fa-95eae2e69410", Email = "admin@admin.de", EmailConfirmed = true, FirstName = "Admin", @@ -362,9 +362,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) LockoutEnabled = false, NormalizedEmail = "ADMIN@ADMIN.DE", NormalizedUserName = "ADMIN", - PasswordHash = "AQAAAAIAAYagAAAAEBQZqmlKIsoqJXLPAEONrg4qS/LiDqczL05LikcpplHSrajOE+VxOsnzvK2Xq5bxig==", + PasswordHash = "AQAAAAIAAYagAAAAEK8gPOw/LRS1KOMtItdcM8BTgCAcUcbU/Vdonq1PDSC5X/SPhWNjh6eRCVI/eqRktw==", PhoneNumberConfirmed = false, - SecurityStamp = "9529d94c-3a1d-4616-b977-af03e35856e8", + SecurityStamp = "3806018a-661d-427c-8601-3ee04c4cc6a3", TwoFactorEnabled = false, UserName = "admin" }); @@ -486,6 +486,27 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("EventTicketTypes", (string)null); }); + modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PurchaseTime") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Purchases", (string)null); + }); + modelBuilder.Entity("NetEvent.Server.Models.SystemImage", b => { b.Property("Id") @@ -610,9 +631,53 @@ protected override void BuildModel(ModelBuilder modelBuilder) { Key = "Steam", SerializedValue = "False" + }, + new + { + Key = "AdyenApiKey ", + SerializedValue = "" + }, + new + { + Key = "AdyenClientKey ", + SerializedValue = "" + }, + new + { + Key = "AdyenMerchantAccount ", + SerializedValue = "" }); }); + modelBuilder.Entity("NetEvent.Server.Models.TicketPurchase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Currency") + .HasColumnType("integer"); + + b.Property("Price") + .HasColumnType("integer"); + + b.Property("PurchaseId") + .HasColumnType("bigint"); + + b.Property("TicketId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("PurchaseId"); + + b.HasIndex("TicketId"); + + b.ToTable("TicketPurchases", (string)null); + }); + modelBuilder.Entity("NetEvent.Server.Models.Venue", b => { b.Property("Id") @@ -727,10 +792,39 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Event"); }); + modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.TicketPurchase", b => + { + b.HasOne("NetEvent.Server.Models.Purchase", "Purchase") + .WithMany("TicketPurchases") + .HasForeignKey("PurchaseId"); + + b.HasOne("NetEvent.Server.Models.EventTicketType", "Ticket") + .WithMany() + .HasForeignKey("TicketId"); + + b.Navigation("Purchase"); + + b.Navigation("Ticket"); + }); + modelBuilder.Entity("NetEvent.Server.Models.Event", b => { b.Navigation("TicketTypes"); }); + + modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => + { + b.Navigation("TicketPurchases"); + }); #pragma warning restore 612, 618 } } diff --git a/NetEvent/Server/Migrations/Sqlite/20230126222503_AddTickets.Designer.cs b/NetEvent/Server/Migrations/Sqlite/20230126222503_AddTickets.Designer.cs new file mode 100644 index 00000000..50d5a723 --- /dev/null +++ b/NetEvent/Server/Migrations/Sqlite/20230126222503_AddTickets.Designer.cs @@ -0,0 +1,815 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NetEvent.Server.Data; + +#nullable disable + +namespace NetEvent.Server.Migrations.Sqlite +{ + [DbContext(typeof(SqliteApplicationDbContext))] + [Migration("20230126222503_AddTickets")] + partial class AddTickets + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.2"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", (string)null); + + b.HasData( + new + { + Id = 1, + ClaimType = "Admin.Users.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 2, + ClaimType = "Admin.Users.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 3, + ClaimType = "Admin.Roles.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 4, + ClaimType = "Admin.Roles.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 5, + ClaimType = "Admin.System.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 6, + ClaimType = "Admin.System.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 7, + ClaimType = "Admin.Images.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 8, + ClaimType = "Admin.Images.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 9, + ClaimType = "Admin.Events.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 10, + ClaimType = "Admin.Events.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 11, + ClaimType = "Admin.Venues.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 12, + ClaimType = "Admin.Venues.Write", + ClaimValue = "", + RoleId = "admin" + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoles", (string)null); + + b.HasData( + new + { + UserId = "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + RoleId = "admin" + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserTokens", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.ApplicationRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("IsDefault") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("Role", (string)null); + + b.HasData( + new + { + Id = "user", + IsDefault = true, + Name = "User", + NormalizedName = "USER" + }, + new + { + Id = "orga", + IsDefault = false, + Name = "Orga", + NormalizedName = "ORGA" + }, + new + { + Id = "admin", + IsDefault = false, + Name = "Admin", + NormalizedName = "ADMIN" + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("FirstName") + .HasColumnType("TEXT"); + + b.Property("LastName") + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProfilePicture") + .HasColumnType("BLOB"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("User", (string)null); + + b.HasData( + new + { + Id = "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + AccessFailedCount = 0, + ConcurrencyStamp = "5d10c057-f0c5-4439-9ea5-52da9de25db4", + Email = "admin@admin.de", + EmailConfirmed = true, + FirstName = "Admin", + LastName = "istrator", + LockoutEnabled = false, + NormalizedEmail = "ADMIN@ADMIN.DE", + NormalizedUserName = "ADMIN", + PasswordHash = "AQAAAAIAAYagAAAAEHl8xBgwOlrJfSfDpoRyQLa1TdrX7zMysaC62jvZEjAyngzzdjD+zyfPkY2zk66ZGQ==", + PhoneNumberConfirmed = false, + SecurityStamp = "83f864b3-fb09-44e4-9e5c-748beadc4af3", + TwoFactorEnabled = false, + UserName = "admin" + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.EmailTemplate", b => + { + b.Property("TemplateId") + .HasColumnType("TEXT"); + + b.Property("ContentTemplate") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SubjectTemplate") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("TemplateId"); + + b.ToTable("EmailTemplates", (string)null); + + b.HasData( + new + { + TemplateId = "UserEmailConfirmEmailTemplate", + ContentTemplate = "

@Model.TemplateVariables[\"firstName\"], welcome to NetEvent.

\n

Please confirm your E-Mail by clicking on the following link:

@Model.TemplateVariables[\"confirmUrl\"] ", + SubjectTemplate = "@Model.TemplateVariables[\"firstName\"], please confirm your E-Mail address." + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("EventFormat") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("ShortDescription") + .HasColumnType("TEXT"); + + b.Property("Slug") + .HasColumnType("TEXT"); + + b.Property("StartDate") + .HasColumnType("TEXT"); + + b.Property("State") + .HasColumnType("INTEGER"); + + b.Property("VenueId") + .HasColumnType("INTEGER"); + + b.Property("Visibility") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("Slug") + .IsUnique(); + + b.HasIndex("VenueId"); + + b.ToTable("Events", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.EventTicketType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AvailableTickets") + .HasColumnType("INTEGER"); + + b.Property("Currency") + .HasColumnType("INTEGER"); + + b.Property("EventId") + .HasColumnType("INTEGER"); + + b.Property("IsGiftable") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("SellEndDate") + .HasColumnType("TEXT"); + + b.Property("SellStartDate") + .HasColumnType("TEXT"); + + b.Property("Slug") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EventId"); + + b.ToTable("EventTicketTypes", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("PurchaseTime") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Purchases", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.SystemImage", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Data") + .HasColumnType("BLOB"); + + b.Property("Extension") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("UploadTime") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("SystemImages", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.SystemSettingValue", b => + { + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("SerializedValue") + .HasColumnType("TEXT"); + + b.HasKey("Key"); + + b.ToTable("SystemSettings", (string)null); + + b.HasData( + new + { + Key = "OrganizationName", + SerializedValue = "NetEvent" + }, + new + { + Key = "HideOrganizationNameInNavBar", + SerializedValue = "False" + }, + new + { + Key = "DataCultureInfo", + SerializedValue = "en-US" + }, + new + { + Key = "Favicon", + SerializedValue = "" + }, + new + { + Key = "Logo", + SerializedValue = "" + }, + new + { + Key = "AboutUs", + SerializedValue = "" + }, + new + { + Key = "LegalNotice", + SerializedValue = "" + }, + new + { + Key = "PrivacyPolicy", + SerializedValue = "" + }, + new + { + Key = "PrimaryColor", + SerializedValue = "" + }, + new + { + Key = "PrimaryTextColor", + SerializedValue = "" + }, + new + { + Key = "SecondaryColor", + SerializedValue = "" + }, + new + { + Key = "SecondaryTextColor", + SerializedValue = "" + }, + new + { + Key = "Background", + SerializedValue = "" + }, + new + { + Key = "AppbarBackground", + SerializedValue = "" + }, + new + { + Key = "AppbarText", + SerializedValue = "" + }, + new + { + Key = "CustomCss", + SerializedValue = "" + }, + new + { + Key = "Standard", + SerializedValue = "True" + }, + new + { + Key = "Steam", + SerializedValue = "False" + }, + new + { + Key = "AdyenApiKey ", + SerializedValue = "" + }, + new + { + Key = "AdyenClientKey ", + SerializedValue = "" + }, + new + { + Key = "AdyenMerchantAccount ", + SerializedValue = "" + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.TicketPurchase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Currency") + .HasColumnType("INTEGER"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("PurchaseId") + .HasColumnType("INTEGER"); + + b.Property("TicketId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PurchaseId"); + + b.HasIndex("TicketId"); + + b.ToTable("TicketPurchases", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Venue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("City") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Number") + .HasColumnType("TEXT"); + + b.Property("Slug") + .HasColumnType("TEXT"); + + b.Property("Street") + .HasColumnType("TEXT"); + + b.Property("ZipCode") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Venues", (string)null); + }); + + modelBuilder.Entity("NetEvent.Shared.Dto.ThemeDto", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ThemeData") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Themes", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.HasOne("NetEvent.Server.Models.Venue", "Venue") + .WithMany() + .HasForeignKey("VenueId"); + + b.Navigation("Venue"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.EventTicketType", b => + { + b.HasOne("NetEvent.Server.Models.Event", "Event") + .WithMany("TicketTypes") + .HasForeignKey("EventId"); + + b.Navigation("Event"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.TicketPurchase", b => + { + b.HasOne("NetEvent.Server.Models.Purchase", "Purchase") + .WithMany("TicketPurchases") + .HasForeignKey("PurchaseId"); + + b.HasOne("NetEvent.Server.Models.EventTicketType", "Ticket") + .WithMany() + .HasForeignKey("TicketId"); + + b.Navigation("Purchase"); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.Navigation("TicketTypes"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => + { + b.Navigation("TicketPurchases"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/NetEvent/Server/Migrations/Sqlite/20230126222503_AddTickets.cs b/NetEvent/Server/Migrations/Sqlite/20230126222503_AddTickets.cs new file mode 100644 index 00000000..5420660b --- /dev/null +++ b/NetEvent/Server/Migrations/Sqlite/20230126222503_AddTickets.cs @@ -0,0 +1,126 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace NetEvent.Server.Migrations.Sqlite +{ + /// + public partial class AddTickets : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Purchases", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + PurchaseTime = table.Column(type: "TEXT", nullable: true), + UserId = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Purchases", x => x.Id); + table.ForeignKey( + name: "FK_Purchases_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "TicketPurchases", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + TicketId = table.Column(type: "INTEGER", nullable: true), + PurchaseId = table.Column(type: "INTEGER", nullable: true), + Price = table.Column(type: "INTEGER", nullable: false), + Currency = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_TicketPurchases", x => x.Id); + table.ForeignKey( + name: "FK_TicketPurchases_EventTicketTypes_TicketId", + column: x => x.TicketId, + principalTable: "EventTicketTypes", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_TicketPurchases_Purchases_PurchaseId", + column: x => x.PurchaseId, + principalTable: "Purchases", + principalColumn: "Id"); + }); + + migrationBuilder.InsertData( + table: "SystemSettings", + columns: new[] { "Key", "SerializedValue" }, + values: new object[,] + { + { "AdyenApiKey ", "" }, + { "AdyenClientKey ", "" }, + { "AdyenMerchantAccount ", "" } + }); + + migrationBuilder.UpdateData( + table: "User", + keyColumn: "Id", + keyValue: "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + columns: new[] { "ConcurrencyStamp", "PasswordHash", "SecurityStamp" }, + values: new object[] { "5d10c057-f0c5-4439-9ea5-52da9de25db4", "AQAAAAIAAYagAAAAEHl8xBgwOlrJfSfDpoRyQLa1TdrX7zMysaC62jvZEjAyngzzdjD+zyfPkY2zk66ZGQ==", "83f864b3-fb09-44e4-9e5c-748beadc4af3" }); + + migrationBuilder.CreateIndex( + name: "IX_Purchases_UserId", + table: "Purchases", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_TicketPurchases_PurchaseId", + table: "TicketPurchases", + column: "PurchaseId"); + + migrationBuilder.CreateIndex( + name: "IX_TicketPurchases_TicketId", + table: "TicketPurchases", + column: "TicketId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "TicketPurchases"); + + migrationBuilder.DropTable( + name: "Purchases"); + + migrationBuilder.DeleteData( + table: "SystemSettings", + keyColumn: "Key", + keyValue: "AdyenApiKey "); + + migrationBuilder.DeleteData( + table: "SystemSettings", + keyColumn: "Key", + keyValue: "AdyenClientKey "); + + migrationBuilder.DeleteData( + table: "SystemSettings", + keyColumn: "Key", + keyValue: "AdyenMerchantAccount "); + + migrationBuilder.UpdateData( + table: "User", + keyColumn: "Id", + keyValue: "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + columns: new[] { "ConcurrencyStamp", "PasswordHash", "SecurityStamp" }, + values: new object[] { "26cbb106-629e-4b0f-b528-03e4fbaf148e", "AQAAAAIAAYagAAAAEMVeCrEoGoqMFSa9mWv07gyORfXVq9Zash81NSc3Z4QmFWadfMKOABkphkaem7Q7nQ==", "56b690d3-1bb2-4ef1-8fde-0397861a166b" }); + } + } +} diff --git a/NetEvent/Server/Migrations/Sqlite/SqliteApplicationDbContextModelSnapshot.cs b/NetEvent/Server/Migrations/Sqlite/SqliteApplicationDbContextModelSnapshot.cs index 73705028..ab7cd474 100644 --- a/NetEvent/Server/Migrations/Sqlite/SqliteApplicationDbContextModelSnapshot.cs +++ b/NetEvent/Server/Migrations/Sqlite/SqliteApplicationDbContextModelSnapshot.cs @@ -15,7 +15,7 @@ partial class SqliteApplicationDbContextModelSnapshot : ModelSnapshot protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "7.0.1"); + modelBuilder.HasAnnotation("ProductVersion", "7.0.2"); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { @@ -345,7 +345,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { Id = "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", AccessFailedCount = 0, - ConcurrencyStamp = "26cbb106-629e-4b0f-b528-03e4fbaf148e", + ConcurrencyStamp = "5d10c057-f0c5-4439-9ea5-52da9de25db4", Email = "admin@admin.de", EmailConfirmed = true, FirstName = "Admin", @@ -353,9 +353,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) LockoutEnabled = false, NormalizedEmail = "ADMIN@ADMIN.DE", NormalizedUserName = "ADMIN", - PasswordHash = "AQAAAAIAAYagAAAAEMVeCrEoGoqMFSa9mWv07gyORfXVq9Zash81NSc3Z4QmFWadfMKOABkphkaem7Q7nQ==", + PasswordHash = "AQAAAAIAAYagAAAAEHl8xBgwOlrJfSfDpoRyQLa1TdrX7zMysaC62jvZEjAyngzzdjD+zyfPkY2zk66ZGQ==", PhoneNumberConfirmed = false, - SecurityStamp = "56b690d3-1bb2-4ef1-8fde-0397861a166b", + SecurityStamp = "83f864b3-fb09-44e4-9e5c-748beadc4af3", TwoFactorEnabled = false, UserName = "admin" }); @@ -473,6 +473,25 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("EventTicketTypes", (string)null); }); + modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("PurchaseTime") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Purchases", (string)null); + }); + modelBuilder.Entity("NetEvent.Server.Models.SystemImage", b => { b.Property("Id") @@ -597,9 +616,51 @@ protected override void BuildModel(ModelBuilder modelBuilder) { Key = "Steam", SerializedValue = "False" + }, + new + { + Key = "AdyenApiKey ", + SerializedValue = "" + }, + new + { + Key = "AdyenClientKey ", + SerializedValue = "" + }, + new + { + Key = "AdyenMerchantAccount ", + SerializedValue = "" }); }); + modelBuilder.Entity("NetEvent.Server.Models.TicketPurchase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Currency") + .HasColumnType("INTEGER"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("PurchaseId") + .HasColumnType("INTEGER"); + + b.Property("TicketId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PurchaseId"); + + b.HasIndex("TicketId"); + + b.ToTable("TicketPurchases", (string)null); + }); + modelBuilder.Entity("NetEvent.Server.Models.Venue", b => { b.Property("Id") @@ -712,10 +773,39 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Event"); }); + modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.TicketPurchase", b => + { + b.HasOne("NetEvent.Server.Models.Purchase", "Purchase") + .WithMany("TicketPurchases") + .HasForeignKey("PurchaseId"); + + b.HasOne("NetEvent.Server.Models.EventTicketType", "Ticket") + .WithMany() + .HasForeignKey("TicketId"); + + b.Navigation("Purchase"); + + b.Navigation("Ticket"); + }); + modelBuilder.Entity("NetEvent.Server.Models.Event", b => { b.Navigation("TicketTypes"); }); + + modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => + { + b.Navigation("TicketPurchases"); + }); #pragma warning restore 612, 618 } } diff --git a/NetEvent/Server/Models/Purchase.cs b/NetEvent/Server/Models/Purchase.cs index ca56e427..136cf699 100644 --- a/NetEvent/Server/Models/Purchase.cs +++ b/NetEvent/Server/Models/Purchase.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; namespace NetEvent.Server.Models; @@ -60,10 +62,15 @@ public class Purchase public DateTime? PurchaseTime { get; set; } - public long? UserId { get; set; } + public string? UserId { get; set; } [ForeignKey(nameof(UserId))] public ApplicationUser? User { get; set; } + + [InverseProperty(nameof(TicketPurchase.Purchase))] + public List? TicketPurchases { get; set; } + + public int Price => TicketPurchases?.Sum(x => x.Price) ?? 0; } public class TicketPurchase diff --git a/NetEvent/Server/Modules/ModuleExtensions.cs b/NetEvent/Server/Modules/ModuleExtensions.cs index 89b104d8..2ae3d9fb 100644 --- a/NetEvent/Server/Modules/ModuleExtensions.cs +++ b/NetEvent/Server/Modules/ModuleExtensions.cs @@ -57,7 +57,6 @@ public static WebApplication MapEndpoints(this WebApplication app) writeModuleGroup.RequireAuthorization(writePolicy); } } - return app; } diff --git a/NetEvent/Server/Modules/Payment/Endpoints/DeleteVenue.cs b/NetEvent/Server/Modules/Payment/Endpoints/DeleteVenue.cs new file mode 100644 index 00000000..073bb790 --- /dev/null +++ b/NetEvent/Server/Modules/Payment/Endpoints/DeleteVenue.cs @@ -0,0 +1,53 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using NetEvent.Server.Data.Events; + +namespace NetEvent.Server.Modules.Payment.Endpoints +{ + public static class DeleteVenue + { + public sealed class Handler : IRequestHandler + { + private readonly IEventManager _EventManager; + + public Handler(IEventManager eventManager) + { + _EventManager = eventManager; + } + + public async Task Handle(Request request, CancellationToken cancellationToken) + { + var result = await _EventManager.DeleteVenueAsync(request.VenueId).ConfigureAwait(false); + if (!result.Succeeded) + { + return new Response(ReturnType.Error, string.Join(Environment.NewLine, result.Errors)); + } + + return new Response(); + } + } + + public sealed class Request : IRequest + { + public Request(long venueId) + { + VenueId = venueId; + } + + public long VenueId { get; } + } + + public sealed class Response : ResponseBase + { + public Response() + { + } + + public Response(ReturnType returnType, string error) : base(returnType, error) + { + } + } + } +} diff --git a/NetEvent/Server/Modules/Payment/Endpoints/GetVenue.cs b/NetEvent/Server/Modules/Payment/Endpoints/GetVenue.cs new file mode 100644 index 00000000..2a4f80c4 --- /dev/null +++ b/NetEvent/Server/Modules/Payment/Endpoints/GetVenue.cs @@ -0,0 +1,74 @@ +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using NetEvent.Server.Data; +using NetEvent.Shared; +using NetEvent.Shared.Dto.Event; + +namespace NetEvent.Server.Modules.Payment.Endpoints +{ + public static class GetVenue + { + public sealed class Handler : IRequestHandler + { + private readonly ApplicationDbContext _DbContext; + + public Handler(ApplicationDbContext dbContext) + { + _DbContext = dbContext; + } + + public async Task Handle(Request request, CancellationToken cancellationToken) + { + Models.Venue? venueModel; + if (request.Slug != null) + { + venueModel = _DbContext.Venues.Where(e => e.Slug != null && e.Slug.Equals(request.Slug, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); + } + else + { + venueModel = await _DbContext.Venues.FindAsync(new object[] { request.Id }, cancellationToken); + } + + if (venueModel == null) + { + return new Response(ReturnType.NotFound, "Venue for Id not found!"); + } + + var convertedVenue = venueModel.ToVenueDto(); + + return new Response(convertedVenue); + } + } + + public sealed class Request : IRequest + { + public Request(long id) + { + Id = id; + } + + public Request(string slug) + { + Slug = slug; + } + + public long Id { get; } + + public string? Slug { get; } + } + + public sealed class Response : ResponseBase + { + public Response(VenueDto? value) : base(value) + { + } + + public Response(ReturnType returnType, string error) : base(returnType, error) + { + } + } + } +} diff --git a/NetEvent/Server/Modules/Payment/Endpoints/GetVenues.cs b/NetEvent/Server/Modules/Payment/Endpoints/GetVenues.cs new file mode 100644 index 00000000..fd70e656 --- /dev/null +++ b/NetEvent/Server/Modules/Payment/Endpoints/GetVenues.cs @@ -0,0 +1,47 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Microsoft.EntityFrameworkCore; +using NetEvent.Server.Data; +using NetEvent.Shared; +using NetEvent.Shared.Dto.Event; + +namespace NetEvent.Server.Modules.Payment.Endpoints +{ + public static class GetVenues + { + public sealed class Handler : IRequestHandler + { + private readonly ApplicationDbContext _DbContext; + + public Handler(ApplicationDbContext dbContext) + { + _DbContext = dbContext; + } + + public async Task Handle(Request request, CancellationToken cancellationToken) + { + var allVenues = await _DbContext.Venues.ToListAsync(cancellationToken); + var convertedVenues = allVenues.Select(DtoMapper.ToVenueDto).ToList(); + return new Response(convertedVenues); + } + } + + public sealed class Request : IRequest + { + } + + public sealed class Response : ResponseBase> + { + public Response(IEnumerable? value) : base(value) + { + } + + public Response(ReturnType returnType, string error) : base(returnType, error) + { + } + } + } +} diff --git a/NetEvent/Server/Modules/Payment/Endpoints/PostCart.cs b/NetEvent/Server/Modules/Payment/Endpoints/PostCart.cs new file mode 100644 index 00000000..1a48f880 --- /dev/null +++ b/NetEvent/Server/Modules/Payment/Endpoints/PostCart.cs @@ -0,0 +1,63 @@ +using System; +using System.Security.Claims; +using System.Threading; +using System.Threading.Tasks; +using Adyen.Model.Checkout; +using MediatR; +using NetEvent.Server.Data; +using NetEvent.Server.Data.Events; +using NetEvent.Shared; +using NetEvent.Shared.Dto; + +namespace NetEvent.Server.Modules.Payment.Endpoints +{ + public static class PostCart + { + public sealed class Handler : IRequestHandler + { + private readonly IPaymentManager _PaymentManager; + + public Handler(IPaymentManager paymentManager) + { + _PaymentManager = paymentManager; + } + + public async Task Handle(Request request, CancellationToken cancellationToken) + { + return new Response(await _PaymentManager.PayAsync(request.CartDto, request.User)); + //var newVenue = request.Venue.ToVenue(); + //var result = await _PaymentManager.CreateVenueAsync(newVenue).ConfigureAwait(false); + //if (!result.Succeeded || newVenue.Id == null) + //{ + // return new Response(ReturnType.Error, string.Join(Environment.NewLine, result.Errors)); + //} + + //return new Response(newVenue.Id!.Value); + } + } + + public sealed class Request : IRequest + { + public Request(CartDto cartDto, ClaimsPrincipal user) + { + CartDto = cartDto; + User = user; + } + + public CartDto CartDto { get; } + + public ClaimsPrincipal User { get; } + } + + public sealed class Response : ResponseBase + { + public Response(CreateCheckoutSessionResponse response) : base(response) + { + } + + public Response(ReturnType returnType, string error) : base(returnType, error) + { + } + } + } +} diff --git a/NetEvent/Server/Modules/Payment/Endpoints/PutVenue.cs b/NetEvent/Server/Modules/Payment/Endpoints/PutVenue.cs new file mode 100644 index 00000000..42ec0c10 --- /dev/null +++ b/NetEvent/Server/Modules/Payment/Endpoints/PutVenue.cs @@ -0,0 +1,62 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using NetEvent.Server.Data.Events; +using NetEvent.Shared; +using NetEvent.Shared.Dto.Event; + +namespace NetEvent.Server.Modules.Payment.Endpoints +{ + public static class PutVenue + { + public sealed class Handler : IRequestHandler + { + private readonly IEventManager _EventManager; + + public Handler(IEventManager eventManager) + { + _EventManager = eventManager; + } + + public async Task Handle(Request request, CancellationToken cancellationToken) + { + var newVenue = request.Venue.ToVenue(); + var result = await _EventManager.UpdateVenueAsync(newVenue).ConfigureAwait(false); + if (!result.Succeeded) + { + return new Response(ReturnType.Error, string.Join(Environment.NewLine, result.Errors)); + } + + return new Response(newVenue.ToVenueDto()); + } + } + + public sealed class Request : IRequest + { + public Request(long id, VenueDto venueDto) + { + Guard.IsNotNull(venueDto, nameof(venueDto)); + Guard.IsNotNull(venueDto!.Id, nameof(venueDto)); + + Id = id; + Venue = venueDto; + } + + public long Id { get; } + + public VenueDto Venue { get; } + } + + public sealed class Response : ResponseBase + { + public Response(VenueDto createdVenue) : base(createdVenue) + { + } + + public Response(ReturnType returnType, string error) : base(returnType, error) + { + } + } + } +} diff --git a/NetEvent/Server/Modules/Payment/PaymentModule.cs b/NetEvent/Server/Modules/Payment/PaymentModule.cs new file mode 100644 index 00000000..50c80447 --- /dev/null +++ b/NetEvent/Server/Modules/Payment/PaymentModule.cs @@ -0,0 +1,43 @@ +using System.Security.Claims; +using MediatR; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.EntityFrameworkCore; +using NetEvent.Server.Models; +using NetEvent.Server.Modules; +using NetEvent.Server.Modules.Payment.Endpoints; +using NetEvent.Shared.Dto; +using NetEvent.Shared.Dto.Event; + +namespace NetVenue.Server.Modules.Payment +{ + public class PaymentModule : ModuleBase + { + public override IEndpointRouteBuilder MapModuleEndpoints(IEndpointRouteBuilder endpoints) + { + // BaseRoute: /api/payment + endpoints.MapPost("/buy", async ([FromBody] CartDto cartDto, ClaimsPrincipal user, [FromServices] IMediator m) => ToApiResult(await m.Send(new PostCart.Request(cartDto, user)))); + //endpoints.MapGet("/{venueId:long}", async ([FromRoute] long venueId, [FromServices] IMediator m) => ToApiResult(await m.Send(new GetVenue.Request(venueId)))); + //endpoints.MapGet("/{slug}", async ([FromRoute] string slug, [FromServices] IMediator m) => ToApiResult(await m.Send(new GetVenue.Request(slug)))); + //endpoints.MapGet("/", async ([FromServices] IMediator m) => ToApiResult(await m.Send(new GetVenues.Request()))); + //endpoints.MapPost("/", async ([FromBody] VenueDto venueDto, [FromServices] IMediator m) => ToApiResult(await m.Send(new PostVenue.Request(venueDto)))); + //endpoints.MapPut("/{venueId}", async ([FromRoute] long venueId, [FromBody] VenueDto venueDto, [FromServices] IMediator m) => ToApiResult(await m.Send(new PutVenue.Request(venueId, venueDto)))); + //endpoints.MapDelete("/{venueId}", async ([FromRoute] long venueId, [FromServices] IMediator m) => ToApiResult(await m.Send(new DeleteVenue.Request(venueId)))); + + return endpoints; + } + + public override void OnModelCreating(ModelBuilder builder) + { + builder.Entity(entity => + { + entity.ToTable(name: "Purchases"); + }); + builder.Entity(entity => + { + entity.ToTable(name: "TicketPurchases"); + }); + } + } +} diff --git a/NetEvent/Server/NetEvent.Server.csproj b/NetEvent/Server/NetEvent.Server.csproj index 28bad44e..1c28ae7b 100644 --- a/NetEvent/Server/NetEvent.Server.csproj +++ b/NetEvent/Server/NetEvent.Server.csproj @@ -19,6 +19,7 @@ + diff --git a/NetEvent/Server/Program.cs b/NetEvent/Server/Program.cs index 358d871e..753e5303 100644 --- a/NetEvent/Server/Program.cs +++ b/NetEvent/Server/Program.cs @@ -103,6 +103,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddSingleton(); diff --git a/NetEvent/Shared/Config/SystemSettingGroup.cs b/NetEvent/Shared/Config/SystemSettingGroup.cs index 4a5b37fc..6dabd466 100644 --- a/NetEvent/Shared/Config/SystemSettingGroup.cs +++ b/NetEvent/Shared/Config/SystemSettingGroup.cs @@ -5,5 +5,6 @@ public enum SystemSettingGroup OrganizationData, AuthenticationData, StyleData, + PaymentData, } } diff --git a/NetEvent/Shared/Config/SystemSettings.cs b/NetEvent/Shared/Config/SystemSettings.cs index 74bad957..8c87faf4 100644 --- a/NetEvent/Shared/Config/SystemSettings.cs +++ b/NetEvent/Shared/Config/SystemSettings.cs @@ -12,7 +12,8 @@ private SystemSettings() { new OrganizationData(), new StyleData(), - new AuthenticationData() + new AuthenticationData(), + new PaymentData(), }; } @@ -56,6 +57,20 @@ public AuthenticationData() : base(SystemSettingGroup.AuthenticationData) } } + public class PaymentData : SettingGroupBase + { + public const string AdyenApiKey = "AdyenApiKey "; + public const string AdyenClientKey = "AdyenClientKey "; + public const string AdyenMerchantAccount = "AdyenMerchantAccount "; + + public PaymentData() : base(SystemSettingGroup.PaymentData) + { + CreateSystemSettingWithHint(AdyenApiKey, new StringValueType(string.Empty)); + CreateSystemSettingWithHint(AdyenClientKey, new StringValueType(string.Empty)); + CreateSystemSettingWithHint(AdyenMerchantAccount, new StringValueType(string.Empty)); + } + } + public class StyleData : SettingGroupBase { public const string PrimaryColor = "PrimaryColor"; diff --git a/NetEvent/Shared/Dto/CartDto.cs b/NetEvent/Shared/Dto/CartDto.cs new file mode 100644 index 00000000..d5718819 --- /dev/null +++ b/NetEvent/Shared/Dto/CartDto.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace NetEvent.Shared.Dto; + +public class CartDto +{ + [JsonPropertyName("cartentries")] + public IReadOnlyList CartEntries { get; set; } = Array.Empty(); +} diff --git a/NetEvent/Shared/Dto/CartEntryDto.cs b/NetEvent/Shared/Dto/CartEntryDto.cs new file mode 100644 index 00000000..a99e9dc4 --- /dev/null +++ b/NetEvent/Shared/Dto/CartEntryDto.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace NetEvent.Shared.Dto; + +public class CartEntryDto +{ + [JsonPropertyName("amount")] + public int Amount { get; set; } + + [JsonPropertyName("ticketId")] + public int? TicketId { get; set; } +} diff --git a/NetEvent/Shared/Dto/Event/CurrencyExtension.cs b/NetEvent/Shared/Dto/Event/CurrencyExtension.cs index bab7703c..47cd74b7 100644 --- a/NetEvent/Shared/Dto/Event/CurrencyExtension.cs +++ b/NetEvent/Shared/Dto/Event/CurrencyExtension.cs @@ -12,5 +12,14 @@ public static string ToSymbol(this CurrencyDto currency) _ => throw new NotSupportedException($"The Currency {currency} is not implemented!"), }; } + + public static string To3DigitIso(this CurrencyDto currency) + { + return currency switch + { + CurrencyDto.Euro => "EUR", + _ => throw new NotSupportedException($"The Currency {currency} is not implemented!"), + }; + } } } diff --git a/NetEvent/Shared/Dto/Event/EventDto.cs b/NetEvent/Shared/Dto/Event/EventDto.cs index d7d71c05..337e1c4b 100644 --- a/NetEvent/Shared/Dto/Event/EventDto.cs +++ b/NetEvent/Shared/Dto/Event/EventDto.cs @@ -28,6 +28,6 @@ public class EventDto public EventFormatDto EventFormat { get; set; } - public ICollection TicketTypes { get; set; } = new Collection(); + public ICollection? TicketTypes { get; set; } = new Collection(); } } From 9903f88cbeedf9bd8d2289f0cd4ad405d5739ed5 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Wed, 1 Feb 2023 21:53:47 +0100 Subject: [PATCH 11/39] Start Add TicketCheckout --- .gitignore | 1 + Directory.Build.props | 7 + NetEvent.sln | 1 + .../Client.Tests/NetEvent.Client.Tests.csproj | 3 - NetEvent/Client/JavaScripts/package-lock.json | 1636 +++++++++++++++++ NetEvent/Client/JavaScripts/package.json | 24 + NetEvent/Client/JavaScripts/src/checkout.js | 2 + NetEvent/Client/JavaScripts/src/index.js | 1 + .../JavaScripts/webpack-checkout.config.js | 11 + NetEvent/Client/NetEvent.Client.csproj | 12 +- NetEvent/Client/Pages/Events/Event.razor | 2 +- NetEvent/Client/Pages/Events/Event.razor.cs | 9 + NetEvent/Client/Program.cs | 4 + NetEvent/Client/Services/CartService.cs | 32 + NetEvent/Client/Services/ICartService.cs | 10 + NetEvent/Client/wwwroot/index.html | 7 + .../Server.Tests/NetEvent.Server.Tests.csproj | 3 - NetEvent/Server/Data/PaymentManager.cs | 3 + NetEvent/Server/NetEvent.Server.csproj | 2 - .../Shared.Tests/NetEvent.Shared.Tests.csproj | 3 - NetEvent/Shared/NetEvent.Shared.csproj | 3 - NetEvent/TestHelper/Fakers.cs | 5 +- .../TestHelper/NetEvent.TestHelper.csproj | 3 - 23 files changed, 1761 insertions(+), 23 deletions(-) create mode 100644 Directory.Build.props create mode 100644 NetEvent/Client/JavaScripts/package-lock.json create mode 100644 NetEvent/Client/JavaScripts/package.json create mode 100644 NetEvent/Client/JavaScripts/src/checkout.js create mode 100644 NetEvent/Client/JavaScripts/src/index.js create mode 100644 NetEvent/Client/JavaScripts/webpack-checkout.config.js create mode 100644 NetEvent/Client/Services/CartService.cs create mode 100644 NetEvent/Client/Services/ICartService.cs diff --git a/.gitignore b/.gitignore index f941d0e2..46c6c204 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ # NetEvent specific NetEvent/Client/wwwroot/lib/ +NetEvent/Client/wwwroot/js/ # User-specific files *.rsuser diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 00000000..005b3859 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,7 @@ + + + net7.0 + enable + true + + \ No newline at end of file diff --git a/NetEvent.sln b/NetEvent.sln index dd63480f..b785f25f 100644 --- a/NetEvent.sln +++ b/NetEvent.sln @@ -14,6 +14,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .editorconfig = .editorconfig .gitignore = .gitignore CodeCoverage.runsettings = CodeCoverage.runsettings + directory.build.props = directory.build.props Makefile = Makefile NetEvent\TestHelper\NetEvent.TestHelper.csproj = NetEvent\TestHelper\NetEvent.TestHelper.csproj README.md = README.md diff --git a/NetEvent/Client.Tests/NetEvent.Client.Tests.csproj b/NetEvent/Client.Tests/NetEvent.Client.Tests.csproj index f301c6d3..279e1e48 100644 --- a/NetEvent/Client.Tests/NetEvent.Client.Tests.csproj +++ b/NetEvent/Client.Tests/NetEvent.Client.Tests.csproj @@ -1,9 +1,6 @@ - net7.0 - enable - false false ..\..\.sonarlint\lan2play_custom.ruleset diff --git a/NetEvent/Client/JavaScripts/package-lock.json b/NetEvent/Client/JavaScripts/package-lock.json new file mode 100644 index 00000000..bb185446 --- /dev/null +++ b/NetEvent/Client/JavaScripts/package-lock.json @@ -0,0 +1,1636 @@ +{ + "name": "NetEvent", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "NetEvent", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@adyen/adyen-web": "^5.32.0" + }, + "devDependencies": { + "css-loader": "^6.7.3", + "style-loader": "^3.3.1", + "webpack": "^5.75.0", + "webpack-cli": "^5.0.1" + } + }, + "node_modules/@adyen/adyen-web": { + "version": "5.32.0", + "resolved": "https://registry.npmjs.org/@adyen/adyen-web/-/adyen-web-5.32.0.tgz", + "integrity": "sha512-12Xi5UAnIWZTK0DZPBs+yFeM3eaMRaXNkPrfOKPrzHLI6qq5OxQ9/wyBDrTBA9phSRqE1HP2vtSzEucC3zIsZw==", + "dependencies": { + "@babel/runtime": "^7.15.4", + "@babel/runtime-corejs3": "^7.20.1", + "@types/applepayjs": "^3.0.4", + "@types/googlepay": "^0.6.2", + "classnames": "^2.3.1", + "core-js-pure": "^3.25.3", + "preact": "10.11.3" + } + }, + "node_modules/@babel/runtime": { + "version": "7.20.13", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz", + "integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==", + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.20.13", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.20.13.tgz", + "integrity": "sha512-p39/6rmY9uvlzRiLZBIB3G9/EBr66LBMcYm7fIDeSBNdRjF2AGD3rFZucUyAgGHC2N+7DdLvVi33uTjSE44FIw==", + "dependencies": { + "core-js-pure": "^3.25.1", + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@types/applepayjs": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/applepayjs/-/applepayjs-3.0.4.tgz", + "integrity": "sha512-RqaVZWy1Kj4e1PoUoOI8uA+4UuuLpicQFxfU9Y/xWJFZFT6mFB4PiiY911iDxFk7pdvaj5HKH7VsWRisRca1Rg==" + }, + "node_modules/@types/eslint": { + "version": "8.4.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.10.tgz", + "integrity": "sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true + }, + "node_modules/@types/googlepay": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@types/googlepay/-/googlepay-0.6.4.tgz", + "integrity": "sha512-PTt/UCllzl8z5HmhymPpSj6uENZvVKZvCBYdDVmbBVJnLStitxtWrterAOQZkKGlqVdzxNXYeif5hOAMNMS5mw==" + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.11.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", + "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", + "dev": true + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.0.1.tgz", + "integrity": "sha512-njsdJXJSiS2iNbQVS0eT8A/KPnmyH4pv1APj2K0d1wrZcBLw+yppxOy4CGqa0OxDJkzfL/XELDhD8rocnIwB5A==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.1.tgz", + "integrity": "sha512-fE1UEWTwsAxRhrJNikE7v4EotYflkEhBL7EbajfkPlf6E37/2QshOy/D48Mw8G5XMFlQtS6YV42vtbG9zBpIQA==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.1.tgz", + "integrity": "sha512-0G7tNyS+yW8TdgHwZKlDWYXFA6OJQnoLCQvYKkQP0Q2X205PSQ6RNUj0M+1OB/9gRQaUZ/ccYfaxd0nhaWKfjw==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/browserslist": { + "version": "4.21.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", + "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001400", + "electron-to-chromium": "^1.4.251", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.9" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001449", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001449.tgz", + "integrity": "sha512-CPB+UL9XMT/Av+pJxCKGhdx+yg1hzplvFJQlJ2n68PyQGMz9L/E2zCyLdOL8uasbouTUgnPl+y0tccI/se+BEw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/core-js-pure": { + "version": "3.27.2", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.27.2.tgz", + "integrity": "sha512-Cf2jqAbXgWH3VVzjyaaFkY1EBazxugUepGymDoeteyYr9ByX51kD2jdHZlsEF/xnJMyN3Prua7mQuzwMg6Zc9A==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-loader": { + "version": "6.7.3", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.3.tgz", + "integrity": "sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.19", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.8" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.284", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", + "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "dev": true + }, + "node_modules/enhanced-resolve": { + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", + "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/is-core-module": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz", + "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", + "dev": true + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", + "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/preact": { + "version": "10.11.3", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.11.3.tgz", + "integrity": "sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/style-loader": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", + "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", + "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", + "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.14", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "terser": "^5.14.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", + "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack": { + "version": "5.75.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz", + "integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.10.0", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.0.1.tgz", + "integrity": "sha512-S3KVAyfwUqr0Mo/ur3NzIp6jnerNpo7GUO6so51mxLi1spqsA17YcMXy0WOIJtBSnj748lthxC6XLbNKh/ZC+A==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.0.1", + "@webpack-cli/info": "^2.0.1", + "@webpack-cli/serve": "^2.0.1", + "colorette": "^2.0.14", + "commander": "^9.4.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } +} diff --git a/NetEvent/Client/JavaScripts/package.json b/NetEvent/Client/JavaScripts/package.json new file mode 100644 index 00000000..148a8e29 --- /dev/null +++ b/NetEvent/Client/JavaScripts/package.json @@ -0,0 +1,24 @@ +{ + "name": "NetEvent", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "build-checkout": "webpack --config webpack-checkout.config.js --output-path ../wwwroot/js/checkout --output-filename checkout.bundle.js --mode=production", + "build-checkout-dev": "webpack --config webpack-checkout.config.js --output-path ../wwwroot/js/checkout --output-filename checkout.bundle.js --mode=development", + "build": "npm run build-checkout", + "build-dev": "npm run build-checkout-dev" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "css-loader": "^6.7.3", + "style-loader": "^3.3.1", + "webpack": "^5.75.0", + "webpack-cli": "^5.0.1" + }, + "dependencies": { + "@adyen/adyen-web": "^5.32.0" + } +} diff --git a/NetEvent/Client/JavaScripts/src/checkout.js b/NetEvent/Client/JavaScripts/src/checkout.js new file mode 100644 index 00000000..50ee74a6 --- /dev/null +++ b/NetEvent/Client/JavaScripts/src/checkout.js @@ -0,0 +1,2 @@ +import AdyenCheckout from '@adyen/adyen-web'; +import '@adyen/adyen-web/dist/adyen.css'; diff --git a/NetEvent/Client/JavaScripts/src/index.js b/NetEvent/Client/JavaScripts/src/index.js new file mode 100644 index 00000000..0459ee5d --- /dev/null +++ b/NetEvent/Client/JavaScripts/src/index.js @@ -0,0 +1 @@ +// empty file required for webpack \ No newline at end of file diff --git a/NetEvent/Client/JavaScripts/webpack-checkout.config.js b/NetEvent/Client/JavaScripts/webpack-checkout.config.js new file mode 100644 index 00000000..843e46dc --- /dev/null +++ b/NetEvent/Client/JavaScripts/webpack-checkout.config.js @@ -0,0 +1,11 @@ +module.exports = { + entry: './src/checkout.js', + module: { + rules: [ + { + test: /\.css$/i, + use: ["style-loader", "css-loader"], + }, + ], + }, +}; \ No newline at end of file diff --git a/NetEvent/Client/NetEvent.Client.csproj b/NetEvent/Client/NetEvent.Client.csproj index 973679a2..1af4f2df 100644 --- a/NetEvent/Client/NetEvent.Client.csproj +++ b/NetEvent/Client/NetEvent.Client.csproj @@ -1,9 +1,6 @@ - + - net7.0 - enable - ..\..\.sonarlint\lan2play_custom.ruleset @@ -28,6 +25,7 @@ + @@ -62,4 +60,10 @@ true + + + + + + diff --git a/NetEvent/Client/Pages/Events/Event.razor b/NetEvent/Client/Pages/Events/Event.razor index 64db28c2..12b2ad88 100644 --- a/NetEvent/Client/Pages/Events/Event.razor +++ b/NetEvent/Client/Pages/Events/Event.razor @@ -87,7 +87,7 @@ } - @Localize["Administration.Events.Event.Tickets.Buy"] + @Localize["Administration.Events.Event.Tickets.Buy"] } diff --git a/NetEvent/Client/Pages/Events/Event.razor.cs b/NetEvent/Client/Pages/Events/Event.razor.cs index d1619bbd..ca374110 100644 --- a/NetEvent/Client/Pages/Events/Event.razor.cs +++ b/NetEvent/Client/Pages/Events/Event.razor.cs @@ -1,5 +1,6 @@ using System.Threading; using System.Threading.Tasks; +using Blazored.LocalStorage; using Microsoft.AspNetCore.Components; using Microsoft.Extensions.Localization; using MudBlazor; @@ -25,6 +26,9 @@ public partial class Event [Inject] private IStringLocalizer Localizer { get; set; } = default!; + [Inject] + private ICartService CartService { get; set; } = default!; + #endregion [Parameter] @@ -56,5 +60,10 @@ private static Color GetStateColor(PublishStateDto state) _ => throw new($"PublishState {state} is not supported!"), }; } + + private async Task BuyTicketAsync(EventTicketTypeDto eventTicketType) + { + //CartService.AddToCart(eventTicketType); + } } } diff --git a/NetEvent/Client/Program.cs b/NetEvent/Client/Program.cs index dbc2b332..5590d57e 100644 --- a/NetEvent/Client/Program.cs +++ b/NetEvent/Client/Program.cs @@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis; using System.Net; using System.Threading.Tasks; +using Blazored.LocalStorage; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.WebAssembly.Authentication; @@ -39,6 +40,8 @@ private static async Task Main(string[] args) builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddSingleton(); builder.Services.AddHttpClient(Constants.BackendApiHttpClientName) @@ -71,6 +74,7 @@ private static async Task Main(string[] args) config.SnackbarConfiguration.SnackbarVariant = Variant.Filled; #pragma warning restore S109 }); + builder.Services.AddBlazoredLocalStorage(); var app = builder.Build(); await app.SetDefaultCultureAsync(); diff --git a/NetEvent/Client/Services/CartService.cs b/NetEvent/Client/Services/CartService.cs new file mode 100644 index 00000000..cda6e806 --- /dev/null +++ b/NetEvent/Client/Services/CartService.cs @@ -0,0 +1,32 @@ +using System.Threading.Tasks; +using Blazored.LocalStorage; +using NetEvent.Shared.Dto; + +namespace NetEvent.Client.Services +{ + public class CartService : ICartService + { + private const string _CartKey = "cart"; + + private readonly ILocalStorageService _LocalStorage; + + public CartService(ILocalStorageService localStorage) + { + _LocalStorage = localStorage; + } + + public async Task LoadCart(string cartId) + { + if (await _LocalStorage.ContainKeyAsync(cartId).ConfigureAwait(false)) + { + return await _LocalStorage.GetItemAsync(_CartKey); + } + + var cart = new CartDto(); + await _LocalStorage.SetItemAsync(_CartKey, cart); + return cart; + } + + //public async Task AddToCart() + } +} diff --git a/NetEvent/Client/Services/ICartService.cs b/NetEvent/Client/Services/ICartService.cs new file mode 100644 index 00000000..704a1e2b --- /dev/null +++ b/NetEvent/Client/Services/ICartService.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; +using NetEvent.Shared.Dto; + +namespace NetEvent.Client.Services +{ + public interface ICartService + { + Task LoadCart(string cartId); + } +} diff --git a/NetEvent/Client/wwwroot/index.html b/NetEvent/Client/wwwroot/index.html index 7cc649be..cec07fbc 100644 --- a/NetEvent/Client/wwwroot/index.html +++ b/NetEvent/Client/wwwroot/index.html @@ -31,6 +31,13 @@ + diff --git a/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj b/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj index d3dd8750..b87d7f1b 100644 --- a/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj +++ b/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj @@ -1,9 +1,6 @@  - net7.0 - enable - false false ..\..\.sonarlint\lan2play_custom.ruleset diff --git a/NetEvent/Server/Data/PaymentManager.cs b/NetEvent/Server/Data/PaymentManager.cs index bd4737cc..eeb68699 100644 --- a/NetEvent/Server/Data/PaymentManager.cs +++ b/NetEvent/Server/Data/PaymentManager.cs @@ -67,6 +67,9 @@ public async Task PayAsync(CartDto cart, ClaimsPr return null; } + await _DbContext.Purchases.AddAsync(purchase).ConfigureAwait(false); + await _DbContext.SaveChangesAsync().ConfigureAwait(false); + var checkoutSessionRequest = new CreateCheckoutSessionRequest { MerchantAccount = merchantAccount.SerializedValue, diff --git a/NetEvent/Server/NetEvent.Server.csproj b/NetEvent/Server/NetEvent.Server.csproj index 1c28ae7b..ea7439a6 100644 --- a/NetEvent/Server/NetEvent.Server.csproj +++ b/NetEvent/Server/NetEvent.Server.csproj @@ -1,8 +1,6 @@ - net7.0 - enable NetEvent.Server-22C6183C-4927-4801-90E6-4AC1E79183B5 ..\..\.sonarlint\lan2play_custom.ruleset diff --git a/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj b/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj index 1ea16ae9..cee851f9 100644 --- a/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj +++ b/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj @@ -1,9 +1,6 @@ - net7.0 - enable - ..\..\.sonarlint\lan2play_custom.ruleset false diff --git a/NetEvent/Shared/NetEvent.Shared.csproj b/NetEvent/Shared/NetEvent.Shared.csproj index 8abf59c0..23e938fc 100644 --- a/NetEvent/Shared/NetEvent.Shared.csproj +++ b/NetEvent/Shared/NetEvent.Shared.csproj @@ -1,9 +1,6 @@ - net7.0 - enable - ..\..\.sonarlint\lan2play_custom.ruleset diff --git a/NetEvent/TestHelper/Fakers.cs b/NetEvent/TestHelper/Fakers.cs index 63de1f57..c2fc30c3 100644 --- a/NetEvent/TestHelper/Fakers.cs +++ b/NetEvent/TestHelper/Fakers.cs @@ -1,5 +1,8 @@ -using System.Diagnostics.CodeAnalysis; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Globalization; +using System.Linq; using Bogus; using NetEvent.Server.Models; using NetEvent.Shared.Dto; diff --git a/NetEvent/TestHelper/NetEvent.TestHelper.csproj b/NetEvent/TestHelper/NetEvent.TestHelper.csproj index a9c4912f..dc6790f5 100644 --- a/NetEvent/TestHelper/NetEvent.TestHelper.csproj +++ b/NetEvent/TestHelper/NetEvent.TestHelper.csproj @@ -1,9 +1,6 @@ - net7.0 - enable - enable ..\..\.sonarlint\lan2play_custom.ruleset From c737b12a88cf414fb618629585b78595b79eda72 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Wed, 1 Feb 2023 22:40:54 +0100 Subject: [PATCH 12/39] : --- .../Components/Administration/SystemSettingControl.razor | 2 +- NetEvent/Client/Extensions/TinyMceConfig.cs | 2 ++ NetEvent/Client/JavaScripts/package-lock.json | 8 +++++++- NetEvent/Client/JavaScripts/package.json | 6 ++---- .../{webpack-checkout.config.js => webpack.config.js} | 8 +++++++- .../Pages/Administration/Events/EventSettings.razor | 4 ++-- 6 files changed, 21 insertions(+), 9 deletions(-) rename NetEvent/Client/JavaScripts/{webpack-checkout.config.js => webpack.config.js} (54%) diff --git a/NetEvent/Client/Components/Administration/SystemSettingControl.razor b/NetEvent/Client/Components/Administration/SystemSettingControl.razor index 2cfd1bb1..4d6d3698 100644 --- a/NetEvent/Client/Components/Administration/SystemSettingControl.razor +++ b/NetEvent/Client/Components/Administration/SystemSettingControl.razor @@ -18,7 +18,7 @@ { - + } diff --git a/NetEvent/Client/Extensions/TinyMceConfig.cs b/NetEvent/Client/Extensions/TinyMceConfig.cs index 1a6d36ca..e9b308be 100644 --- a/NetEvent/Client/Extensions/TinyMceConfig.cs +++ b/NetEvent/Client/Extensions/TinyMceConfig.cs @@ -10,6 +10,8 @@ public static class TinyMceConfig private const int _HeaderHeight = 64; private const int _EditorHeight = 500; + public const string ScriptSrc = "/lib/tinymce/tinymce.min.js"; + /// /// Provide Editor Config for TinyMce /// More Information: https://www.tiny.cloud/docs/tinymce/6/editor-important-options/ diff --git a/NetEvent/Client/JavaScripts/package-lock.json b/NetEvent/Client/JavaScripts/package-lock.json index bb185446..c5cffff1 100644 --- a/NetEvent/Client/JavaScripts/package-lock.json +++ b/NetEvent/Client/JavaScripts/package-lock.json @@ -9,7 +9,8 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@adyen/adyen-web": "^5.32.0" + "@adyen/adyen-web": "^5.32.0", + "tinymce": "^6.3.1" }, "devDependencies": { "css-loader": "^6.7.3", @@ -1428,6 +1429,11 @@ } } }, + "node_modules/tinymce": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-6.3.1.tgz", + "integrity": "sha512-+oCwXuTxAdJXVJ0130OxQz0JDNsqg3deuzgeUo8X5Vb27EzCJgXwO5eWvCxvkxpQo4oiHMVlM4tUIpTUHufHGQ==" + }, "node_modules/update-browserslist-db": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", diff --git a/NetEvent/Client/JavaScripts/package.json b/NetEvent/Client/JavaScripts/package.json index 148a8e29..d14bc4d8 100644 --- a/NetEvent/Client/JavaScripts/package.json +++ b/NetEvent/Client/JavaScripts/package.json @@ -4,10 +4,8 @@ "description": "", "main": "index.js", "scripts": { - "build-checkout": "webpack --config webpack-checkout.config.js --output-path ../wwwroot/js/checkout --output-filename checkout.bundle.js --mode=production", - "build-checkout-dev": "webpack --config webpack-checkout.config.js --output-path ../wwwroot/js/checkout --output-filename checkout.bundle.js --mode=development", - "build": "npm run build-checkout", - "build-dev": "npm run build-checkout-dev" + "build": "webpack --config webpack.config.js --mode=production", + "build-dev": "webpack --config webpack.config.js --mode=development" }, "keywords": [], "author": "", diff --git a/NetEvent/Client/JavaScripts/webpack-checkout.config.js b/NetEvent/Client/JavaScripts/webpack.config.js similarity index 54% rename from NetEvent/Client/JavaScripts/webpack-checkout.config.js rename to NetEvent/Client/JavaScripts/webpack.config.js index 843e46dc..a7e5ee5b 100644 --- a/NetEvent/Client/JavaScripts/webpack-checkout.config.js +++ b/NetEvent/Client/JavaScripts/webpack.config.js @@ -1,5 +1,11 @@ module.exports = { - entry: './src/checkout.js', + entry: { + checkout: './src/checkout.js', + }, + output: { + filename: '[name].js', + path: __dirname + '/../wwwroot/js', + }, module: { rules: [ { diff --git a/NetEvent/Client/Pages/Administration/Events/EventSettings.razor b/NetEvent/Client/Pages/Administration/Events/EventSettings.razor index 9d258599..64e66b51 100644 --- a/NetEvent/Client/Pages/Administration/Events/EventSettings.razor +++ b/NetEvent/Client/Pages/Administration/Events/EventSettings.razor @@ -111,14 +111,14 @@ - + - + From 950652839b744045e4102c5fafb490728ee006b3 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Thu, 2 Feb 2023 21:56:14 +0100 Subject: [PATCH 13/39] Update Payment --- NetEvent/Client/JavaScripts/package-lock.json | 8 +- NetEvent/Client/JavaScripts/src/checkout.js | 47 ++++++++++ .../Pages/Checkout/CheckoutTicket.razor | 33 +++++++ .../Pages/Checkout/CheckoutTicket.razor.cs | 85 +++++++++++++++++++ NetEvent/Client/Pages/Events/Event.razor | 8 +- NetEvent/Client/Pages/Events/Event.razor.cs | 3 + NetEvent/Client/Resources/App.resx | 15 ++-- NetEvent/Client/Services/EventService.cs | 23 +++++ NetEvent/Client/Services/IEventService.cs | 6 ++ NetEvent/Client/wwwroot/index.html | 2 +- NetEvent/Server/Helpers/DtoMapper.cs | 3 + .../Modules/Payment/Endpoints/PostCart.cs | 17 ++-- NetEvent/Shared/Dto/CartEntryDto.cs | 2 +- NetEvent/Shared/Dto/CheckoutSessionDto.cs | 12 +++ 14 files changed, 234 insertions(+), 30 deletions(-) create mode 100644 NetEvent/Client/Pages/Checkout/CheckoutTicket.razor create mode 100644 NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs create mode 100644 NetEvent/Shared/Dto/CheckoutSessionDto.cs diff --git a/NetEvent/Client/JavaScripts/package-lock.json b/NetEvent/Client/JavaScripts/package-lock.json index c5cffff1..bb185446 100644 --- a/NetEvent/Client/JavaScripts/package-lock.json +++ b/NetEvent/Client/JavaScripts/package-lock.json @@ -9,8 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@adyen/adyen-web": "^5.32.0", - "tinymce": "^6.3.1" + "@adyen/adyen-web": "^5.32.0" }, "devDependencies": { "css-loader": "^6.7.3", @@ -1429,11 +1428,6 @@ } } }, - "node_modules/tinymce": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-6.3.1.tgz", - "integrity": "sha512-+oCwXuTxAdJXVJ0130OxQz0JDNsqg3deuzgeUo8X5Vb27EzCJgXwO5eWvCxvkxpQo4oiHMVlM4tUIpTUHufHGQ==" - }, "node_modules/update-browserslist-db": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", diff --git a/NetEvent/Client/JavaScripts/src/checkout.js b/NetEvent/Client/JavaScripts/src/checkout.js index 50ee74a6..fbe34f28 100644 --- a/NetEvent/Client/JavaScripts/src/checkout.js +++ b/NetEvent/Client/JavaScripts/src/checkout.js @@ -1,2 +1,49 @@ import AdyenCheckout from '@adyen/adyen-web'; import '@adyen/adyen-web/dist/adyen.css'; + + +const configuration = { + environment: 'test', // Change to one of the environment values specified in step 4. + //clientKey: 'test_870be2...', // Public key used for client-side authentication: https://docs.adyen.com/development-resources/client-side-authentication + analytics: { + enabled: false // Set to false to not send analytics data to Adyen. + }, + session: { + //id: 'CSD9CAC3...', // Unique identifier for the payment session. + //sessionData: 'Ab02b4c...' // The payment session data. + }, + onPaymentCompleted: (result, component) => { + console.info(result, component); + }, + onError: (error, component) => { + console.error(error.name, error.message, error.stack, component); + }, + // Any payment method specific configuration. Find the configuration specific to each payment method: https://docs.adyen.com/payment-methods + // For example, this is 3D Secure configuration for cards: + paymentMethodsConfiguration: { + card: { + hasHolderName: true, + holderNameRequired: true, + billingAddressRequired: true + } + } +}; + +const jsInterop = jsInterop || {}; + +jsInterop.startPayment = async function (clientKey, sessionId, sessionData) { + configuration.clientKey = clientKey; + configuration.session.id = sessionId; + configuration.session.sessionData = sessionData; + + // Create an instance of AdyenCheckout using the configuration object. + const checkout = await AdyenCheckout(configuration); + // Access the available payment methods for the session. + console.log(checkout.paymentMethodsResponse); // => { paymentMethods: [...], storedPaymentMethods: [...] } + + // Create an instance of the Component and mount it to the container you created. + const cardComponent = checkout.create('card').mount('#payment-container'); + + // TODO Handle RedirectResult + // https://docs.adyen.com/online-payments/web-components#handle-redirect-result +}; \ No newline at end of file diff --git a/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor new file mode 100644 index 00000000..eb594ba3 --- /dev/null +++ b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor @@ -0,0 +1,33 @@ +@page "/checkout/ticket/{ticketType:long}/{amoint:int}" +@using NetEvent.Shared.Dto.Event; + + +@if (CheckoutSession == null) +{ + +
+ + + + + @EventTicketType.Name + + + @EventTicketType.Price @EventTicketType.Currency.ToSymbol() + + + + + TODO: Confirm AGB? + + + + @Localizer["Events.Event.Tickets.BuyNow"] + + +
+} +else +{ +
+} \ No newline at end of file diff --git a/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs new file mode 100644 index 00000000..d0dab38b --- /dev/null +++ b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; +using System.Net.Http; +using System.Net.Http.Json; +using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.AspNetCore.Components.Forms; +using Microsoft.AspNetCore.Components.Routing; +using Microsoft.AspNetCore.Components.Web; +using Microsoft.AspNetCore.Components.Web.Virtualization; +using Microsoft.AspNetCore.Components.WebAssembly.Http; +using Microsoft.JSInterop; +using MudBlazor; +using NetEvent.Client; +using NetEvent.Client.Shared; +using NetEvent.Client.Components; +using NetEvent.Client.Services; +using System.Threading; +using NetEvent.Shared.Dto.Event; +using Microsoft.Extensions.Localization; +using NetEvent.Shared.Dto; +using NetEvent.Shared.Config; + +namespace NetEvent.Client.Pages.Checkout +{ + public partial class CheckoutTicket + { + #region Injects + + [Inject] + private IEventService EventService { get; set; } = default!; + + [Inject] + private ISystemSettingsDataService SettingsService { get; set; } = default!; + + [Inject] + private IStringLocalizer Localizer { get; set; } = default!; + + [Inject] + private IJSRuntime JsRuntime { get; set; } = default!; + + #endregion + + #region Parameters + + [Parameter] + public long TicketType { get; set; } + + [Parameter] + public int? Amount { get; set; } + + #endregion + + private EventTicketTypeDto? EventTicketType; + private CheckoutSessionDto? CheckoutSession; + + protected override async Task OnInitializedAsync() + { + var cts = new CancellationTokenSource(); + Amount ??= 1; + + EventTicketType = await EventService.GetEventTicketTypeAsync(TicketType, cts.Token).ConfigureAwait(false); + } + + private async Task BuyTicketAsync() + { + if (EventTicketType?.Id == null || Amount == null) + { + return; + } + + var cts = new CancellationTokenSource(); + var result = await EventService.BuyTicketAsync(EventTicketType.Id.Value, Amount.Value, cts.Token).ConfigureAwait(false); + if (result.Successful && result.ResultData != null) + { + var clientKey = SettingsService.GetSystemSettingAsync(SystemSettingGroup.PaymentData, SystemSettings.PaymentData.AdyenClientKey, cts.Token); + + CheckoutSession = result.ResultData; + await JsRuntime.InvokeVoidAsync("jsInterop.startPayment", clientKey, CheckoutSession.Id, CheckoutSession.SessionData).ConfigureAwait(false); + } + } + } +} diff --git a/NetEvent/Client/Pages/Events/Event.razor b/NetEvent/Client/Pages/Events/Event.razor index 12b2ad88..00f99c35 100644 --- a/NetEvent/Client/Pages/Events/Event.razor +++ b/NetEvent/Client/Pages/Events/Event.razor @@ -73,21 +73,21 @@ - TODO remainingTickets / @ticketType.AvailableTickets @Localize["Administration.Events.Event.Tickets.Available"] + @Localize["Events.Event.Tickets.Available", "TODO remainingTickets / " + @ticketType.AvailableTickets] @if (ticketType.SellStartDate >= DateTime.Now) { - @Localize["Administration.Events.Event.Tickets.AvailableFrom", ticketType.SellStartDate] + @Localize["Events.Event.Tickets.AvailableFrom", ticketType.SellStartDate] } else { - @Localize["Administration.Events.Event.Tickets.AvailableUntil", ticketType.SellEndDate] + @Localize["Events.Event.Tickets.AvailableUntil", ticketType.SellEndDate] } - @Localize["Administration.Events.Event.Tickets.Buy"] + @Localize["Events.Event.Tickets.Buy"] } diff --git a/NetEvent/Client/Pages/Events/Event.razor.cs b/NetEvent/Client/Pages/Events/Event.razor.cs index ca374110..5ed3b3a1 100644 --- a/NetEvent/Client/Pages/Events/Event.razor.cs +++ b/NetEvent/Client/Pages/Events/Event.razor.cs @@ -63,6 +63,9 @@ private static Color GetStateColor(PublishStateDto state) private async Task BuyTicketAsync(EventTicketTypeDto eventTicketType) { + // /checkout/ticket/{tickettypeid}/{count} + NavigationManager.NavigateTo($"checkout/ticket/{eventTicketType.Id}"); + //CartService.AddToCart(eventTicketType); } } diff --git a/NetEvent/Client/Resources/App.resx b/NetEvent/Client/Resources/App.resx index ee11d23e..d87919b1 100644 --- a/NetEvent/Client/Resources/App.resx +++ b/NetEvent/Client/Resources/App.resx @@ -750,16 +750,19 @@ Save - - available - - + Buy - + Available from {0} - + Available until {0} + + Buy now + + + available {0} + \ No newline at end of file diff --git a/NetEvent/Client/Services/EventService.cs b/NetEvent/Client/Services/EventService.cs index 971ed0fa..526a8128 100644 --- a/NetEvent/Client/Services/EventService.cs +++ b/NetEvent/Client/Services/EventService.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; +using NetEvent.Shared.Dto; using NetEvent.Shared.Dto.Event; namespace NetEvent.Client.Services @@ -240,5 +241,27 @@ public async Task DeleteEventTicketTypeAsync(long id, Cancellatio } } + public async Task> BuyTicketAsync(long id, int amount, CancellationToken cancellationToken) + { + try + { + var ticketCart = new CartDto { CartEntries = new[] { new CartEntryDto { TicketId = id, Amount = amount } } }; + + var client = _HttpClientFactory.CreateClient(Constants.BackendApiHttpClientName); + + var response = await client.PostAsJsonAsync($"api/payment/buy", ticketCart, cancellationToken); + response.EnsureSuccessStatusCode(); + + var sessionResponse = await response.Content.ReadFromJsonAsync().ConfigureAwait(false); + + return ServiceResult.Success(sessionResponse, "EventService.AddAsync.Success"); + } + catch (Exception ex) + { + _Logger.LogError(ex, "Unable to create eventTicketType in backend."); + } + + return ServiceResult.Error("EventService.AddAsync.Error"); + } } } diff --git a/NetEvent/Client/Services/IEventService.cs b/NetEvent/Client/Services/IEventService.cs index f2c2c295..8773ee24 100644 --- a/NetEvent/Client/Services/IEventService.cs +++ b/NetEvent/Client/Services/IEventService.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using NetEvent.Shared.Dto; using NetEvent.Shared.Dto.Event; namespace NetEvent.Client.Services @@ -20,8 +21,13 @@ public interface IEventService Task UpdateEventAsync(EventDto eventDto, CancellationToken cancellationToken); Task CreateEventAsync(EventDto eventDto, CancellationToken cancellationToken); + Task GetEventTicketTypeAsync(long id, CancellationToken cancellationToken); + Task UpdateEventTicketTypeAsync(EventTicketTypeDto eventTicketTypeDto, CancellationToken cancellationToken); + Task CreateEventTicketTypeAsync(long eventId, EventTicketTypeDto eventTicketTypeDto, CancellationToken cancellationToken); + + Task> BuyTicketAsync(long id, int amount, CancellationToken cancellationToken); } } diff --git a/NetEvent/Client/wwwroot/index.html b/NetEvent/Client/wwwroot/index.html index cec07fbc..418d654c 100644 --- a/NetEvent/Client/wwwroot/index.html +++ b/NetEvent/Client/wwwroot/index.html @@ -34,7 +34,7 @@ diff --git a/NetEvent/Server/Helpers/DtoMapper.cs b/NetEvent/Server/Helpers/DtoMapper.cs index 7748e334..32d07da5 100644 --- a/NetEvent/Server/Helpers/DtoMapper.cs +++ b/NetEvent/Server/Helpers/DtoMapper.cs @@ -1,4 +1,5 @@ using System.Security.Claims; +using Adyen.Model.Checkout; using NetEvent.Server.Models; using NetEvent.Shared.Dto; using NetEvent.Shared.Dto.Administration; @@ -62,5 +63,7 @@ public static partial class DtoMapper public static partial VenueDto ToVenueDto(this Venue venue); public static partial Venue ToVenue(this VenueDto venue); + + public static partial CheckoutSessionDto ToCheckoutSessionDto(this CreateCheckoutSessionResponse createCheckoutSessionResponse); } } diff --git a/NetEvent/Server/Modules/Payment/Endpoints/PostCart.cs b/NetEvent/Server/Modules/Payment/Endpoints/PostCart.cs index 1a48f880..ace5aa8d 100644 --- a/NetEvent/Server/Modules/Payment/Endpoints/PostCart.cs +++ b/NetEvent/Server/Modules/Payment/Endpoints/PostCart.cs @@ -24,15 +24,10 @@ public Handler(IPaymentManager paymentManager) public async Task Handle(Request request, CancellationToken cancellationToken) { - return new Response(await _PaymentManager.PayAsync(request.CartDto, request.User)); - //var newVenue = request.Venue.ToVenue(); - //var result = await _PaymentManager.CreateVenueAsync(newVenue).ConfigureAwait(false); - //if (!result.Succeeded || newVenue.Id == null) - //{ - // return new Response(ReturnType.Error, string.Join(Environment.NewLine, result.Errors)); - //} - - //return new Response(newVenue.Id!.Value); + var sessionResponse = await _PaymentManager.PayAsync(request.CartDto, request.User); + var result = sessionResponse.ToCheckoutSessionDto(); + + return new Response(result); } } @@ -49,9 +44,9 @@ public Request(CartDto cartDto, ClaimsPrincipal user) public ClaimsPrincipal User { get; } } - public sealed class Response : ResponseBase + public sealed class Response : ResponseBase { - public Response(CreateCheckoutSessionResponse response) : base(response) + public Response(CheckoutSessionDto response) : base(response) { } diff --git a/NetEvent/Shared/Dto/CartEntryDto.cs b/NetEvent/Shared/Dto/CartEntryDto.cs index a99e9dc4..303c3ac3 100644 --- a/NetEvent/Shared/Dto/CartEntryDto.cs +++ b/NetEvent/Shared/Dto/CartEntryDto.cs @@ -9,5 +9,5 @@ public class CartEntryDto public int Amount { get; set; } [JsonPropertyName("ticketId")] - public int? TicketId { get; set; } + public long? TicketId { get; set; } } diff --git a/NetEvent/Shared/Dto/CheckoutSessionDto.cs b/NetEvent/Shared/Dto/CheckoutSessionDto.cs new file mode 100644 index 00000000..9c0e4126 --- /dev/null +++ b/NetEvent/Shared/Dto/CheckoutSessionDto.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; + +namespace NetEvent.Shared.Dto; + +public class CheckoutSessionDto +{ + [JsonPropertyName("id")] + public string? Id { get; set; } + + [JsonPropertyName("sessionData")] + public string? SessionData { get; set; } +} From fb07143fd08bf85a2bf54cce96499d91b82e3bb1 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Thu, 2 Feb 2023 21:59:10 +0100 Subject: [PATCH 14/39] Update Packages --- NetEvent/Client/NetEvent.Client.csproj | 2 +- NetEvent/Server/NetEvent.Server.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NetEvent/Client/NetEvent.Client.csproj b/NetEvent/Client/NetEvent.Client.csproj index 1af4f2df..ab5dffc3 100644 --- a/NetEvent/Client/NetEvent.Client.csproj +++ b/NetEvent/Client/NetEvent.Client.csproj @@ -34,7 +34,7 @@ - + diff --git a/NetEvent/Server/NetEvent.Server.csproj b/NetEvent/Server/NetEvent.Server.csproj index ea7439a6..b56c4646 100644 --- a/NetEvent/Server/NetEvent.Server.csproj +++ b/NetEvent/Server/NetEvent.Server.csproj @@ -17,7 +17,7 @@ - + From d349cc9d90fc3d13e34223f5a87a77baa4d3af3f Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Thu, 2 Feb 2023 22:51:23 +0100 Subject: [PATCH 15/39] Move Directory.Build.Props --- NetEvent.sln | 2 +- Directory.Build.props => NetEvent/Directory.Build.props | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename Directory.Build.props => NetEvent/Directory.Build.props (100%) diff --git a/NetEvent.sln b/NetEvent.sln index b785f25f..6a348250 100644 --- a/NetEvent.sln +++ b/NetEvent.sln @@ -14,7 +14,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .editorconfig = .editorconfig .gitignore = .gitignore CodeCoverage.runsettings = CodeCoverage.runsettings - directory.build.props = directory.build.props + NetEvent\Directory.Build.props = NetEvent\Directory.Build.props Makefile = Makefile NetEvent\TestHelper\NetEvent.TestHelper.csproj = NetEvent\TestHelper\NetEvent.TestHelper.csproj README.md = README.md diff --git a/Directory.Build.props b/NetEvent/Directory.Build.props similarity index 100% rename from Directory.Build.props rename to NetEvent/Directory.Build.props From 1b7665d45df9dc872632f0ba8d7762e3d12c7654 Mon Sep 17 00:00:00 2001 From: Alexander Volz Date: Thu, 2 Feb 2023 23:09:09 +0100 Subject: [PATCH 16/39] add npm to dockerfile --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index de4be40c..d7ecbe30 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,10 +14,11 @@ ENV NETEVENTNETVER=$NETEVENTNETVER WORKDIR / RUN apt-get update -qqy && DEBIAN_FRONTEND=noninteractive apt-get install -y \ wget bash apt-transport-https +RUN wget -q -O - https://deb.nodesource.com/setup_current.x | bash - RUN wget https://packages.microsoft.com/config/debian/11/packages-microsoft-prod.deb -O packages-microsoft-prod.deb RUN dpkg -i packages-microsoft-prod.deb RUN rm packages-microsoft-prod.deb -RUN apt-get update -qqy && apt-get install -y dotnet-sdk-7.0 python3 python3-pip wget +RUN apt-get update -qqy && apt-get install -y dotnet-sdk-7.0 python3 python3-pip nodejs RUN pip install lastversion RUN eval apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* From 29b83dbce577779d0efc4790ee721abc8f6cf62c Mon Sep 17 00:00:00 2001 From: Alexander Volz Date: Thu, 2 Feb 2023 23:18:29 +0100 Subject: [PATCH 17/39] fixed local build (default version arg) and disabled pulling of the old docker image while building, optimized image size --- .github/workflows/test_and_build.yml | 4 ++-- Dockerfile | 17 +++++++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 2562289e..156bc03c 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -111,8 +111,8 @@ jobs: submodules: recursive - name: Set up QEMU uses: docker/setup-qemu-action@v2.1.0 - - name: Pull Latest Linux Base Image - run: docker pull lan2play/netevent + # - name: Pull Latest Linux Base Image + # run: docker pull lan2play/netevent - name: set Version if: ${{ (startsWith(github.ref, 'refs/tags/v')) }} run: echo "NETEVENTNETVER=$(echo ${GITHUB_REF} | sed 's|refs/heads/||g' | sed 's|refs/tags/v||g' | sed 's|-beta||g' )" >> $GITHUB_ENV diff --git a/Dockerfile b/Dockerfile index d7ecbe30..7198a244 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ LABEL stage=builder LABEL org.opencontainers.image.authors="Alexander@volzit.de" #args -ARG NETEVENTNETVER +ARG NETEVENTNETVER=0.0.1 ENV NETEVENTNETVER=$NETEVENTNETVER #install prereqs @@ -62,13 +62,14 @@ RUN chmod +x /usr/local/bin/start-container RUN chmod +x /usr/local/bin/wait-for.sh #install prereqs -RUN apt-get update -qqy && DEBIAN_FRONTEND=noninteractive apt-get install -y \ - wget apt-transport-https -RUN wget https://packages.microsoft.com/config/debian/11/packages-microsoft-prod.deb -O packages-microsoft-prod.deb -RUN dpkg -i packages-microsoft-prod.deb -RUN rm packages-microsoft-prod.deb -RUN apt-get update -qqy && apt-get install -y aspnetcore-runtime-7.0 netcat curl -RUN eval apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* +RUN apt-get update -qqy && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y wget apt-transport-https && \ + wget https://packages.microsoft.com/config/debian/11/packages-microsoft-prod.deb -O packages-microsoft-prod.deb && \ + dpkg -i packages-microsoft-prod.deb && \ + rm packages-microsoft-prod.deb && \ + apt-get update -qqy && \ + apt-get install -y aspnetcore-runtime-7.0 netcat curl && \ + eval apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* #copy NetEvent files WORKDIR /NetEvent From 0c704e93b97d271a7192c2bcd0f01d37e0f9032d Mon Sep 17 00:00:00 2001 From: Alexander Volz Date: Thu, 2 Feb 2023 23:23:37 +0100 Subject: [PATCH 18/39] remove bad things :D --- docker/start-container | 2 -- 1 file changed, 2 deletions(-) diff --git a/docker/start-container b/docker/start-container index 1a39ef4f..c4145477 100644 --- a/docker/start-container +++ b/docker/start-container @@ -3,7 +3,6 @@ if [[ "$DBProvider" = "psql" ]] then export DBConnection="Host=$DBServer;Port=$DBPort;Username=$DBUser;Password=$DBPassword;Database=$DBName" - echo "DBConnection string: $DBConnection" # Database Wait check echo "---------------" echo "WAITING FOR $DBServer:$DBPort..." @@ -12,6 +11,5 @@ fi if [[ "$DBProvider" = "sqlite" ]] then export DBConnection="Data Source=$DBName" - echo "DBConnection string: $DBConnection" /NetEvent/NetEvent.Server fi \ No newline at end of file From 9439268a2e8742e9c91a01ffb323681165cc4286 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Sat, 4 Feb 2023 00:26:44 +0100 Subject: [PATCH 19/39] Start add Checkout --- .../SystemSettingGroupTab.razor | 18 +++++ .../SystemSettingGroupTab.razor.cs | 49 ++++++++++++ NetEvent/Client/JavaScripts/src/checkout.js | 4 +- NetEvent/Client/JavaScripts/webpack.config.js | 1 + .../Pages/Administration/Settings.razor | 21 +----- .../Pages/Administration/Settings.razor.cs | 30 -------- .../Pages/Checkout/CheckoutTicket.razor | 20 ++--- .../Pages/Checkout/CheckoutTicket.razor.cs | 5 +- NetEvent/Client/Resources/App.resx | 21 ++++++ NetEvent/Client/wwwroot/index.html | 6 +- NetEvent/Server/Data/IPaymentManager.cs | 3 + NetEvent/Server/Data/PaymentManager.cs | 36 ++++++++- NetEvent/Server/Helpers/DtoMapper.cs | 2 + .../20230126222513_AddTickets.Designer.cs | 6 +- .../Psql/20230126222513_AddTickets.cs | 12 +-- .../PsqlApplicationDbContextModelSnapshot.cs | 6 +- .../20230126222503_AddTickets.Designer.cs | 6 +- .../Sqlite/20230126222503_AddTickets.cs | 12 +-- ...SqliteApplicationDbContextModelSnapshot.cs | 6 +- .../Modules/Events/Endpoints/GetEvent.cs | 2 +- .../Modules/Payment/Endpoints/DeleteVenue.cs | 53 ------------- .../Payment/Endpoints/GetPaymentMethods.cs | 57 ++++++++++++++ .../Modules/Payment/Endpoints/GetVenue.cs | 74 ------------------- .../Modules/Payment/Endpoints/GetVenues.cs | 47 ------------ .../Modules/Payment/Endpoints/PutVenue.cs | 62 ---------------- .../Server/Modules/Payment/PaymentModule.cs | 1 + NetEvent/Shared/Config/SystemSettings.cs | 6 +- NetEvent/Shared/Dto/PaymentMethodDto.cs | 12 +++ 28 files changed, 246 insertions(+), 332 deletions(-) create mode 100644 NetEvent/Client/Components/Administration/SystemSettingGroupTab.razor create mode 100644 NetEvent/Client/Components/Administration/SystemSettingGroupTab.razor.cs delete mode 100644 NetEvent/Server/Modules/Payment/Endpoints/DeleteVenue.cs create mode 100644 NetEvent/Server/Modules/Payment/Endpoints/GetPaymentMethods.cs delete mode 100644 NetEvent/Server/Modules/Payment/Endpoints/GetVenue.cs delete mode 100644 NetEvent/Server/Modules/Payment/Endpoints/GetVenues.cs delete mode 100644 NetEvent/Server/Modules/Payment/Endpoints/PutVenue.cs create mode 100644 NetEvent/Shared/Dto/PaymentMethodDto.cs diff --git a/NetEvent/Client/Components/Administration/SystemSettingGroupTab.razor b/NetEvent/Client/Components/Administration/SystemSettingGroupTab.razor new file mode 100644 index 00000000..5fa45796 --- /dev/null +++ b/NetEvent/Client/Components/Administration/SystemSettingGroupTab.razor @@ -0,0 +1,18 @@ + + @if (_Loading) + { +
@Localizer["Administration.Settings.LoadingData"]
+ } + else + { + + @foreach (var systemSetting in SettingsGroup.Settings) + { + + + + } + + } + +
\ No newline at end of file diff --git a/NetEvent/Client/Components/Administration/SystemSettingGroupTab.razor.cs b/NetEvent/Client/Components/Administration/SystemSettingGroupTab.razor.cs new file mode 100644 index 00000000..12416967 --- /dev/null +++ b/NetEvent/Client/Components/Administration/SystemSettingGroupTab.razor.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.Localization; +using NetEvent.Client.Services; +using NetEvent.Shared.Config; +using NetEvent.Shared.Dto; + +namespace NetEvent.Client.Components.Administration +{ + public partial class SystemSettingGroupTab + { + #region Injects + + [Inject] + private IStringLocalizer Localizer { get; set; } = default!; + + [Inject] + private ISystemSettingsDataService SystemSettingsDataService { get; set; } = default!; + + #endregion + + #region Parameters + + [Parameter] + public ISettingsGroup SettingsGroup { get; set; } = default!; + + #endregion + + private IList _Data = new List(); + private bool _Loading = true; + + protected override async Task OnInitializedAsync() + { + var cts = new CancellationTokenSource(); + _Data = await SystemSettingsDataService.GetSystemSettingsAsync(SettingsGroup.SettingGroup, cts.Token); + _Loading = false; + } + + private SystemSettingValueDto? GetValue(string key) + { + return _Data.FirstOrDefault(x => x.Key.Equals(key, StringComparison.Ordinal)) + ?? new SystemSettingValueDto(key, string.Empty); + } + } +} diff --git a/NetEvent/Client/JavaScripts/src/checkout.js b/NetEvent/Client/JavaScripts/src/checkout.js index fbe34f28..d005f8d4 100644 --- a/NetEvent/Client/JavaScripts/src/checkout.js +++ b/NetEvent/Client/JavaScripts/src/checkout.js @@ -29,9 +29,7 @@ const configuration = { } }; -const jsInterop = jsInterop || {}; - -jsInterop.startPayment = async function (clientKey, sessionId, sessionData) { +export async function startPaymentAsync(clientKey, sessionId, sessionData) { configuration.clientKey = clientKey; configuration.session.id = sessionId; configuration.session.sessionData = sessionData; diff --git a/NetEvent/Client/JavaScripts/webpack.config.js b/NetEvent/Client/JavaScripts/webpack.config.js index a7e5ee5b..910f1e0f 100644 --- a/NetEvent/Client/JavaScripts/webpack.config.js +++ b/NetEvent/Client/JavaScripts/webpack.config.js @@ -4,6 +4,7 @@ module.exports = { }, output: { filename: '[name].js', + library: 'checkout', path: __dirname + '/../wwwroot/js', }, module: { diff --git a/NetEvent/Client/Pages/Administration/Settings.razor b/NetEvent/Client/Pages/Administration/Settings.razor index c589d113..b4fd2c04 100644 --- a/NetEvent/Client/Pages/Administration/Settings.razor +++ b/NetEvent/Client/Pages/Administration/Settings.razor @@ -1,6 +1,5 @@ @page "/administration/settings" @attribute [Authorize(Policy = "Admin.System.*")] -@inject Microsoft.Extensions.Localization.IStringLocalizer Localize @using Microsoft.AspNetCore.Authorization @using NetEvent.Client.Components.Administration @@ -10,27 +9,11 @@ - @foreach (var settingsGroup in _SystemSettings.SettingsGroups) { - - @if (_Loading) - { -
@Localize["Administration.Settings.LoadingData"]
- } - else - { - - @foreach (var systemSetting in settingsGroup.Settings) - { - - - - } - - } -
+ } +
\ No newline at end of file diff --git a/NetEvent/Client/Pages/Administration/Settings.razor.cs b/NetEvent/Client/Pages/Administration/Settings.razor.cs index 4dbc49b7..6799f305 100644 --- a/NetEvent/Client/Pages/Administration/Settings.razor.cs +++ b/NetEvent/Client/Pages/Administration/Settings.razor.cs @@ -12,36 +12,6 @@ namespace NetEvent.Client.Pages.Administration { public partial class Settings { - #region Injects - - [Inject] - private ISystemSettingsDataService SystemSettingsDataService { get; set; } = default!; - - #endregion - private readonly SystemSettings _SystemSettings = SystemSettings.Instance; - private bool _Loading = true; - private IList _OrganizationData = new List(); - private IList _StyleData = new List(); - private IList _AuthenticationData = new List(); - - protected override async Task OnInitializedAsync() - { - var cts = new CancellationTokenSource(); - - _OrganizationData = await SystemSettingsDataService.GetSystemSettingsAsync(SystemSettingGroup.OrganizationData, cts.Token); - _StyleData = await SystemSettingsDataService.GetSystemSettingsAsync(SystemSettingGroup.StyleData, cts.Token); - _AuthenticationData = await SystemSettingsDataService.GetSystemSettingsAsync(SystemSettingGroup.AuthenticationData, cts.Token); - - _Loading = false; - } - - private SystemSettingValueDto? GetValue(string key) - { - return _OrganizationData.FirstOrDefault(x => x.Key.Equals(key, StringComparison.Ordinal)) - ?? _StyleData.FirstOrDefault(x => x.Key.Equals(key, StringComparison.Ordinal)) - ?? _AuthenticationData.FirstOrDefault(x => x.Key.Equals(key, StringComparison.Ordinal)) - ?? new SystemSettingValueDto(key, string.Empty); - } } } diff --git a/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor index eb594ba3..4c54f8fe 100644 --- a/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor +++ b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor @@ -1,15 +1,19 @@ -@page "/checkout/ticket/{ticketType:long}/{amoint:int}" +@page "/checkout/ticket/{ticketType:long}" +@page "/checkout/ticket/{ticketType:long}/{amount:int}" @using NetEvent.Shared.Dto.Event; - -@if (CheckoutSession == null) +@if (EventTicketType == null) +{ + +} +else { -
+ c @EventTicketType.Name @@ -22,12 +26,10 @@ - @Localizer["Events.Event.Tickets.BuyNow"] + @Localizer["Events.Event.Tickets.BuyNow"]
} -else -{ -
-} \ No newline at end of file + +
diff --git a/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs index d0dab38b..2c0a61bd 100644 --- a/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs +++ b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs @@ -62,6 +62,7 @@ protected override async Task OnInitializedAsync() Amount ??= 1; EventTicketType = await EventService.GetEventTicketTypeAsync(TicketType, cts.Token).ConfigureAwait(false); + // TODO Load PaymentMethods via new IPaymentService } private async Task BuyTicketAsync() @@ -75,10 +76,10 @@ private async Task BuyTicketAsync() var result = await EventService.BuyTicketAsync(EventTicketType.Id.Value, Amount.Value, cts.Token).ConfigureAwait(false); if (result.Successful && result.ResultData != null) { - var clientKey = SettingsService.GetSystemSettingAsync(SystemSettingGroup.PaymentData, SystemSettings.PaymentData.AdyenClientKey, cts.Token); + var clientKey = await SettingsService.GetSystemSettingAsync(SystemSettingGroup.PaymentData, SystemSettings.PaymentData.AdyenClientKey, cts.Token).ConfigureAwait(false); CheckoutSession = result.ResultData; - await JsRuntime.InvokeVoidAsync("jsInterop.startPayment", clientKey, CheckoutSession.Id, CheckoutSession.SessionData).ConfigureAwait(false); + await JsRuntime.InvokeVoidAsync("checkout.startPaymentAsync", clientKey?.Value, CheckoutSession.Id, CheckoutSession.SessionData).ConfigureAwait(false); } } } diff --git a/NetEvent/Client/Resources/App.resx b/NetEvent/Client/Resources/App.resx index d87919b1..a04b0cec 100644 --- a/NetEvent/Client/Resources/App.resx +++ b/NetEvent/Client/Resources/App.resx @@ -765,4 +765,25 @@ available {0} + + Payment + + + https://docs.adyen.com/development-resources/api-credentials#generate-api-key + + + Adyen Api Key + + + https://docs.adyen.com/development-resources/client-side-authentication#get-your-client-key + + + Adyen Client Key + + + https://ca-test.adyen.com/ca/ca/accounts/show.shtml?accountTypeCode=MerchantAccount + + + Adyen Merchant Account + \ No newline at end of file diff --git a/NetEvent/Client/wwwroot/index.html b/NetEvent/Client/wwwroot/index.html index 418d654c..bc040a91 100644 --- a/NetEvent/Client/wwwroot/index.html +++ b/NetEvent/Client/wwwroot/index.html @@ -30,14 +30,14 @@ - - + diff --git a/NetEvent/Server/Data/IPaymentManager.cs b/NetEvent/Server/Data/IPaymentManager.cs index 1609a713..77f805e5 100644 --- a/NetEvent/Server/Data/IPaymentManager.cs +++ b/NetEvent/Server/Data/IPaymentManager.cs @@ -2,11 +2,14 @@ using System.Threading.Tasks; using Adyen.Model.Checkout; using NetEvent.Shared.Dto; +using NetEvent.Shared.Dto.Event; namespace NetEvent.Server.Data { public interface IPaymentManager { + Task GetPaymentMethodsAsync(long amount, CurrencyDto currency); + Task PayAsync(CartDto cart, ClaimsPrincipal claimsPrincipal); } } diff --git a/NetEvent/Server/Data/PaymentManager.cs b/NetEvent/Server/Data/PaymentManager.cs index eeb68699..eb020678 100644 --- a/NetEvent/Server/Data/PaymentManager.cs +++ b/NetEvent/Server/Data/PaymentManager.cs @@ -34,6 +34,39 @@ public PaymentManager(ApplicationDbContext dbContext, NetEventUserManager userMa _Logger = logger; } + public async Task GetPaymentMethodsAsync(long amount, CurrencyDto currency) + { + var merchantAccount = await _DbContext.SystemSettingValues.FindAsync(SystemSettings.PaymentData.AdyenMerchantAccount).ConfigureAwait(false); + var apiKey = await _DbContext.SystemSettingValues.FindAsync(SystemSettings.PaymentData.AdyenApiKey).ConfigureAwait(false); + + if (string.IsNullOrEmpty(merchantAccount?.SerializedValue)) + { + // TODO Error + return null; + } + + if (string.IsNullOrEmpty(apiKey?.SerializedValue)) + { + // TODO Error + return null; + } + + var client = new Adyen.Client(apiKey.SerializedValue, Adyen.Model.Enum.Environment.Test); + var checkout = new Checkout(client); + + var paymentMethodsRequest = new PaymentMethodsRequest() + { + MerchantAccount = merchantAccount.SerializedValue, + CountryCode = new RegionInfo(CultureInfo.CurrentUICulture.LCID).TwoLetterISORegionName, + ShopperLocale = CultureInfo.CurrentUICulture.Name, + Amount = new Amount(currency.To3DigitIso(), amount), + Channel = PaymentMethodsRequest.ChannelEnum.Web + }; + + var paymentMethodsResponse = checkout.PaymentMethods(paymentMethodsRequest); + return paymentMethodsResponse; + } + public async Task PayAsync(CartDto cart, ClaimsPrincipal claimsPrincipal) { var paymentId = Guid.NewGuid(); @@ -53,7 +86,6 @@ public async Task PayAsync(CartDto cart, ClaimsPr return null; } - var purchase = await CreatePurchaseAsync(cart, claimsPrincipal).ConfigureAwait(false); if (purchase == null) @@ -76,7 +108,7 @@ public async Task PayAsync(CartDto cart, ClaimsPr Reference = paymentId.ToString(), ReturnUrl = "https://your-company.com/checkout?shopperOrder=12xy..", // TODO Checkout Seite mit Polling/Events/... Amount = new Amount(currencyGroup.First().Key.ToCurrencyDto().To3DigitIso(), purchase.Price), - CountryCode = CultureInfo.CurrentCulture.ToString(), + CountryCode = new RegionInfo(CultureInfo.CurrentUICulture.LCID).TwoLetterISORegionName, }; var client = new Adyen.Client(apiKey.SerializedValue, Adyen.Model.Enum.Environment.Test); var checkout = new Checkout(client); diff --git a/NetEvent/Server/Helpers/DtoMapper.cs b/NetEvent/Server/Helpers/DtoMapper.cs index 32d07da5..776f3d90 100644 --- a/NetEvent/Server/Helpers/DtoMapper.cs +++ b/NetEvent/Server/Helpers/DtoMapper.cs @@ -65,5 +65,7 @@ public static partial class DtoMapper public static partial Venue ToVenue(this VenueDto venue); public static partial CheckoutSessionDto ToCheckoutSessionDto(this CreateCheckoutSessionResponse createCheckoutSessionResponse); + + public static partial PaymentMethodDto ToPaymentMethodDto(this PaymentMethod paymentMethods); } } diff --git a/NetEvent/Server/Migrations/Psql/20230126222513_AddTickets.Designer.cs b/NetEvent/Server/Migrations/Psql/20230126222513_AddTickets.Designer.cs index fc091a2b..4f8f9011 100644 --- a/NetEvent/Server/Migrations/Psql/20230126222513_AddTickets.Designer.cs +++ b/NetEvent/Server/Migrations/Psql/20230126222513_AddTickets.Designer.cs @@ -637,17 +637,17 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) }, new { - Key = "AdyenApiKey ", + Key = "AdyenApiKey", SerializedValue = "" }, new { - Key = "AdyenClientKey ", + Key = "AdyenClientKey", SerializedValue = "" }, new { - Key = "AdyenMerchantAccount ", + Key = "AdyenMerchantAccount", SerializedValue = "" }); }); diff --git a/NetEvent/Server/Migrations/Psql/20230126222513_AddTickets.cs b/NetEvent/Server/Migrations/Psql/20230126222513_AddTickets.cs index cf405d2e..d5adc746 100644 --- a/NetEvent/Server/Migrations/Psql/20230126222513_AddTickets.cs +++ b/NetEvent/Server/Migrations/Psql/20230126222513_AddTickets.cs @@ -64,9 +64,9 @@ protected override void Up(MigrationBuilder migrationBuilder) columns: new[] { "Key", "SerializedValue" }, values: new object[,] { - { "AdyenApiKey ", "" }, - { "AdyenClientKey ", "" }, - { "AdyenMerchantAccount ", "" } + { "AdyenApiKey", "" }, + { "AdyenClientKey", "" }, + { "AdyenMerchantAccount", "" } }); migrationBuilder.UpdateData( @@ -104,17 +104,17 @@ protected override void Down(MigrationBuilder migrationBuilder) migrationBuilder.DeleteData( table: "SystemSettings", keyColumn: "Key", - keyValue: "AdyenApiKey "); + keyValue: "AdyenApiKey"); migrationBuilder.DeleteData( table: "SystemSettings", keyColumn: "Key", - keyValue: "AdyenClientKey "); + keyValue: "AdyenClientKey"); migrationBuilder.DeleteData( table: "SystemSettings", keyColumn: "Key", - keyValue: "AdyenMerchantAccount "); + keyValue: "AdyenMerchantAccount"); migrationBuilder.UpdateData( table: "User", diff --git a/NetEvent/Server/Migrations/Psql/PsqlApplicationDbContextModelSnapshot.cs b/NetEvent/Server/Migrations/Psql/PsqlApplicationDbContextModelSnapshot.cs index 2d8f1ba9..01f919ff 100644 --- a/NetEvent/Server/Migrations/Psql/PsqlApplicationDbContextModelSnapshot.cs +++ b/NetEvent/Server/Migrations/Psql/PsqlApplicationDbContextModelSnapshot.cs @@ -634,17 +634,17 @@ protected override void BuildModel(ModelBuilder modelBuilder) }, new { - Key = "AdyenApiKey ", + Key = "AdyenApiKey", SerializedValue = "" }, new { - Key = "AdyenClientKey ", + Key = "AdyenClientKey", SerializedValue = "" }, new { - Key = "AdyenMerchantAccount ", + Key = "AdyenMerchantAccount", SerializedValue = "" }); }); diff --git a/NetEvent/Server/Migrations/Sqlite/20230126222503_AddTickets.Designer.cs b/NetEvent/Server/Migrations/Sqlite/20230126222503_AddTickets.Designer.cs index 50d5a723..8e2eaae4 100644 --- a/NetEvent/Server/Migrations/Sqlite/20230126222503_AddTickets.Designer.cs +++ b/NetEvent/Server/Migrations/Sqlite/20230126222503_AddTickets.Designer.cs @@ -622,17 +622,17 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) }, new { - Key = "AdyenApiKey ", + Key = "AdyenApiKey", SerializedValue = "" }, new { - Key = "AdyenClientKey ", + Key = "AdyenClientKey", SerializedValue = "" }, new { - Key = "AdyenMerchantAccount ", + Key = "AdyenMerchantAccount", SerializedValue = "" }); }); diff --git a/NetEvent/Server/Migrations/Sqlite/20230126222503_AddTickets.cs b/NetEvent/Server/Migrations/Sqlite/20230126222503_AddTickets.cs index 5420660b..865047ba 100644 --- a/NetEvent/Server/Migrations/Sqlite/20230126222503_AddTickets.cs +++ b/NetEvent/Server/Migrations/Sqlite/20230126222503_AddTickets.cs @@ -63,9 +63,9 @@ protected override void Up(MigrationBuilder migrationBuilder) columns: new[] { "Key", "SerializedValue" }, values: new object[,] { - { "AdyenApiKey ", "" }, - { "AdyenClientKey ", "" }, - { "AdyenMerchantAccount ", "" } + { "AdyenApiKey", "" }, + { "AdyenClientKey", "" }, + { "AdyenMerchantAccount", "" } }); migrationBuilder.UpdateData( @@ -103,17 +103,17 @@ protected override void Down(MigrationBuilder migrationBuilder) migrationBuilder.DeleteData( table: "SystemSettings", keyColumn: "Key", - keyValue: "AdyenApiKey "); + keyValue: "AdyenApiKey"); migrationBuilder.DeleteData( table: "SystemSettings", keyColumn: "Key", - keyValue: "AdyenClientKey "); + keyValue: "AdyenClientKey"); migrationBuilder.DeleteData( table: "SystemSettings", keyColumn: "Key", - keyValue: "AdyenMerchantAccount "); + keyValue: "AdyenMerchantAccount"); migrationBuilder.UpdateData( table: "User", diff --git a/NetEvent/Server/Migrations/Sqlite/SqliteApplicationDbContextModelSnapshot.cs b/NetEvent/Server/Migrations/Sqlite/SqliteApplicationDbContextModelSnapshot.cs index ab7cd474..d28ec9d3 100644 --- a/NetEvent/Server/Migrations/Sqlite/SqliteApplicationDbContextModelSnapshot.cs +++ b/NetEvent/Server/Migrations/Sqlite/SqliteApplicationDbContextModelSnapshot.cs @@ -619,17 +619,17 @@ protected override void BuildModel(ModelBuilder modelBuilder) }, new { - Key = "AdyenApiKey ", + Key = "AdyenApiKey", SerializedValue = "" }, new { - Key = "AdyenClientKey ", + Key = "AdyenClientKey", SerializedValue = "" }, new { - Key = "AdyenMerchantAccount ", + Key = "AdyenMerchantAccount", SerializedValue = "" }); }); diff --git a/NetEvent/Server/Modules/Events/Endpoints/GetEvent.cs b/NetEvent/Server/Modules/Events/Endpoints/GetEvent.cs index ca93a343..b0a6debb 100644 --- a/NetEvent/Server/Modules/Events/Endpoints/GetEvent.cs +++ b/NetEvent/Server/Modules/Events/Endpoints/GetEvent.cs @@ -26,7 +26,7 @@ public async Task Handle(Request request, CancellationToken cancellati Models.Event? eventModel; if (request.Slug != null) { - eventModel = await _DbContext.Events.Where(e => e.Slug != null && e.Slug.Equals(request.Slug, StringComparison.OrdinalIgnoreCase)).Include(e => e.TicketTypes).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); + eventModel = await _DbContext.Events.Where(e => e.Slug == request.Slug).Include(e => e.TicketTypes).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); } else { diff --git a/NetEvent/Server/Modules/Payment/Endpoints/DeleteVenue.cs b/NetEvent/Server/Modules/Payment/Endpoints/DeleteVenue.cs deleted file mode 100644 index 073bb790..00000000 --- a/NetEvent/Server/Modules/Payment/Endpoints/DeleteVenue.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using NetEvent.Server.Data.Events; - -namespace NetEvent.Server.Modules.Payment.Endpoints -{ - public static class DeleteVenue - { - public sealed class Handler : IRequestHandler - { - private readonly IEventManager _EventManager; - - public Handler(IEventManager eventManager) - { - _EventManager = eventManager; - } - - public async Task Handle(Request request, CancellationToken cancellationToken) - { - var result = await _EventManager.DeleteVenueAsync(request.VenueId).ConfigureAwait(false); - if (!result.Succeeded) - { - return new Response(ReturnType.Error, string.Join(Environment.NewLine, result.Errors)); - } - - return new Response(); - } - } - - public sealed class Request : IRequest - { - public Request(long venueId) - { - VenueId = venueId; - } - - public long VenueId { get; } - } - - public sealed class Response : ResponseBase - { - public Response() - { - } - - public Response(ReturnType returnType, string error) : base(returnType, error) - { - } - } - } -} diff --git a/NetEvent/Server/Modules/Payment/Endpoints/GetPaymentMethods.cs b/NetEvent/Server/Modules/Payment/Endpoints/GetPaymentMethods.cs new file mode 100644 index 00000000..1531cb68 --- /dev/null +++ b/NetEvent/Server/Modules/Payment/Endpoints/GetPaymentMethods.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using NetEvent.Server.Data; +using NetEvent.Shared; +using NetEvent.Shared.Dto; +using NetEvent.Shared.Dto.Event; + +namespace NetEvent.Server.Modules.Payment.Endpoints +{ + public static class GetPaymentMethods + { + public sealed class Handler : IRequestHandler + { + private readonly IPaymentManager _PaymentManager; + + public Handler(IPaymentManager paymentManager) + { + _PaymentManager = paymentManager; + } + + public async Task Handle(Request request, CancellationToken cancellationToken) + { + var paymentMethodResponse = await _PaymentManager.GetPaymentMethodsAsync(request.Amount, request.Currency); + var result = paymentMethodResponse.PaymentMethods.Select(x => x.ToPaymentMethodDto()).ToList(); + + return new Response(result); + } + } + + public sealed class Request : IRequest + { + public Request(long amount, CurrencyDto currency) + { + Amount = amount; + Currency = currency; + } + + public CurrencyDto Currency { get; } + + public long Amount { get; } + } + + public sealed class Response : ResponseBase> + { + public Response(IReadOnlyCollection response) : base(response) + { + } + + public Response(ReturnType returnType, string error) : base(returnType, error) + { + } + } + } +} diff --git a/NetEvent/Server/Modules/Payment/Endpoints/GetVenue.cs b/NetEvent/Server/Modules/Payment/Endpoints/GetVenue.cs deleted file mode 100644 index 2a4f80c4..00000000 --- a/NetEvent/Server/Modules/Payment/Endpoints/GetVenue.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using NetEvent.Server.Data; -using NetEvent.Shared; -using NetEvent.Shared.Dto.Event; - -namespace NetEvent.Server.Modules.Payment.Endpoints -{ - public static class GetVenue - { - public sealed class Handler : IRequestHandler - { - private readonly ApplicationDbContext _DbContext; - - public Handler(ApplicationDbContext dbContext) - { - _DbContext = dbContext; - } - - public async Task Handle(Request request, CancellationToken cancellationToken) - { - Models.Venue? venueModel; - if (request.Slug != null) - { - venueModel = _DbContext.Venues.Where(e => e.Slug != null && e.Slug.Equals(request.Slug, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); - } - else - { - venueModel = await _DbContext.Venues.FindAsync(new object[] { request.Id }, cancellationToken); - } - - if (venueModel == null) - { - return new Response(ReturnType.NotFound, "Venue for Id not found!"); - } - - var convertedVenue = venueModel.ToVenueDto(); - - return new Response(convertedVenue); - } - } - - public sealed class Request : IRequest - { - public Request(long id) - { - Id = id; - } - - public Request(string slug) - { - Slug = slug; - } - - public long Id { get; } - - public string? Slug { get; } - } - - public sealed class Response : ResponseBase - { - public Response(VenueDto? value) : base(value) - { - } - - public Response(ReturnType returnType, string error) : base(returnType, error) - { - } - } - } -} diff --git a/NetEvent/Server/Modules/Payment/Endpoints/GetVenues.cs b/NetEvent/Server/Modules/Payment/Endpoints/GetVenues.cs deleted file mode 100644 index fd70e656..00000000 --- a/NetEvent/Server/Modules/Payment/Endpoints/GetVenues.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using Microsoft.EntityFrameworkCore; -using NetEvent.Server.Data; -using NetEvent.Shared; -using NetEvent.Shared.Dto.Event; - -namespace NetEvent.Server.Modules.Payment.Endpoints -{ - public static class GetVenues - { - public sealed class Handler : IRequestHandler - { - private readonly ApplicationDbContext _DbContext; - - public Handler(ApplicationDbContext dbContext) - { - _DbContext = dbContext; - } - - public async Task Handle(Request request, CancellationToken cancellationToken) - { - var allVenues = await _DbContext.Venues.ToListAsync(cancellationToken); - var convertedVenues = allVenues.Select(DtoMapper.ToVenueDto).ToList(); - return new Response(convertedVenues); - } - } - - public sealed class Request : IRequest - { - } - - public sealed class Response : ResponseBase> - { - public Response(IEnumerable? value) : base(value) - { - } - - public Response(ReturnType returnType, string error) : base(returnType, error) - { - } - } - } -} diff --git a/NetEvent/Server/Modules/Payment/Endpoints/PutVenue.cs b/NetEvent/Server/Modules/Payment/Endpoints/PutVenue.cs deleted file mode 100644 index 42ec0c10..00000000 --- a/NetEvent/Server/Modules/Payment/Endpoints/PutVenue.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using MediatR; -using NetEvent.Server.Data.Events; -using NetEvent.Shared; -using NetEvent.Shared.Dto.Event; - -namespace NetEvent.Server.Modules.Payment.Endpoints -{ - public static class PutVenue - { - public sealed class Handler : IRequestHandler - { - private readonly IEventManager _EventManager; - - public Handler(IEventManager eventManager) - { - _EventManager = eventManager; - } - - public async Task Handle(Request request, CancellationToken cancellationToken) - { - var newVenue = request.Venue.ToVenue(); - var result = await _EventManager.UpdateVenueAsync(newVenue).ConfigureAwait(false); - if (!result.Succeeded) - { - return new Response(ReturnType.Error, string.Join(Environment.NewLine, result.Errors)); - } - - return new Response(newVenue.ToVenueDto()); - } - } - - public sealed class Request : IRequest - { - public Request(long id, VenueDto venueDto) - { - Guard.IsNotNull(venueDto, nameof(venueDto)); - Guard.IsNotNull(venueDto!.Id, nameof(venueDto)); - - Id = id; - Venue = venueDto; - } - - public long Id { get; } - - public VenueDto Venue { get; } - } - - public sealed class Response : ResponseBase - { - public Response(VenueDto createdVenue) : base(createdVenue) - { - } - - public Response(ReturnType returnType, string error) : base(returnType, error) - { - } - } - } -} diff --git a/NetEvent/Server/Modules/Payment/PaymentModule.cs b/NetEvent/Server/Modules/Payment/PaymentModule.cs index 50c80447..e469d985 100644 --- a/NetEvent/Server/Modules/Payment/PaymentModule.cs +++ b/NetEvent/Server/Modules/Payment/PaymentModule.cs @@ -17,6 +17,7 @@ public class PaymentModule : ModuleBase public override IEndpointRouteBuilder MapModuleEndpoints(IEndpointRouteBuilder endpoints) { // BaseRoute: /api/payment + endpoints.MapGet("/paymentmethods/{amount:long}/{currency}", async ([FromRoute] long amount, [FromRoute] CurrencyDto currency, [FromServices] IMediator m) => ToApiResult(await m.Send(new GetPaymentMethods.Request(amount, currency)))); endpoints.MapPost("/buy", async ([FromBody] CartDto cartDto, ClaimsPrincipal user, [FromServices] IMediator m) => ToApiResult(await m.Send(new PostCart.Request(cartDto, user)))); //endpoints.MapGet("/{venueId:long}", async ([FromRoute] long venueId, [FromServices] IMediator m) => ToApiResult(await m.Send(new GetVenue.Request(venueId)))); //endpoints.MapGet("/{slug}", async ([FromRoute] string slug, [FromServices] IMediator m) => ToApiResult(await m.Send(new GetVenue.Request(slug)))); diff --git a/NetEvent/Shared/Config/SystemSettings.cs b/NetEvent/Shared/Config/SystemSettings.cs index 8c87faf4..0455f5f0 100644 --- a/NetEvent/Shared/Config/SystemSettings.cs +++ b/NetEvent/Shared/Config/SystemSettings.cs @@ -59,9 +59,9 @@ public AuthenticationData() : base(SystemSettingGroup.AuthenticationData) public class PaymentData : SettingGroupBase { - public const string AdyenApiKey = "AdyenApiKey "; - public const string AdyenClientKey = "AdyenClientKey "; - public const string AdyenMerchantAccount = "AdyenMerchantAccount "; + public const string AdyenApiKey = "AdyenApiKey"; + public const string AdyenClientKey = "AdyenClientKey"; + public const string AdyenMerchantAccount = "AdyenMerchantAccount"; public PaymentData() : base(SystemSettingGroup.PaymentData) { diff --git a/NetEvent/Shared/Dto/PaymentMethodDto.cs b/NetEvent/Shared/Dto/PaymentMethodDto.cs new file mode 100644 index 00000000..3197300e --- /dev/null +++ b/NetEvent/Shared/Dto/PaymentMethodDto.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; + +namespace NetEvent.Shared.Dto; + +public class PaymentMethodDto +{ + [JsonPropertyName("name")] + public string? Name { get; set; } + + [JsonPropertyName("type")] + public string? Type { get; set; } +} From 3f5ecaa85fa88b047fa43ac5bbbc072ba672e972 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Tue, 14 Feb 2023 21:44:11 +0100 Subject: [PATCH 20/39] checkout --- .../Client/Extensions/CurrencyConverter.cs | 33 +++++ NetEvent/Client/JavaScripts/src/checkout.js | 115 +++++++++++++++--- .../Administration/Events/TicketType.razor | 16 +-- .../Administration/Events/TicketType.razor.cs | 5 + .../Administration/Events/TicketTypes.razor | 2 +- .../Pages/Checkout/CheckoutTicket.razor | 6 +- .../Pages/Checkout/CheckoutTicket.razor.cs | 20 ++- NetEvent/Client/Pages/Events/Event.razor | 3 +- NetEvent/Client/Pages/Events/Event.razor.cs | 2 +- NetEvent/Client/Program.cs | 2 +- NetEvent/Client/Services/CartService.cs | 32 ----- NetEvent/Client/Services/EventService.cs | 24 +--- NetEvent/Client/Services/ICartService.cs | 10 -- NetEvent/Client/Services/IEventService.cs | 2 - NetEvent/Client/Services/IPaymentService.cs | 15 +++ NetEvent/Client/Services/PaymentService.cs | 82 +++++++++++++ NetEvent/Server/Data/PaymentManager.cs | 3 +- .../Shared/Dto/Event/CurrencyExtension.cs | 18 +++ NetEvent/Shared/Dto/PaymentMethodDto.cs | 42 ++++++- .../EventTicketTypeModelFluentValidator.cs | 2 +- 20 files changed, 328 insertions(+), 106 deletions(-) create mode 100644 NetEvent/Client/Extensions/CurrencyConverter.cs delete mode 100644 NetEvent/Client/Services/CartService.cs delete mode 100644 NetEvent/Client/Services/ICartService.cs create mode 100644 NetEvent/Client/Services/IPaymentService.cs create mode 100644 NetEvent/Client/Services/PaymentService.cs diff --git a/NetEvent/Client/Extensions/CurrencyConverter.cs b/NetEvent/Client/Extensions/CurrencyConverter.cs new file mode 100644 index 00000000..9a0b22dc --- /dev/null +++ b/NetEvent/Client/Extensions/CurrencyConverter.cs @@ -0,0 +1,33 @@ +using System; +using System.Globalization; +using NetEvent.Shared.Dto.Event; + +namespace NetEvent.Client.Extensions +{ + public class CurrencyConverter : MudBlazor.Converter + { + private readonly CurrencyDto _Currency; + + public CurrencyConverter(CurrencyDto currency) + { + SetFunc = ToInputValue; + GetFunc = ToCurrencyValue; + _Currency = currency; + } + + private int ToCurrencyValue(string arg) + { + if (!double.TryParse(arg, CultureInfo.InvariantCulture, out var value)) + { + return 0; + } + + return _Currency.ToCurrencyBaseValue(value); + } + + private string ToInputValue(int arg) + { + return Convert.ToString(_Currency.ToCurrencyValue(arg), Culture); + } + } +} diff --git a/NetEvent/Client/JavaScripts/src/checkout.js b/NetEvent/Client/JavaScripts/src/checkout.js index d005f8d4..887ffb70 100644 --- a/NetEvent/Client/JavaScripts/src/checkout.js +++ b/NetEvent/Client/JavaScripts/src/checkout.js @@ -2,45 +2,122 @@ import AdyenCheckout from '@adyen/adyen-web'; import '@adyen/adyen-web/dist/adyen.css'; +//const configuration = { +// environment: 'test', // Change to one of the environment values specified in step 4. +// //clientKey: 'test_870be2...', // Public key used for client-side authentication: https://docs.adyen.com/development-resources/client-side-authentication +// analytics: { +// enabled: false // Set to false to not send analytics data to Adyen. +// }, +// session: { +// //id: 'CSD9CAC3...', // Unique identifier for the payment session. +// //sessionData: 'Ab02b4c...' // The payment session data. +// }, +// onPaymentCompleted: (result, component) => { +// console.info(result, component); +// }, +// onError: (error, component) => { +// console.error(error.name, error.message, error.stack, component); +// }, +// // Any payment method specific configuration. Find the configuration specific to each payment method: https://docs.adyen.com/payment-methods +// // For example, this is 3D Secure configuration for cards: +// paymentMethodsConfiguration: { +// card: { +// hasHolderName: true, +// holderNameRequired: true, +// billingAddressRequired: true +// } +// } +//}; + +//export async function startPaymentAsync(clientKey, sessionId, sessionData) { +// configuration.clientKey = clientKey; +// configuration.session.id = sessionId; +// configuration.session.sessionData = sessionData; + +// // Create an instance of AdyenCheckout using the configuration object. +// const checkout = await AdyenCheckout(configuration); +// // Access the available payment methods for the session. +// console.log(checkout.paymentMethodsResponse); // => { paymentMethods: [...], storedPaymentMethods: [...] } + +// // Create an instance of the Component and mount it to the container you created. +// const cardComponent = checkout.create('card').mount('#payment-container'); + +// // TODO Handle RedirectResult +// // https://docs.adyen.com/online-payments/web-components#handle-redirect-result +//}; + + const configuration = { - environment: 'test', // Change to one of the environment values specified in step 4. - //clientKey: 'test_870be2...', // Public key used for client-side authentication: https://docs.adyen.com/development-resources/client-side-authentication + //paymentMethodsResponse: paymentMethodsResponse, // The `/paymentMethods` response from the server. + //clientKey: "YOUR_CLIENT_KEY", // Web Drop-in versions before 3.10.1 use originKey instead of clientKey. + locale: "de-DE", + environment: "test", analytics: { enabled: false // Set to false to not send analytics data to Adyen. }, - session: { - //id: 'CSD9CAC3...', // Unique identifier for the payment session. - //sessionData: 'Ab02b4c...' // The payment session data. + onSubmit: (state, dropin) => { + // Global configuration for onSubmit + // Your function calling your server to make the `/payments` request + makePayment(state.data) + .then(response => { + if (response.action) { + // Drop-in handles the action object from the /payments response + dropin.handleAction(response.action); + } else { + // Your function to show the final result to the shopper + showFinalResult(response); + } + }) + .catch(error => { + throw Error(error); + }); }, - onPaymentCompleted: (result, component) => { - console.info(result, component); + onAdditionalDetails: (state, dropin) => { + // Your function calling your server to make a `/payments/details` request + makeDetailsCall(state.data) + .then(response => { + if (response.action) { + // Drop-in handles the action object from the /payments response + dropin.handleAction(response.action); + } else { + // Your function to show the final result to the shopper + showFinalResult(response); + } + }) + .catch(error => { + throw Error(error); + }); }, - onError: (error, component) => { - console.error(error.name, error.message, error.stack, component); - }, - // Any payment method specific configuration. Find the configuration specific to each payment method: https://docs.adyen.com/payment-methods - // For example, this is 3D Secure configuration for cards: paymentMethodsConfiguration: { - card: { + card: { // Example optional configuration for Cards hasHolderName: true, holderNameRequired: true, - billingAddressRequired: true + enableStoreDetails: true, + hideCVC: false, // Change this to true to hide the CVC field for stored cards + name: 'Credit or debit card', + onSubmit: () => { }, // onSubmit configuration for card payments. Overrides the global configuration. } } }; -export async function startPaymentAsync(clientKey, sessionId, sessionData) { + +export async function startPaymentAsync(clientKey, paymentMethods) { configuration.clientKey = clientKey; - configuration.session.id = sessionId; - configuration.session.sessionData = sessionData; + configuration.paymentMethodsResponse = JSON.parse(paymentMethods); // Create an instance of AdyenCheckout using the configuration object. const checkout = await AdyenCheckout(configuration); // Access the available payment methods for the session. - console.log(checkout.paymentMethodsResponse); // => { paymentMethods: [...], storedPaymentMethods: [...] } + console.log(clientKey); + console.log(checkout.paymentMethodsResponse); // Create an instance of the Component and mount it to the container you created. - const cardComponent = checkout.create('card').mount('#payment-container'); + const dropin = checkout + .create('dropin', { + // Starting from version 4.0.0, Drop-in configuration only accepts props related to itself and cannot contain generic configuration like the onSubmit event. + openFirstPaymentMethod: false + }) + .mount('#dropin-container'); // TODO Handle RedirectResult // https://docs.adyen.com/online-payments/web-components#handle-redirect-result diff --git a/NetEvent/Client/Pages/Administration/Events/TicketType.razor b/NetEvent/Client/Pages/Administration/Events/TicketType.razor index 62e3cd50..123ea535 100644 --- a/NetEvent/Client/Pages/Administration/Events/TicketType.razor +++ b/NetEvent/Client/Pages/Administration/Events/TicketType.razor @@ -1,4 +1,5 @@ @page "/administration/event/{eventId}/tickettype/{ticketTypeId}" +@using NetEvent.Client.Extensions; @using NetEvent.Shared.Dto.Event; @if (_Loading) @@ -43,18 +44,13 @@ else if (_EventTicketType != null) - - - + + + _EventTicketType.Currency.ToCurrencyValue(_EventTicketType.Price); set => _EventTicketType.Price = _EventTicketType.Currency.ToCurrencyBaseValue(value); } protected override async Task OnInitializedAsync() { @@ -80,6 +83,8 @@ protected override async Task OnInitializedAsync() }; } + CurrencyConverter = new CurrencyConverter(_EventTicketType.Currency); + _Loading = false; } diff --git a/NetEvent/Client/Pages/Administration/Events/TicketTypes.razor b/NetEvent/Client/Pages/Administration/Events/TicketTypes.razor index 32993947..29417e4f 100644 --- a/NetEvent/Client/Pages/Administration/Events/TicketTypes.razor +++ b/NetEvent/Client/Pages/Administration/Events/TicketTypes.razor @@ -26,7 +26,7 @@ @context.SellStartDate @context.SellEndDate @context.AvailableTickets - @context.Price @context.Currency.ToSymbol() + @context.Currency.ToCurrencyValue(context.Price) @context.Currency.ToSymbol() @context.IsGiftable @Localizer["Administration.Events.EventTicketType.Edit"] diff --git a/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor index 4c54f8fe..98fbfb9e 100644 --- a/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor +++ b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor @@ -17,7 +17,7 @@ else @EventTicketType.Name - @EventTicketType.Price @EventTicketType.Currency.ToSymbol() + @EventTicketType.Currency.ToCurrencyValue(EventTicketType.Price) @EventTicketType.Currency.ToSymbol() @@ -32,4 +32,6 @@ else
} -
+
+ +@*
*@ diff --git a/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs index 2c0a61bd..4e6943fd 100644 --- a/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs +++ b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs @@ -22,6 +22,8 @@ using Microsoft.Extensions.Localization; using NetEvent.Shared.Dto; using NetEvent.Shared.Config; +using System.Text.Json.Serialization; +using System.Text.Json; namespace NetEvent.Client.Pages.Checkout { @@ -32,6 +34,9 @@ public partial class CheckoutTicket [Inject] private IEventService EventService { get; set; } = default!; + [Inject] + private IPaymentService PaymentService { get; set; } = default!; + [Inject] private ISystemSettingsDataService SettingsService { get; set; } = default!; @@ -55,6 +60,7 @@ public partial class CheckoutTicket private EventTicketTypeDto? EventTicketType; private CheckoutSessionDto? CheckoutSession; + private IReadOnlyCollection? PaymentMethods; protected override async Task OnInitializedAsync() { @@ -62,7 +68,17 @@ protected override async Task OnInitializedAsync() Amount ??= 1; EventTicketType = await EventService.GetEventTicketTypeAsync(TicketType, cts.Token).ConfigureAwait(false); - // TODO Load PaymentMethods via new IPaymentService + if (EventTicketType != null) + { + var result = await PaymentService.LoadPaymentMethodsAsync(EventTicketType.Price, EventTicketType.Currency, cts.Token).ConfigureAwait(false); + if (result.Successful) + { + PaymentMethods = result.ResultData; + var clientKey = await SettingsService.GetSystemSettingAsync(SystemSettingGroup.PaymentData, SystemSettings.PaymentData.AdyenClientKey, cts.Token).ConfigureAwait(false); + var paymentMethod = JsonSerializer.Serialize(new { paymentMethods = PaymentMethods }, new JsonSerializerOptions() { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault }); + await JsRuntime.InvokeVoidAsync("checkout.startPaymentAsync", clientKey?.Value, paymentMethod).ConfigureAwait(false); + } + } } private async Task BuyTicketAsync() @@ -73,7 +89,7 @@ private async Task BuyTicketAsync() } var cts = new CancellationTokenSource(); - var result = await EventService.BuyTicketAsync(EventTicketType.Id.Value, Amount.Value, cts.Token).ConfigureAwait(false); + var result = await PaymentService.BuyTicketAsync(EventTicketType.Id.Value, Amount.Value, cts.Token).ConfigureAwait(false); if (result.Successful && result.ResultData != null) { var clientKey = await SettingsService.GetSystemSettingAsync(SystemSettingGroup.PaymentData, SystemSettings.PaymentData.AdyenClientKey, cts.Token).ConfigureAwait(false); diff --git a/NetEvent/Client/Pages/Events/Event.razor b/NetEvent/Client/Pages/Events/Event.razor index 00f99c35..32ccb0bd 100644 --- a/NetEvent/Client/Pages/Events/Event.razor +++ b/NetEvent/Client/Pages/Events/Event.razor @@ -66,11 +66,10 @@ @ticketType.Name - @ticketType.Price @ticketType.Currency.ToSymbol() + @ticketType.Currency.ToCurrencyValue(ticketType.Price) @ticketType.Currency.ToSymbol() - @Localize["Events.Event.Tickets.Available", "TODO remainingTickets / " + @ticketType.AvailableTickets] diff --git a/NetEvent/Client/Pages/Events/Event.razor.cs b/NetEvent/Client/Pages/Events/Event.razor.cs index 5ed3b3a1..3e2c4369 100644 --- a/NetEvent/Client/Pages/Events/Event.razor.cs +++ b/NetEvent/Client/Pages/Events/Event.razor.cs @@ -27,7 +27,7 @@ public partial class Event private IStringLocalizer Localizer { get; set; } = default!; [Inject] - private ICartService CartService { get; set; } = default!; + private IPaymentService CartService { get; set; } = default!; #endregion diff --git a/NetEvent/Client/Program.cs b/NetEvent/Client/Program.cs index 5590d57e..fd9c499b 100644 --- a/NetEvent/Client/Program.cs +++ b/NetEvent/Client/Program.cs @@ -40,7 +40,7 @@ private static async Task Main(string[] args) builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); - builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddSingleton(); diff --git a/NetEvent/Client/Services/CartService.cs b/NetEvent/Client/Services/CartService.cs deleted file mode 100644 index cda6e806..00000000 --- a/NetEvent/Client/Services/CartService.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Threading.Tasks; -using Blazored.LocalStorage; -using NetEvent.Shared.Dto; - -namespace NetEvent.Client.Services -{ - public class CartService : ICartService - { - private const string _CartKey = "cart"; - - private readonly ILocalStorageService _LocalStorage; - - public CartService(ILocalStorageService localStorage) - { - _LocalStorage = localStorage; - } - - public async Task LoadCart(string cartId) - { - if (await _LocalStorage.ContainKeyAsync(cartId).ConfigureAwait(false)) - { - return await _LocalStorage.GetItemAsync(_CartKey); - } - - var cart = new CartDto(); - await _LocalStorage.SetItemAsync(_CartKey, cart); - return cart; - } - - //public async Task AddToCart() - } -} diff --git a/NetEvent/Client/Services/EventService.cs b/NetEvent/Client/Services/EventService.cs index 526a8128..f37dbaf7 100644 --- a/NetEvent/Client/Services/EventService.cs +++ b/NetEvent/Client/Services/EventService.cs @@ -241,27 +241,5 @@ public async Task DeleteEventTicketTypeAsync(long id, Cancellatio } } - public async Task> BuyTicketAsync(long id, int amount, CancellationToken cancellationToken) - { - try - { - var ticketCart = new CartDto { CartEntries = new[] { new CartEntryDto { TicketId = id, Amount = amount } } }; - - var client = _HttpClientFactory.CreateClient(Constants.BackendApiHttpClientName); - - var response = await client.PostAsJsonAsync($"api/payment/buy", ticketCart, cancellationToken); - response.EnsureSuccessStatusCode(); - - var sessionResponse = await response.Content.ReadFromJsonAsync().ConfigureAwait(false); - - return ServiceResult.Success(sessionResponse, "EventService.AddAsync.Success"); - } - catch (Exception ex) - { - _Logger.LogError(ex, "Unable to create eventTicketType in backend."); - } - - return ServiceResult.Error("EventService.AddAsync.Error"); - } - } + } } diff --git a/NetEvent/Client/Services/ICartService.cs b/NetEvent/Client/Services/ICartService.cs deleted file mode 100644 index 704a1e2b..00000000 --- a/NetEvent/Client/Services/ICartService.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Threading.Tasks; -using NetEvent.Shared.Dto; - -namespace NetEvent.Client.Services -{ - public interface ICartService - { - Task LoadCart(string cartId); - } -} diff --git a/NetEvent/Client/Services/IEventService.cs b/NetEvent/Client/Services/IEventService.cs index 8773ee24..24758fe8 100644 --- a/NetEvent/Client/Services/IEventService.cs +++ b/NetEvent/Client/Services/IEventService.cs @@ -27,7 +27,5 @@ public interface IEventService Task UpdateEventTicketTypeAsync(EventTicketTypeDto eventTicketTypeDto, CancellationToken cancellationToken); Task CreateEventTicketTypeAsync(long eventId, EventTicketTypeDto eventTicketTypeDto, CancellationToken cancellationToken); - - Task> BuyTicketAsync(long id, int amount, CancellationToken cancellationToken); } } diff --git a/NetEvent/Client/Services/IPaymentService.cs b/NetEvent/Client/Services/IPaymentService.cs new file mode 100644 index 00000000..a583ce82 --- /dev/null +++ b/NetEvent/Client/Services/IPaymentService.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using NetEvent.Shared.Dto; +using NetEvent.Shared.Dto.Event; + +namespace NetEvent.Client.Services +{ + public interface IPaymentService + { + Task> BuyTicketAsync(long id, int amount, CancellationToken cancellationToken); + Task LoadCart(string cartId); + Task?>> LoadPaymentMethodsAsync(long amount, CurrencyDto currency, CancellationToken cancellationToken); + } +} diff --git a/NetEvent/Client/Services/PaymentService.cs b/NetEvent/Client/Services/PaymentService.cs new file mode 100644 index 00000000..8060d747 --- /dev/null +++ b/NetEvent/Client/Services/PaymentService.cs @@ -0,0 +1,82 @@ +using System.Net.Http; +using System.Threading; +using System; +using System.Threading.Tasks; +using Blazored.LocalStorage; +using NetEvent.Shared.Dto; +using System.Net.Http.Json; +using Microsoft.Extensions.Logging; +using NetEvent.Shared.Dto.Event; +using System.Collections.Generic; + +namespace NetEvent.Client.Services +{ + public class PaymentService : IPaymentService + { + private const string _CartKey = "cart"; + + private readonly IHttpClientFactory _HttpClientFactory; + private readonly ILogger _Logger; + private readonly ILocalStorageService _LocalStorage; + + public PaymentService(ILocalStorageService localStorage, IHttpClientFactory httpClientFactory, ILogger logger) + { + _LocalStorage = localStorage; + _HttpClientFactory = httpClientFactory; + _Logger = logger; + } + + public async Task LoadCart(string cartId) + { + if (await _LocalStorage.ContainKeyAsync(cartId).ConfigureAwait(false)) + { + return await _LocalStorage.GetItemAsync(_CartKey); + } + + var cart = new CartDto(); + await _LocalStorage.SetItemAsync(_CartKey, cart); + return cart; + } + + public async Task> BuyTicketAsync(long id, int amount, CancellationToken cancellationToken) + { + try + { + var ticketCart = new CartDto { CartEntries = new[] { new CartEntryDto { TicketId = id, Amount = amount } } }; + + var client = _HttpClientFactory.CreateClient(Constants.BackendApiHttpClientName); + + var response = await client.PostAsJsonAsync($"api/payment/buy", ticketCart, cancellationToken); + response.EnsureSuccessStatusCode(); + + var sessionResponse = await response.Content.ReadFromJsonAsync().ConfigureAwait(false); + + return ServiceResult.Success(sessionResponse, "EventService.AddAsync.Success"); + } + catch (Exception ex) + { + _Logger.LogError(ex, "Unable to create eventTicketType in backend."); + } + + return ServiceResult.Error("EventService.AddAsync.Error"); + } + + public async Task?>> LoadPaymentMethodsAsync(long amount, CurrencyDto currency, CancellationToken cancellationToken) + { + try + { + var client = _HttpClientFactory.CreateClient(Constants.BackendApiHttpClientName); + + var response = await client.GetFromJsonAsync>($"api/payment/paymentmethods/{amount}/{currency}", cancellationToken); + + return ServiceResult?>.Success(response); + } + catch (Exception ex) + { + _Logger.LogError(ex, "Unable to create eventTicketType in backend."); + } + + return ServiceResult?>.Error("PaymentService.LoadPaymentMethodsAsync.Error"); + } + } +} diff --git a/NetEvent/Server/Data/PaymentManager.cs b/NetEvent/Server/Data/PaymentManager.cs index eb020678..428f0702 100644 --- a/NetEvent/Server/Data/PaymentManager.cs +++ b/NetEvent/Server/Data/PaymentManager.cs @@ -54,9 +54,8 @@ public async Task GetPaymentMethodsAsync(long amount, Cu var client = new Adyen.Client(apiKey.SerializedValue, Adyen.Model.Enum.Environment.Test); var checkout = new Checkout(client); - var paymentMethodsRequest = new PaymentMethodsRequest() + var paymentMethodsRequest = new PaymentMethodsRequest(merchantAccount: merchantAccount.SerializedValue) { - MerchantAccount = merchantAccount.SerializedValue, CountryCode = new RegionInfo(CultureInfo.CurrentUICulture.LCID).TwoLetterISORegionName, ShopperLocale = CultureInfo.CurrentUICulture.Name, Amount = new Amount(currency.To3DigitIso(), amount), diff --git a/NetEvent/Shared/Dto/Event/CurrencyExtension.cs b/NetEvent/Shared/Dto/Event/CurrencyExtension.cs index 47cd74b7..a7ac7cfc 100644 --- a/NetEvent/Shared/Dto/Event/CurrencyExtension.cs +++ b/NetEvent/Shared/Dto/Event/CurrencyExtension.cs @@ -21,5 +21,23 @@ public static string To3DigitIso(this CurrencyDto currency) _ => throw new NotSupportedException($"The Currency {currency} is not implemented!"), }; } + + public static int ToCurrencyBaseValue(this CurrencyDto currency, double value) + { + return currency switch + { + CurrencyDto.Euro => (int)(value * 100), + _ => throw new NotSupportedException($"The Currency {currency} is not implemented!"), + }; + } + + public static double ToCurrencyValue(this CurrencyDto currency, int baseValue) + { + return currency switch + { + CurrencyDto.Euro => baseValue / 100d, + _ => throw new NotSupportedException($"The Currency {currency} is not implemented!"), + }; + } } } diff --git a/NetEvent/Shared/Dto/PaymentMethodDto.cs b/NetEvent/Shared/Dto/PaymentMethodDto.cs index 3197300e..fa725249 100644 --- a/NetEvent/Shared/Dto/PaymentMethodDto.cs +++ b/NetEvent/Shared/Dto/PaymentMethodDto.cs @@ -1,12 +1,52 @@ -using System.Text.Json.Serialization; +using System.Collections.Generic; +using System.Text.Json.Serialization; namespace NetEvent.Shared.Dto; public class PaymentMethodDto { + [JsonPropertyName("brand")] + public string? Brand { get; set; } + + [JsonPropertyName("brands")] + public List Brands { get; set; } + + [JsonPropertyName("configuration")] + public Dictionary Configuration { get; set; } + + [JsonPropertyName("group")] + public PaymentMethodGroupDto Group { get; set; } + + [JsonPropertyName("issuers")] + public List Issuers { get; set; } + [JsonPropertyName("name")] public string? Name { get; set; } [JsonPropertyName("type")] public string? Type { get; set; } } + +public class PaymentMethodGroupDto +{ + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("paymentMethodData")] + public string PaymentMethodData { get; set; } + + [JsonPropertyName("type")] + public string Type { get; set; } +} + +public class PaymentMethodIssuerDto +{ + [JsonPropertyName("disabled")] + public bool Disabled { get; set; } + + [JsonPropertyName("id")] + public string Id { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } +} diff --git a/NetEvent/Shared/Validators/EventTicketTypeModelFluentValidator.cs b/NetEvent/Shared/Validators/EventTicketTypeModelFluentValidator.cs index 75b98f2f..86c74cbc 100644 --- a/NetEvent/Shared/Validators/EventTicketTypeModelFluentValidator.cs +++ b/NetEvent/Shared/Validators/EventTicketTypeModelFluentValidator.cs @@ -25,7 +25,7 @@ public EventTicketTypeModelFluentValidator() .GreaterThan(x => x.SellStartDate); RuleFor(x => x.SellStartDate) - .GreaterThan(DateTime.UtcNow); + .NotNull(); } public Func>> ValidateValue => async (model, propertyName) => From 1c15e4476f4779b7ff6290bbde79e7543237eb3c Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Fri, 17 Feb 2023 00:34:27 +0100 Subject: [PATCH 21/39] Continue Payment --- NetEvent/Client/JavaScripts/package-lock.json | 62 +- NetEvent/Client/JavaScripts/src/checkout.js | 102 +-- .../Pages/Checkout/CheckoutTicket.razor.cs | 50 +- NetEvent/Client/Pages/Events/Event.razor.cs | 4 +- NetEvent/Client/Services/IPaymentService.cs | 6 +- NetEvent/Client/Services/PaymentService.cs | 29 +- NetEvent/Server/Data/IPaymentManager.cs | 5 +- NetEvent/Server/Data/PaymentManager.cs | 65 +- NetEvent/Server/Helpers/DtoMapper.cs | 2 + ...216225406_ChangePurchaseIdType.Designer.cs | 831 ++++++++++++++++++ .../20230216225406_ChangePurchaseIdType.cs | 69 ++ .../PsqlApplicationDbContextModelSnapshot.cs | 17 +- ...216225358_ChangePurchaseIdType.Designer.cs | 814 +++++++++++++++++ .../20230216225358_ChangePurchaseIdType.cs | 68 ++ ...SqliteApplicationDbContextModelSnapshot.cs | 15 +- NetEvent/Server/Models/Purchase.cs | 4 +- .../Modules/Payment/Endpoints/PostCart.cs | 13 +- .../Payment/Endpoints/PostDropInData.cs | 59 ++ .../Server/Modules/Payment/PaymentModule.cs | 5 +- NetEvent/Shared/Dto/CheckoutSessionDto.cs | 5 +- NetEvent/Shared/Dto/PaymentResponseDto.cs | 29 + 21 files changed, 2091 insertions(+), 163 deletions(-) create mode 100644 NetEvent/Server/Migrations/Psql/20230216225406_ChangePurchaseIdType.Designer.cs create mode 100644 NetEvent/Server/Migrations/Psql/20230216225406_ChangePurchaseIdType.cs create mode 100644 NetEvent/Server/Migrations/Sqlite/20230216225358_ChangePurchaseIdType.Designer.cs create mode 100644 NetEvent/Server/Migrations/Sqlite/20230216225358_ChangePurchaseIdType.cs create mode 100644 NetEvent/Server/Modules/Payment/Endpoints/PostDropInData.cs create mode 100644 NetEvent/Shared/Dto/PaymentResponseDto.cs diff --git a/NetEvent/Client/JavaScripts/package-lock.json b/NetEvent/Client/JavaScripts/package-lock.json index bb185446..cd1bfb5f 100644 --- a/NetEvent/Client/JavaScripts/package-lock.json +++ b/NetEvent/Client/JavaScripts/package-lock.json @@ -19,9 +19,9 @@ } }, "node_modules/@adyen/adyen-web": { - "version": "5.32.0", - "resolved": "https://registry.npmjs.org/@adyen/adyen-web/-/adyen-web-5.32.0.tgz", - "integrity": "sha512-12Xi5UAnIWZTK0DZPBs+yFeM3eaMRaXNkPrfOKPrzHLI6qq5OxQ9/wyBDrTBA9phSRqE1HP2vtSzEucC3zIsZw==", + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/@adyen/adyen-web/-/adyen-web-5.33.0.tgz", + "integrity": "sha512-UKYjlEVasf4D4ujVxsAb9dvY+oDhNxM7KaBZMFJ7l3sU9bHE037g3Y1+3yraUxJaHfSJQnNVHGrTd3QmQZntbA==", "dependencies": { "@babel/runtime": "^7.15.4", "@babel/runtime-corejs3": "^7.20.1", @@ -128,9 +128,9 @@ "integrity": "sha512-RqaVZWy1Kj4e1PoUoOI8uA+4UuuLpicQFxfU9Y/xWJFZFT6mFB4PiiY911iDxFk7pdvaj5HKH7VsWRisRca1Rg==" }, "node_modules/@types/eslint": { - "version": "8.4.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.10.tgz", - "integrity": "sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw==", + "version": "8.21.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.1.tgz", + "integrity": "sha512-rc9K8ZpVjNcLs8Fp0dkozd5Pt2Apk1glO4Vgz8ix1u6yFByxfqo5Yavpy65o+93TAe24jr7v+eSBtFLvOQtCRQ==", "dev": true, "dependencies": { "@types/estree": "*", @@ -165,9 +165,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.11.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", - "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", + "version": "18.13.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", + "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==", "dev": true }, "node_modules/@webassemblyjs/ast": { @@ -419,9 +419,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", "dev": true, "funding": [ { @@ -434,10 +434,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" @@ -453,9 +453,9 @@ "dev": true }, "node_modules/caniuse-lite": { - "version": "1.0.30001449", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001449.tgz", - "integrity": "sha512-CPB+UL9XMT/Av+pJxCKGhdx+yg1hzplvFJQlJ2n68PyQGMz9L/E2zCyLdOL8uasbouTUgnPl+y0tccI/se+BEw==", + "version": "1.0.30001454", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001454.tgz", + "integrity": "sha512-4E63M5TBbgDoA9dQoFRdjL6iAmzTrz3rwYWoKDlvnvyvBxjCZ0rrUoX3THhEMie0/RYuTCeMbeTYLGAWgnLwEg==", "dev": true, "funding": [ { @@ -509,9 +509,9 @@ "dev": true }, "node_modules/core-js-pure": { - "version": "3.27.2", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.27.2.tgz", - "integrity": "sha512-Cf2jqAbXgWH3VVzjyaaFkY1EBazxugUepGymDoeteyYr9ByX51kD2jdHZlsEF/xnJMyN3Prua7mQuzwMg6Zc9A==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.28.0.tgz", + "integrity": "sha512-DSOVleA9/v3LNj/vFxAPfUHttKTzrB2RXhAPvR5TPXn4vrra3Z2ssytvRyt8eruJwAfwAiFADEbrjcRdcvPLQQ==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -571,9 +571,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "version": "1.4.301", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.301.tgz", + "integrity": "sha512-bz00ASIIDjcgszZKuEA1JEFhbDjqUNbQ/PEhNEl1wbixzYpeTp2H2QWjsQvAL2T1wJBdOwCF5hE896BoMwYKrA==", "dev": true }, "node_modules/enhanced-resolve": { @@ -934,9 +934,9 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz", - "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", "dev": true }, "node_modules/p-limit": { @@ -1377,9 +1377,9 @@ } }, "node_modules/terser": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", - "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", + "version": "5.16.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz", + "integrity": "sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.2", diff --git a/NetEvent/Client/JavaScripts/src/checkout.js b/NetEvent/Client/JavaScripts/src/checkout.js index 887ffb70..5745c14e 100644 --- a/NetEvent/Client/JavaScripts/src/checkout.js +++ b/NetEvent/Client/JavaScripts/src/checkout.js @@ -1,52 +1,6 @@ import AdyenCheckout from '@adyen/adyen-web'; import '@adyen/adyen-web/dist/adyen.css'; - -//const configuration = { -// environment: 'test', // Change to one of the environment values specified in step 4. -// //clientKey: 'test_870be2...', // Public key used for client-side authentication: https://docs.adyen.com/development-resources/client-side-authentication -// analytics: { -// enabled: false // Set to false to not send analytics data to Adyen. -// }, -// session: { -// //id: 'CSD9CAC3...', // Unique identifier for the payment session. -// //sessionData: 'Ab02b4c...' // The payment session data. -// }, -// onPaymentCompleted: (result, component) => { -// console.info(result, component); -// }, -// onError: (error, component) => { -// console.error(error.name, error.message, error.stack, component); -// }, -// // Any payment method specific configuration. Find the configuration specific to each payment method: https://docs.adyen.com/payment-methods -// // For example, this is 3D Secure configuration for cards: -// paymentMethodsConfiguration: { -// card: { -// hasHolderName: true, -// holderNameRequired: true, -// billingAddressRequired: true -// } -// } -//}; - -//export async function startPaymentAsync(clientKey, sessionId, sessionData) { -// configuration.clientKey = clientKey; -// configuration.session.id = sessionId; -// configuration.session.sessionData = sessionData; - -// // Create an instance of AdyenCheckout using the configuration object. -// const checkout = await AdyenCheckout(configuration); -// // Access the available payment methods for the session. -// console.log(checkout.paymentMethodsResponse); // => { paymentMethods: [...], storedPaymentMethods: [...] } - -// // Create an instance of the Component and mount it to the container you created. -// const cardComponent = checkout.create('card').mount('#payment-container'); - -// // TODO Handle RedirectResult -// // https://docs.adyen.com/online-payments/web-components#handle-redirect-result -//}; - - const configuration = { //paymentMethodsResponse: paymentMethodsResponse, // The `/paymentMethods` response from the server. //clientKey: "YOUR_CLIENT_KEY", // Web Drop-in versions before 3.10.1 use originKey instead of clientKey. @@ -55,26 +9,48 @@ const configuration = { analytics: { enabled: false // Set to false to not send analytics data to Adyen. }, - onSubmit: (state, dropin) => { + //paymentMethodsConfiguration: { + // card: { // Example optional configuration for Cards + // hasHolderName: true, + // holderNameRequired: true, + // enableStoreDetails: true, + // hideCVC: false, // Change this to true to hide the CVC field for stored cards + // name: 'Credit or debit card', + // onSubmit: () => { }, // onSubmit configuration for card payments. Overrides the global configuration. + // } + //} +}; + + +export async function startPaymentAsync(clientKey, paymentMethods, checkoutTickets) { + + checkoutTickets.invokeMethodAsync('TestMethod', 123); + + configuration.clientKey = clientKey; + configuration.paymentMethodsResponse = JSON.parse(paymentMethods); + + configuration.onSubmit = (state, dropin) => { // Global configuration for onSubmit // Your function calling your server to make the `/payments` request - makePayment(state.data) + checkoutTickets.invokeMethodAsync('MakePayment', state.data) .then(response => { - if (response.action) { + let responseData = JSON.parse(response); + if (responseData.action) { // Drop-in handles the action object from the /payments response - dropin.handleAction(response.action); + dropin.handleAction(responseData.action); } else { // Your function to show the final result to the shopper - showFinalResult(response); + showFinalResult(responseData); } }) .catch(error => { throw Error(error); }); - }, - onAdditionalDetails: (state, dropin) => { + }; + + configuration.onAdditionalDetails = (state, dropin) => { // Your function calling your server to make a `/payments/details` request - makeDetailsCall(state.data) + checkoutTickets.invokeMethodAsync('MakeDetailsCall', state.data) .then(response => { if (response.action) { // Drop-in handles the action object from the /payments response @@ -87,23 +63,7 @@ const configuration = { .catch(error => { throw Error(error); }); - }, - paymentMethodsConfiguration: { - card: { // Example optional configuration for Cards - hasHolderName: true, - holderNameRequired: true, - enableStoreDetails: true, - hideCVC: false, // Change this to true to hide the CVC field for stored cards - name: 'Credit or debit card', - onSubmit: () => { }, // onSubmit configuration for card payments. Overrides the global configuration. - } - } -}; - - -export async function startPaymentAsync(clientKey, paymentMethods) { - configuration.clientKey = clientKey; - configuration.paymentMethodsResponse = JSON.parse(paymentMethods); + }; // Create an instance of AdyenCheckout using the configuration object. const checkout = await AdyenCheckout(configuration); diff --git a/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs index 4e6943fd..315e2ddc 100644 --- a/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs +++ b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs @@ -24,6 +24,7 @@ using NetEvent.Shared.Config; using System.Text.Json.Serialization; using System.Text.Json; +using System.IO; namespace NetEvent.Client.Pages.Checkout { @@ -37,6 +38,9 @@ public partial class CheckoutTicket [Inject] private IPaymentService PaymentService { get; set; } = default!; + [Inject] + private NavigationService NavigationService { get; set; } = default!; + [Inject] private ISystemSettingsDataService SettingsService { get; set; } = default!; @@ -61,6 +65,7 @@ public partial class CheckoutTicket private EventTicketTypeDto? EventTicketType; private CheckoutSessionDto? CheckoutSession; private IReadOnlyCollection? PaymentMethods; + private PurchaseDto _Purchase; protected override async Task OnInitializedAsync() { @@ -68,16 +73,9 @@ protected override async Task OnInitializedAsync() Amount ??= 1; EventTicketType = await EventService.GetEventTicketTypeAsync(TicketType, cts.Token).ConfigureAwait(false); - if (EventTicketType != null) + if (EventTicketType == null) { - var result = await PaymentService.LoadPaymentMethodsAsync(EventTicketType.Price, EventTicketType.Currency, cts.Token).ConfigureAwait(false); - if (result.Successful) - { - PaymentMethods = result.ResultData; - var clientKey = await SettingsService.GetSystemSettingAsync(SystemSettingGroup.PaymentData, SystemSettings.PaymentData.AdyenClientKey, cts.Token).ConfigureAwait(false); - var paymentMethod = JsonSerializer.Serialize(new { paymentMethods = PaymentMethods }, new JsonSerializerOptions() { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault }); - await JsRuntime.InvokeVoidAsync("checkout.startPaymentAsync", clientKey?.Value, paymentMethod).ConfigureAwait(false); - } + NavigationService.NavigateBack(); } } @@ -92,11 +90,37 @@ private async Task BuyTicketAsync() var result = await PaymentService.BuyTicketAsync(EventTicketType.Id.Value, Amount.Value, cts.Token).ConfigureAwait(false); if (result.Successful && result.ResultData != null) { - var clientKey = await SettingsService.GetSystemSettingAsync(SystemSettingGroup.PaymentData, SystemSettings.PaymentData.AdyenClientKey, cts.Token).ConfigureAwait(false); - - CheckoutSession = result.ResultData; - await JsRuntime.InvokeVoidAsync("checkout.startPaymentAsync", clientKey?.Value, CheckoutSession.Id, CheckoutSession.SessionData).ConfigureAwait(false); + _Purchase = result.ResultData; + var paymentMethods = await PaymentService.LoadPaymentMethodsAsync(EventTicketType.Price, EventTicketType.Currency, cts.Token).ConfigureAwait(false); + if (result.Successful) + { + PaymentMethods = paymentMethods.ResultData; + var clientKey = await SettingsService.GetSystemSettingAsync(SystemSettingGroup.PaymentData, SystemSettings.PaymentData.AdyenClientKey, cts.Token).ConfigureAwait(false); + var paymentMethod = JsonSerializer.Serialize(new { paymentMethods = PaymentMethods }, new JsonSerializerOptions() { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault }); + await JsRuntime.InvokeVoidAsync("checkout.startPaymentAsync", clientKey?.Value, paymentMethod, DotNetObjectReference.Create(this)).ConfigureAwait(false); + } } } + + [JSInvokable] + public async Task MakePayment(JsonElement data) + { + Console.WriteLine(_Purchase.Id); + var dataJson = data.GetRawText(); + var paymentResponse = await PaymentService.MakePaymentAsync(_Purchase.Id, dataJson, CancellationToken.None).ConfigureAwait(false); + return paymentResponse?.ResultData?.PaymentResponseJson; + } + + [JSInvokable] + public Task MakeDetailsCall(object data) + { + return Task.FromResult(null); + } + + [JSInvokable] + public Task TestMethod(object data) + { + return Task.FromResult(null); + } } } diff --git a/NetEvent/Client/Pages/Events/Event.razor.cs b/NetEvent/Client/Pages/Events/Event.razor.cs index 3e2c4369..28b2be39 100644 --- a/NetEvent/Client/Pages/Events/Event.razor.cs +++ b/NetEvent/Client/Pages/Events/Event.razor.cs @@ -61,11 +61,11 @@ private static Color GetStateColor(PublishStateDto state) }; } - private async Task BuyTicketAsync(EventTicketTypeDto eventTicketType) + private Task BuyTicketAsync(EventTicketTypeDto eventTicketType) { // /checkout/ticket/{tickettypeid}/{count} NavigationManager.NavigateTo($"checkout/ticket/{eventTicketType.Id}"); - + return Task.CompletedTask; //CartService.AddToCart(eventTicketType); } } diff --git a/NetEvent/Client/Services/IPaymentService.cs b/NetEvent/Client/Services/IPaymentService.cs index a583ce82..7fc1ca8b 100644 --- a/NetEvent/Client/Services/IPaymentService.cs +++ b/NetEvent/Client/Services/IPaymentService.cs @@ -8,8 +8,12 @@ namespace NetEvent.Client.Services { public interface IPaymentService { - Task> BuyTicketAsync(long id, int amount, CancellationToken cancellationToken); + Task> BuyTicketAsync(long id, int amount, CancellationToken cancellationToken); + Task LoadCart(string cartId); + Task?>> LoadPaymentMethodsAsync(long amount, CurrencyDto currency, CancellationToken cancellationToken); + + Task> MakePaymentAsync(string purchaseId, string paymentDataJson, CancellationToken cancellationToken); } } diff --git a/NetEvent/Client/Services/PaymentService.cs b/NetEvent/Client/Services/PaymentService.cs index 8060d747..71f39be9 100644 --- a/NetEvent/Client/Services/PaymentService.cs +++ b/NetEvent/Client/Services/PaymentService.cs @@ -38,7 +38,7 @@ public async Task LoadCart(string cartId) return cart; } - public async Task> BuyTicketAsync(long id, int amount, CancellationToken cancellationToken) + public async Task> BuyTicketAsync(long id, int amount, CancellationToken cancellationToken) { try { @@ -46,19 +46,19 @@ public async Task LoadCart(string cartId) var client = _HttpClientFactory.CreateClient(Constants.BackendApiHttpClientName); - var response = await client.PostAsJsonAsync($"api/payment/buy", ticketCart, cancellationToken); + var response = await client.PostAsJsonAsync($"api/payment/checkout/buy", ticketCart, cancellationToken); response.EnsureSuccessStatusCode(); - var sessionResponse = await response.Content.ReadFromJsonAsync().ConfigureAwait(false); + var sessionResponse = await response.Content.ReadFromJsonAsync().ConfigureAwait(false); - return ServiceResult.Success(sessionResponse, "EventService.AddAsync.Success"); + return ServiceResult.Success(sessionResponse, "EventService.AddAsync.Success"); } catch (Exception ex) { _Logger.LogError(ex, "Unable to create eventTicketType in backend."); } - return ServiceResult.Error("EventService.AddAsync.Error"); + return ServiceResult.Error("EventService.AddAsync.Error"); } public async Task?>> LoadPaymentMethodsAsync(long amount, CurrencyDto currency, CancellationToken cancellationToken) @@ -78,5 +78,24 @@ public async Task LoadCart(string cartId) return ServiceResult?>.Error("PaymentService.LoadPaymentMethodsAsync.Error"); } + + public async Task> MakePaymentAsync(string purchaseId, string paymentDataJson, CancellationToken cancellationToken) + { + try + { + var client = _HttpClientFactory.CreateClient(Constants.BackendApiHttpClientName); + + var response = await client.PostAsJsonAsync($"api/payment/checkout/{purchaseId}/payments", paymentDataJson, cancellationToken); + response.EnsureSuccessStatusCode(); + var paymentResponse = await response.Content.ReadFromJsonAsync().ConfigureAwait(false); + return ServiceResult.Success(paymentResponse); + } + catch (Exception ex) + { + _Logger.LogError(ex, "Unable to create eventTicketType in backend."); + } + + return ServiceResult.Error("PaymentService.LoadPaymentMethodsAsync.Error"); + } } } diff --git a/NetEvent/Server/Data/IPaymentManager.cs b/NetEvent/Server/Data/IPaymentManager.cs index 77f805e5..b103697b 100644 --- a/NetEvent/Server/Data/IPaymentManager.cs +++ b/NetEvent/Server/Data/IPaymentManager.cs @@ -1,6 +1,7 @@ using System.Security.Claims; using System.Threading.Tasks; using Adyen.Model.Checkout; +using NetEvent.Server.Models; using NetEvent.Shared.Dto; using NetEvent.Shared.Dto.Event; @@ -10,6 +11,8 @@ public interface IPaymentManager { Task GetPaymentMethodsAsync(long amount, CurrencyDto currency); - Task PayAsync(CartDto cart, ClaimsPrincipal claimsPrincipal); + Task PurchaseAsync(CartDto cart, ClaimsPrincipal claimsPrincipal); + + Task SubmitDropInEventDataAsync(ClaimsPrincipal claimsPrincipal, string purchaseId, string paymentMethodData); } } diff --git a/NetEvent/Server/Data/PaymentManager.cs b/NetEvent/Server/Data/PaymentManager.cs index 428f0702..f3660d39 100644 --- a/NetEvent/Server/Data/PaymentManager.cs +++ b/NetEvent/Server/Data/PaymentManager.cs @@ -5,6 +5,7 @@ using System.Security.Claims; using System.Threading.Tasks; using Adyen.Model.Checkout; +using Adyen.Model.Checkout.Details; using Adyen.Service; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; @@ -66,10 +67,8 @@ public async Task GetPaymentMethodsAsync(long amount, Cu return paymentMethodsResponse; } - public async Task PayAsync(CartDto cart, ClaimsPrincipal claimsPrincipal) + public async Task PurchaseAsync(CartDto cart, ClaimsPrincipal claimsPrincipal) { - var paymentId = Guid.NewGuid(); - var merchantAccount = await _DbContext.SystemSettingValues.FindAsync(SystemSettings.PaymentData.AdyenMerchantAccount).ConfigureAwait(false); var apiKey = await _DbContext.SystemSettingValues.FindAsync(SystemSettings.PaymentData.AdyenApiKey).ConfigureAwait(false); @@ -89,31 +88,72 @@ public async Task PayAsync(CartDto cart, ClaimsPr if (purchase == null) { + // TODO Error return null; } var currencyGroup = purchase.TicketPurchases.GroupBy(x => x.Currency); if (currencyGroup.Count() > 1) { + // TODO Error return null; } await _DbContext.Purchases.AddAsync(purchase).ConfigureAwait(false); await _DbContext.SaveChangesAsync().ConfigureAwait(false); - var checkoutSessionRequest = new CreateCheckoutSessionRequest + return purchase; + } + + public async Task SubmitDropInEventDataAsync(ClaimsPrincipal claimsPrincipal, string purchaseId, string paymentMethodData) + { + var merchantAccount = await _DbContext.SystemSettingValues.FindAsync(SystemSettings.PaymentData.AdyenMerchantAccount).ConfigureAwait(false); + var apiKey = await _DbContext.SystemSettingValues.FindAsync(SystemSettings.PaymentData.AdyenApiKey).ConfigureAwait(false); + var purchase = await _DbContext.Purchases.Include(p => p.TicketPurchases).FirstOrDefaultAsync(p => p.Id == purchaseId).ConfigureAwait(false); + + if (string.IsNullOrEmpty(merchantAccount?.SerializedValue)) { + // TODO Error + return null; + } + + if (string.IsNullOrEmpty(apiKey?.SerializedValue)) + { + // TODO Error + return null; + } + + + if (purchase == null) + { + // TODO Error + return null; + } + + var currencyGroup = purchase.TicketPurchases.GroupBy(x => x.Currency); + if (currencyGroup.Count() > 1) + { + // TODO Error + return null; + } + + var paymentRequest = new PaymentRequest + { + PaymentMethod = System.Text.Json.JsonSerializer.Deserialize(paymentMethodData), MerchantAccount = merchantAccount.SerializedValue, - Reference = paymentId.ToString(), + Reference = purchase.Id, ReturnUrl = "https://your-company.com/checkout?shopperOrder=12xy..", // TODO Checkout Seite mit Polling/Events/... Amount = new Amount(currencyGroup.First().Key.ToCurrencyDto().To3DigitIso(), purchase.Price), - CountryCode = new RegionInfo(CultureInfo.CurrentUICulture.LCID).TwoLetterISORegionName, + //CountryCode = new RegionInfo(CultureInfo.CurrentUICulture.LCID).TwoLetterISORegionName, }; var client = new Adyen.Client(apiKey.SerializedValue, Adyen.Model.Enum.Environment.Test); var checkout = new Checkout(client); - return checkout.Sessions(checkoutSessionRequest); + var paymentResult = await checkout.PaymentsAsync(paymentRequest).ConfigureAwait(false); + return paymentResult; } + #region Helpers + private async Task CreatePurchaseAsync(CartDto cart, ClaimsPrincipal claimsPrincipal) { var userId = claimsPrincipal.Id(); @@ -126,11 +166,16 @@ public async Task PayAsync(CartDto cart, ClaimsPr return null; } - var maxPurchaseId = await _DbContext.Purchases.MaxAsync(x => x.Id).ConfigureAwait(false); + string purchaseId; + do + { + purchaseId = Guid.NewGuid().ToString(); + } + while ((await _DbContext.Purchases.FindAsync(purchaseId)) != null); var purchase = new Purchase { - Id = maxPurchaseId + 1, + Id = purchaseId, PurchaseTime = DateTime.UtcNow, User = user, UserId = user.Id, @@ -170,5 +215,7 @@ private async Task CreateTicketPurchasesAsync(CartDto cart, Purchase purchase) purchase.TicketPurchases = ticketPurchases; } } + + #endregion } } diff --git a/NetEvent/Server/Helpers/DtoMapper.cs b/NetEvent/Server/Helpers/DtoMapper.cs index 776f3d90..cdbcd18e 100644 --- a/NetEvent/Server/Helpers/DtoMapper.cs +++ b/NetEvent/Server/Helpers/DtoMapper.cs @@ -67,5 +67,7 @@ public static partial class DtoMapper public static partial CheckoutSessionDto ToCheckoutSessionDto(this CreateCheckoutSessionResponse createCheckoutSessionResponse); public static partial PaymentMethodDto ToPaymentMethodDto(this PaymentMethod paymentMethods); + + public static partial PurchaseDto ToPurchaseDto(this Purchase purchase); } } diff --git a/NetEvent/Server/Migrations/Psql/20230216225406_ChangePurchaseIdType.Designer.cs b/NetEvent/Server/Migrations/Psql/20230216225406_ChangePurchaseIdType.Designer.cs new file mode 100644 index 00000000..e5268ee2 --- /dev/null +++ b/NetEvent/Server/Migrations/Psql/20230216225406_ChangePurchaseIdType.Designer.cs @@ -0,0 +1,831 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NetEvent.Server.Data; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace NetEvent.Server.Migrations.Psql +{ + [DbContext(typeof(PsqlApplicationDbContext))] + [Migration("20230216225406_ChangePurchaseIdType")] + partial class ChangePurchaseIdType + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", (string)null); + + b.HasData( + new + { + Id = 1, + ClaimType = "Admin.Users.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 2, + ClaimType = "Admin.Users.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 3, + ClaimType = "Admin.Roles.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 4, + ClaimType = "Admin.Roles.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 5, + ClaimType = "Admin.System.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 6, + ClaimType = "Admin.System.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 7, + ClaimType = "Admin.Images.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 8, + ClaimType = "Admin.Images.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 9, + ClaimType = "Admin.Events.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 10, + ClaimType = "Admin.Events.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 11, + ClaimType = "Admin.Venues.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 12, + ClaimType = "Admin.Venues.Write", + ClaimValue = "", + RoleId = "admin" + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoles", (string)null); + + b.HasData( + new + { + UserId = "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + RoleId = "admin" + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserTokens", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.ApplicationRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("IsDefault") + .HasColumnType("boolean"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("Role", (string)null); + + b.HasData( + new + { + Id = "user", + IsDefault = true, + Name = "User", + NormalizedName = "USER" + }, + new + { + Id = "orga", + IsDefault = false, + Name = "Orga", + NormalizedName = "ORGA" + }, + new + { + Id = "admin", + IsDefault = false, + Name = "Admin", + NormalizedName = "ADMIN" + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("FirstName") + .HasColumnType("text"); + + b.Property("LastName") + .HasColumnType("text"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("ProfilePicture") + .HasColumnType("bytea"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("User", (string)null); + + b.HasData( + new + { + Id = "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + AccessFailedCount = 0, + ConcurrencyStamp = "b379aa23-f095-4145-baba-e76f442552c0", + Email = "admin@admin.de", + EmailConfirmed = true, + FirstName = "Admin", + LastName = "istrator", + LockoutEnabled = false, + NormalizedEmail = "ADMIN@ADMIN.DE", + NormalizedUserName = "ADMIN", + PasswordHash = "AQAAAAIAAYagAAAAELfWRDoThz05sToVRCMx7OHbxw1L91Pm2RW5UN3xXun3e2YpIX0NJ1s8fmgFZnB+Eg==", + PhoneNumberConfirmed = false, + SecurityStamp = "0c5c2bf4-2389-49dd-bbe2-8c7b3962ef2b", + TwoFactorEnabled = false, + UserName = "admin" + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.EmailTemplate", b => + { + b.Property("TemplateId") + .HasColumnType("text"); + + b.Property("ContentTemplate") + .IsRequired() + .HasColumnType("text"); + + b.Property("SubjectTemplate") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("TemplateId"); + + b.ToTable("EmailTemplates", (string)null); + + b.HasData( + new + { + TemplateId = "UserEmailConfirmEmailTemplate", + ContentTemplate = "

@Model.TemplateVariables[\"firstName\"], welcome to NetEvent.

\n

Please confirm your E-Mail by clicking on the following link:

@Model.TemplateVariables[\"confirmUrl\"] ", + SubjectTemplate = "@Model.TemplateVariables[\"firstName\"], please confirm your E-Mail address." + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("EventFormat") + .HasColumnType("integer"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("ShortDescription") + .HasColumnType("text"); + + b.Property("Slug") + .HasColumnType("text"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("State") + .HasColumnType("integer"); + + b.Property("VenueId") + .HasColumnType("bigint"); + + b.Property("Visibility") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("Slug") + .IsUnique(); + + b.HasIndex("VenueId"); + + b.ToTable("Events", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.EventTicketType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AvailableTickets") + .HasColumnType("bigint"); + + b.Property("Currency") + .HasColumnType("integer"); + + b.Property("EventId") + .HasColumnType("bigint"); + + b.Property("IsGiftable") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("integer"); + + b.Property("SellEndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SellStartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Slug") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("EventId"); + + b.ToTable("EventTicketTypes", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("PurchaseTime") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Purchases", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.SystemImage", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Data") + .HasColumnType("bytea"); + + b.Property("Extension") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("UploadTime") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("SystemImages", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.SystemSettingValue", b => + { + b.Property("Key") + .HasColumnType("text"); + + b.Property("SerializedValue") + .HasColumnType("text"); + + b.HasKey("Key"); + + b.ToTable("SystemSettings", (string)null); + + b.HasData( + new + { + Key = "OrganizationName", + SerializedValue = "NetEvent" + }, + new + { + Key = "HideOrganizationNameInNavBar", + SerializedValue = "False" + }, + new + { + Key = "DataCultureInfo", + SerializedValue = "en-US" + }, + new + { + Key = "Favicon", + SerializedValue = "" + }, + new + { + Key = "Logo", + SerializedValue = "" + }, + new + { + Key = "AboutUs", + SerializedValue = "" + }, + new + { + Key = "LegalNotice", + SerializedValue = "" + }, + new + { + Key = "PrivacyPolicy", + SerializedValue = "" + }, + new + { + Key = "PrimaryColor", + SerializedValue = "" + }, + new + { + Key = "PrimaryTextColor", + SerializedValue = "" + }, + new + { + Key = "SecondaryColor", + SerializedValue = "" + }, + new + { + Key = "SecondaryTextColor", + SerializedValue = "" + }, + new + { + Key = "Background", + SerializedValue = "" + }, + new + { + Key = "AppbarBackground", + SerializedValue = "" + }, + new + { + Key = "AppbarText", + SerializedValue = "" + }, + new + { + Key = "CustomCss", + SerializedValue = "" + }, + new + { + Key = "Standard", + SerializedValue = "True" + }, + new + { + Key = "Steam", + SerializedValue = "False" + }, + new + { + Key = "AdyenApiKey", + SerializedValue = "" + }, + new + { + Key = "AdyenClientKey", + SerializedValue = "" + }, + new + { + Key = "AdyenMerchantAccount", + SerializedValue = "" + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.TicketPurchase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Currency") + .HasColumnType("integer"); + + b.Property("Price") + .HasColumnType("integer"); + + b.Property("PurchaseId") + .HasColumnType("text"); + + b.Property("TicketId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("PurchaseId"); + + b.HasIndex("TicketId"); + + b.ToTable("TicketPurchases", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Venue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("City") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("text"); + + b.Property("Slug") + .HasColumnType("text"); + + b.Property("Street") + .HasColumnType("text"); + + b.Property("ZipCode") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Venues", (string)null); + }); + + modelBuilder.Entity("NetEvent.Shared.Dto.ThemeDto", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ThemeData") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Themes", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.HasOne("NetEvent.Server.Models.Venue", "Venue") + .WithMany() + .HasForeignKey("VenueId"); + + b.Navigation("Venue"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.EventTicketType", b => + { + b.HasOne("NetEvent.Server.Models.Event", "Event") + .WithMany("TicketTypes") + .HasForeignKey("EventId"); + + b.Navigation("Event"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.TicketPurchase", b => + { + b.HasOne("NetEvent.Server.Models.Purchase", "Purchase") + .WithMany("TicketPurchases") + .HasForeignKey("PurchaseId"); + + b.HasOne("NetEvent.Server.Models.EventTicketType", "Ticket") + .WithMany() + .HasForeignKey("TicketId"); + + b.Navigation("Purchase"); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.Navigation("TicketTypes"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => + { + b.Navigation("TicketPurchases"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/NetEvent/Server/Migrations/Psql/20230216225406_ChangePurchaseIdType.cs b/NetEvent/Server/Migrations/Psql/20230216225406_ChangePurchaseIdType.cs new file mode 100644 index 00000000..dfd28096 --- /dev/null +++ b/NetEvent/Server/Migrations/Psql/20230216225406_ChangePurchaseIdType.cs @@ -0,0 +1,69 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace NetEvent.Server.Migrations.Psql +{ + /// + public partial class ChangePurchaseIdType : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "PurchaseId", + table: "TicketPurchases", + type: "text", + nullable: true, + oldClrType: typeof(long), + oldType: "bigint", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Id", + table: "Purchases", + type: "text", + nullable: false, + oldClrType: typeof(long), + oldType: "bigint") + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + migrationBuilder.UpdateData( + table: "User", + keyColumn: "Id", + keyValue: "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + columns: new[] { "ConcurrencyStamp", "PasswordHash", "SecurityStamp" }, + values: new object[] { "b379aa23-f095-4145-baba-e76f442552c0", "AQAAAAIAAYagAAAAELfWRDoThz05sToVRCMx7OHbxw1L91Pm2RW5UN3xXun3e2YpIX0NJ1s8fmgFZnB+Eg==", "0c5c2bf4-2389-49dd-bbe2-8c7b3962ef2b" }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "PurchaseId", + table: "TicketPurchases", + type: "bigint", + nullable: true, + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Id", + table: "Purchases", + type: "bigint", + nullable: false, + oldClrType: typeof(string), + oldType: "text") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + migrationBuilder.UpdateData( + table: "User", + keyColumn: "Id", + keyValue: "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + columns: new[] { "ConcurrencyStamp", "PasswordHash", "SecurityStamp" }, + values: new object[] { "eef6f288-f1da-41c2-81fa-95eae2e69410", "AQAAAAIAAYagAAAAEK8gPOw/LRS1KOMtItdcM8BTgCAcUcbU/Vdonq1PDSC5X/SPhWNjh6eRCVI/eqRktw==", "3806018a-661d-427c-8601-3ee04c4cc6a3" }); + } + } +} diff --git a/NetEvent/Server/Migrations/Psql/PsqlApplicationDbContextModelSnapshot.cs b/NetEvent/Server/Migrations/Psql/PsqlApplicationDbContextModelSnapshot.cs index 01f919ff..044fae65 100644 --- a/NetEvent/Server/Migrations/Psql/PsqlApplicationDbContextModelSnapshot.cs +++ b/NetEvent/Server/Migrations/Psql/PsqlApplicationDbContextModelSnapshot.cs @@ -354,7 +354,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { Id = "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", AccessFailedCount = 0, - ConcurrencyStamp = "eef6f288-f1da-41c2-81fa-95eae2e69410", + ConcurrencyStamp = "b379aa23-f095-4145-baba-e76f442552c0", Email = "admin@admin.de", EmailConfirmed = true, FirstName = "Admin", @@ -362,9 +362,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) LockoutEnabled = false, NormalizedEmail = "ADMIN@ADMIN.DE", NormalizedUserName = "ADMIN", - PasswordHash = "AQAAAAIAAYagAAAAEK8gPOw/LRS1KOMtItdcM8BTgCAcUcbU/Vdonq1PDSC5X/SPhWNjh6eRCVI/eqRktw==", + PasswordHash = "AQAAAAIAAYagAAAAELfWRDoThz05sToVRCMx7OHbxw1L91Pm2RW5UN3xXun3e2YpIX0NJ1s8fmgFZnB+Eg==", PhoneNumberConfirmed = false, - SecurityStamp = "3806018a-661d-427c-8601-3ee04c4cc6a3", + SecurityStamp = "0c5c2bf4-2389-49dd-bbe2-8c7b3962ef2b", TwoFactorEnabled = false, UserName = "admin" }); @@ -488,11 +488,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + b.Property("Id") + .HasColumnType("text"); b.Property("PurchaseTime") .HasColumnType("timestamp with time zone"); @@ -663,8 +660,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Price") .HasColumnType("integer"); - b.Property("PurchaseId") - .HasColumnType("bigint"); + b.Property("PurchaseId") + .HasColumnType("text"); b.Property("TicketId") .HasColumnType("bigint"); diff --git a/NetEvent/Server/Migrations/Sqlite/20230216225358_ChangePurchaseIdType.Designer.cs b/NetEvent/Server/Migrations/Sqlite/20230216225358_ChangePurchaseIdType.Designer.cs new file mode 100644 index 00000000..e57f5788 --- /dev/null +++ b/NetEvent/Server/Migrations/Sqlite/20230216225358_ChangePurchaseIdType.Designer.cs @@ -0,0 +1,814 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NetEvent.Server.Data; + +#nullable disable + +namespace NetEvent.Server.Migrations.Sqlite +{ + [DbContext(typeof(SqliteApplicationDbContext))] + [Migration("20230216225358_ChangePurchaseIdType")] + partial class ChangePurchaseIdType + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.2"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", (string)null); + + b.HasData( + new + { + Id = 1, + ClaimType = "Admin.Users.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 2, + ClaimType = "Admin.Users.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 3, + ClaimType = "Admin.Roles.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 4, + ClaimType = "Admin.Roles.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 5, + ClaimType = "Admin.System.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 6, + ClaimType = "Admin.System.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 7, + ClaimType = "Admin.Images.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 8, + ClaimType = "Admin.Images.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 9, + ClaimType = "Admin.Events.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 10, + ClaimType = "Admin.Events.Write", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 11, + ClaimType = "Admin.Venues.Read", + ClaimValue = "", + RoleId = "admin" + }, + new + { + Id = 12, + ClaimType = "Admin.Venues.Write", + ClaimValue = "", + RoleId = "admin" + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoles", (string)null); + + b.HasData( + new + { + UserId = "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + RoleId = "admin" + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserTokens", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.ApplicationRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("IsDefault") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("Role", (string)null); + + b.HasData( + new + { + Id = "user", + IsDefault = true, + Name = "User", + NormalizedName = "USER" + }, + new + { + Id = "orga", + IsDefault = false, + Name = "Orga", + NormalizedName = "ORGA" + }, + new + { + Id = "admin", + IsDefault = false, + Name = "Admin", + NormalizedName = "ADMIN" + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("FirstName") + .HasColumnType("TEXT"); + + b.Property("LastName") + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProfilePicture") + .HasColumnType("BLOB"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("User", (string)null); + + b.HasData( + new + { + Id = "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + AccessFailedCount = 0, + ConcurrencyStamp = "d07882b0-10fa-4ee6-8bf2-231f80fb4656", + Email = "admin@admin.de", + EmailConfirmed = true, + FirstName = "Admin", + LastName = "istrator", + LockoutEnabled = false, + NormalizedEmail = "ADMIN@ADMIN.DE", + NormalizedUserName = "ADMIN", + PasswordHash = "AQAAAAIAAYagAAAAEJoG+/hCI6v6EHNg+X2s0QzmdcRbSeNwg8rNju5+pXfaezhvxch9oAXvljZaNVeJbg==", + PhoneNumberConfirmed = false, + SecurityStamp = "dce345b2-0622-4092-9182-afc2c76cc50a", + TwoFactorEnabled = false, + UserName = "admin" + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.EmailTemplate", b => + { + b.Property("TemplateId") + .HasColumnType("TEXT"); + + b.Property("ContentTemplate") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SubjectTemplate") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("TemplateId"); + + b.ToTable("EmailTemplates", (string)null); + + b.HasData( + new + { + TemplateId = "UserEmailConfirmEmailTemplate", + ContentTemplate = "

@Model.TemplateVariables[\"firstName\"], welcome to NetEvent.

\n

Please confirm your E-Mail by clicking on the following link:

@Model.TemplateVariables[\"confirmUrl\"] ", + SubjectTemplate = "@Model.TemplateVariables[\"firstName\"], please confirm your E-Mail address." + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("EndDate") + .HasColumnType("TEXT"); + + b.Property("EventFormat") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("ShortDescription") + .HasColumnType("TEXT"); + + b.Property("Slug") + .HasColumnType("TEXT"); + + b.Property("StartDate") + .HasColumnType("TEXT"); + + b.Property("State") + .HasColumnType("INTEGER"); + + b.Property("VenueId") + .HasColumnType("INTEGER"); + + b.Property("Visibility") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("Slug") + .IsUnique(); + + b.HasIndex("VenueId"); + + b.ToTable("Events", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.EventTicketType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AvailableTickets") + .HasColumnType("INTEGER"); + + b.Property("Currency") + .HasColumnType("INTEGER"); + + b.Property("EventId") + .HasColumnType("INTEGER"); + + b.Property("IsGiftable") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("SellEndDate") + .HasColumnType("TEXT"); + + b.Property("SellStartDate") + .HasColumnType("TEXT"); + + b.Property("Slug") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EventId"); + + b.ToTable("EventTicketTypes", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("PurchaseTime") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Purchases", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.SystemImage", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Data") + .HasColumnType("BLOB"); + + b.Property("Extension") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("UploadTime") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("SystemImages", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.SystemSettingValue", b => + { + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("SerializedValue") + .HasColumnType("TEXT"); + + b.HasKey("Key"); + + b.ToTable("SystemSettings", (string)null); + + b.HasData( + new + { + Key = "OrganizationName", + SerializedValue = "NetEvent" + }, + new + { + Key = "HideOrganizationNameInNavBar", + SerializedValue = "False" + }, + new + { + Key = "DataCultureInfo", + SerializedValue = "en-US" + }, + new + { + Key = "Favicon", + SerializedValue = "" + }, + new + { + Key = "Logo", + SerializedValue = "" + }, + new + { + Key = "AboutUs", + SerializedValue = "" + }, + new + { + Key = "LegalNotice", + SerializedValue = "" + }, + new + { + Key = "PrivacyPolicy", + SerializedValue = "" + }, + new + { + Key = "PrimaryColor", + SerializedValue = "" + }, + new + { + Key = "PrimaryTextColor", + SerializedValue = "" + }, + new + { + Key = "SecondaryColor", + SerializedValue = "" + }, + new + { + Key = "SecondaryTextColor", + SerializedValue = "" + }, + new + { + Key = "Background", + SerializedValue = "" + }, + new + { + Key = "AppbarBackground", + SerializedValue = "" + }, + new + { + Key = "AppbarText", + SerializedValue = "" + }, + new + { + Key = "CustomCss", + SerializedValue = "" + }, + new + { + Key = "Standard", + SerializedValue = "True" + }, + new + { + Key = "Steam", + SerializedValue = "False" + }, + new + { + Key = "AdyenApiKey", + SerializedValue = "" + }, + new + { + Key = "AdyenClientKey", + SerializedValue = "" + }, + new + { + Key = "AdyenMerchantAccount", + SerializedValue = "" + }); + }); + + modelBuilder.Entity("NetEvent.Server.Models.TicketPurchase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Currency") + .HasColumnType("INTEGER"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("PurchaseId") + .HasColumnType("TEXT"); + + b.Property("TicketId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PurchaseId"); + + b.HasIndex("TicketId"); + + b.ToTable("TicketPurchases", (string)null); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Venue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("City") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Number") + .HasColumnType("TEXT"); + + b.Property("Slug") + .HasColumnType("TEXT"); + + b.Property("Street") + .HasColumnType("TEXT"); + + b.Property("ZipCode") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Venues", (string)null); + }); + + modelBuilder.Entity("NetEvent.Shared.Dto.ThemeDto", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ThemeData") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Themes", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.HasOne("NetEvent.Server.Models.Venue", "Venue") + .WithMany() + .HasForeignKey("VenueId"); + + b.Navigation("Venue"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.EventTicketType", b => + { + b.HasOne("NetEvent.Server.Models.Event", "Event") + .WithMany("TicketTypes") + .HasForeignKey("EventId"); + + b.Navigation("Event"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => + { + b.HasOne("NetEvent.Server.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.TicketPurchase", b => + { + b.HasOne("NetEvent.Server.Models.Purchase", "Purchase") + .WithMany("TicketPurchases") + .HasForeignKey("PurchaseId"); + + b.HasOne("NetEvent.Server.Models.EventTicketType", "Ticket") + .WithMany() + .HasForeignKey("TicketId"); + + b.Navigation("Purchase"); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Event", b => + { + b.Navigation("TicketTypes"); + }); + + modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => + { + b.Navigation("TicketPurchases"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/NetEvent/Server/Migrations/Sqlite/20230216225358_ChangePurchaseIdType.cs b/NetEvent/Server/Migrations/Sqlite/20230216225358_ChangePurchaseIdType.cs new file mode 100644 index 00000000..88405b2d --- /dev/null +++ b/NetEvent/Server/Migrations/Sqlite/20230216225358_ChangePurchaseIdType.cs @@ -0,0 +1,68 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace NetEvent.Server.Migrations.Sqlite +{ + /// + public partial class ChangePurchaseIdType : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "PurchaseId", + table: "TicketPurchases", + type: "TEXT", + nullable: true, + oldClrType: typeof(long), + oldType: "INTEGER", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Id", + table: "Purchases", + type: "TEXT", + nullable: false, + oldClrType: typeof(long), + oldType: "INTEGER") + .OldAnnotation("Sqlite:Autoincrement", true); + + migrationBuilder.UpdateData( + table: "User", + keyColumn: "Id", + keyValue: "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + columns: new[] { "ConcurrencyStamp", "PasswordHash", "SecurityStamp" }, + values: new object[] { "d07882b0-10fa-4ee6-8bf2-231f80fb4656", "AQAAAAIAAYagAAAAEJoG+/hCI6v6EHNg+X2s0QzmdcRbSeNwg8rNju5+pXfaezhvxch9oAXvljZaNVeJbg==", "dce345b2-0622-4092-9182-afc2c76cc50a" }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "PurchaseId", + table: "TicketPurchases", + type: "INTEGER", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Id", + table: "Purchases", + type: "INTEGER", + nullable: false, + oldClrType: typeof(string), + oldType: "TEXT") + .Annotation("Sqlite:Autoincrement", true); + + migrationBuilder.UpdateData( + table: "User", + keyColumn: "Id", + keyValue: "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", + columns: new[] { "ConcurrencyStamp", "PasswordHash", "SecurityStamp" }, + values: new object[] { "5d10c057-f0c5-4439-9ea5-52da9de25db4", "AQAAAAIAAYagAAAAEHl8xBgwOlrJfSfDpoRyQLa1TdrX7zMysaC62jvZEjAyngzzdjD+zyfPkY2zk66ZGQ==", "83f864b3-fb09-44e4-9e5c-748beadc4af3" }); + } + } +} diff --git a/NetEvent/Server/Migrations/Sqlite/SqliteApplicationDbContextModelSnapshot.cs b/NetEvent/Server/Migrations/Sqlite/SqliteApplicationDbContextModelSnapshot.cs index d28ec9d3..78208921 100644 --- a/NetEvent/Server/Migrations/Sqlite/SqliteApplicationDbContextModelSnapshot.cs +++ b/NetEvent/Server/Migrations/Sqlite/SqliteApplicationDbContextModelSnapshot.cs @@ -345,7 +345,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { Id = "BAFC89CF-4F3E-4595-8256-CCA19C260FBD", AccessFailedCount = 0, - ConcurrencyStamp = "5d10c057-f0c5-4439-9ea5-52da9de25db4", + ConcurrencyStamp = "d07882b0-10fa-4ee6-8bf2-231f80fb4656", Email = "admin@admin.de", EmailConfirmed = true, FirstName = "Admin", @@ -353,9 +353,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) LockoutEnabled = false, NormalizedEmail = "ADMIN@ADMIN.DE", NormalizedUserName = "ADMIN", - PasswordHash = "AQAAAAIAAYagAAAAEHl8xBgwOlrJfSfDpoRyQLa1TdrX7zMysaC62jvZEjAyngzzdjD+zyfPkY2zk66ZGQ==", + PasswordHash = "AQAAAAIAAYagAAAAEJoG+/hCI6v6EHNg+X2s0QzmdcRbSeNwg8rNju5+pXfaezhvxch9oAXvljZaNVeJbg==", PhoneNumberConfirmed = false, - SecurityStamp = "83f864b3-fb09-44e4-9e5c-748beadc4af3", + SecurityStamp = "dce345b2-0622-4092-9182-afc2c76cc50a", TwoFactorEnabled = false, UserName = "admin" }); @@ -475,9 +475,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("NetEvent.Server.Models.Purchase", b => { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); + b.Property("Id") + .HasColumnType("TEXT"); b.Property("PurchaseTime") .HasColumnType("TEXT"); @@ -646,8 +645,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Price") .HasColumnType("INTEGER"); - b.Property("PurchaseId") - .HasColumnType("INTEGER"); + b.Property("PurchaseId") + .HasColumnType("TEXT"); b.Property("TicketId") .HasColumnType("INTEGER"); diff --git a/NetEvent/Server/Models/Purchase.cs b/NetEvent/Server/Models/Purchase.cs index 136cf699..1d3426e1 100644 --- a/NetEvent/Server/Models/Purchase.cs +++ b/NetEvent/Server/Models/Purchase.cs @@ -58,7 +58,7 @@ public class TicketPurchaseRefund public class Purchase { [Key] - public long? Id { get; set; } + public string? Id { get; set; } public DateTime? PurchaseTime { get; set; } @@ -83,7 +83,7 @@ public class TicketPurchase [ForeignKey(nameof(TicketId))] public EventTicketType? Ticket { get; set; } - public long? PurchaseId { get; set; } + public string? PurchaseId { get; set; } [ForeignKey(nameof(PurchaseId))] public Purchase? Purchase { get; set; } diff --git a/NetEvent/Server/Modules/Payment/Endpoints/PostCart.cs b/NetEvent/Server/Modules/Payment/Endpoints/PostCart.cs index ace5aa8d..d79cb01b 100644 --- a/NetEvent/Server/Modules/Payment/Endpoints/PostCart.cs +++ b/NetEvent/Server/Modules/Payment/Endpoints/PostCart.cs @@ -1,11 +1,8 @@ -using System; -using System.Security.Claims; +using System.Security.Claims; using System.Threading; using System.Threading.Tasks; -using Adyen.Model.Checkout; using MediatR; using NetEvent.Server.Data; -using NetEvent.Server.Data.Events; using NetEvent.Shared; using NetEvent.Shared.Dto; @@ -24,8 +21,8 @@ public Handler(IPaymentManager paymentManager) public async Task Handle(Request request, CancellationToken cancellationToken) { - var sessionResponse = await _PaymentManager.PayAsync(request.CartDto, request.User); - var result = sessionResponse.ToCheckoutSessionDto(); + var purchase = await _PaymentManager.PurchaseAsync(request.CartDto, request.User); + var result = purchase.ToPurchaseDto(); return new Response(result); } @@ -44,9 +41,9 @@ public Request(CartDto cartDto, ClaimsPrincipal user) public ClaimsPrincipal User { get; } } - public sealed class Response : ResponseBase + public sealed class Response : ResponseBase { - public Response(CheckoutSessionDto response) : base(response) + public Response(PurchaseDto response) : base(response) { } diff --git a/NetEvent/Server/Modules/Payment/Endpoints/PostDropInData.cs b/NetEvent/Server/Modules/Payment/Endpoints/PostDropInData.cs new file mode 100644 index 00000000..867c4734 --- /dev/null +++ b/NetEvent/Server/Modules/Payment/Endpoints/PostDropInData.cs @@ -0,0 +1,59 @@ +using System.Security.Claims; +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using NetEvent.Server.Data; +using NetEvent.Shared.Dto; +using Json = System.Text.Json; + +namespace NetEvent.Server.Modules.Payment.Endpoints +{ + public static class PostDropInData + { + public sealed class Handler : IRequestHandler + { + private readonly IPaymentManager _PaymentManager; + + public Handler(IPaymentManager paymentManager) + { + _PaymentManager = paymentManager; + } + + public async Task Handle(Request request, CancellationToken cancellationToken) + { + var paymentResponse = await _PaymentManager.SubmitDropInEventDataAsync(request.User, request.PurchaseId, request.PaymentMethodData); + + var paymentResponseJson = Json.JsonSerializer.Serialize(paymentResponse); + var result = new PaymentResponseDto { PaymentResponseJson = paymentResponseJson }; + return new Response(result); + } + } + + public sealed class Request : IRequest + { + public Request(ClaimsPrincipal user, string purchaseId, string paymentMethodData) + { + User = user; + PurchaseId = purchaseId; + PaymentMethodData = paymentMethodData; + } + + public ClaimsPrincipal User { get; } + + public string PaymentMethodData { get; internal set; } + + public string PurchaseId { get; internal set; } + } + + public sealed class Response : ResponseBase + { + public Response(PaymentResponseDto response) : base(response) + { + } + + public Response(ReturnType returnType, string error) : base(returnType, error) + { + } + } + } +} diff --git a/NetEvent/Server/Modules/Payment/PaymentModule.cs b/NetEvent/Server/Modules/Payment/PaymentModule.cs index e469d985..5a86b718 100644 --- a/NetEvent/Server/Modules/Payment/PaymentModule.cs +++ b/NetEvent/Server/Modules/Payment/PaymentModule.cs @@ -18,7 +18,10 @@ public override IEndpointRouteBuilder MapModuleEndpoints(IEndpointRouteBuilder e { // BaseRoute: /api/payment endpoints.MapGet("/paymentmethods/{amount:long}/{currency}", async ([FromRoute] long amount, [FromRoute] CurrencyDto currency, [FromServices] IMediator m) => ToApiResult(await m.Send(new GetPaymentMethods.Request(amount, currency)))); - endpoints.MapPost("/buy", async ([FromBody] CartDto cartDto, ClaimsPrincipal user, [FromServices] IMediator m) => ToApiResult(await m.Send(new PostCart.Request(cartDto, user)))); + endpoints.MapPost("/checkout/buy", async ([FromBody] CartDto cartDto, ClaimsPrincipal user, [FromServices] IMediator m) => ToApiResult(await m.Send(new PostCart.Request(cartDto, user)))); + endpoints.MapPost("/checkout/{purchaseId}/payments", async ([FromRoute] string purchaseId, [FromBody] string paymentMethodData, ClaimsPrincipal user, [FromServices] IMediator m) => ToApiResult(await m.Send(new PostDropInData.Request(user, purchaseId, paymentMethodData)))); + endpoints.MapPost("/checkout/{purchaseId}/payments/details", async ([FromRoute] string purchaseId, [FromBody] string paymentMethodData, ClaimsPrincipal user, [FromServices] IMediator m) => ToApiResult(await m.Send(new PostDropInData.Request(user, purchaseId, paymentMethodData)))); + //endpoints.MapGet("/{venueId:long}", async ([FromRoute] long venueId, [FromServices] IMediator m) => ToApiResult(await m.Send(new GetVenue.Request(venueId)))); //endpoints.MapGet("/{slug}", async ([FromRoute] string slug, [FromServices] IMediator m) => ToApiResult(await m.Send(new GetVenue.Request(slug)))); //endpoints.MapGet("/", async ([FromServices] IMediator m) => ToApiResult(await m.Send(new GetVenues.Request()))); diff --git a/NetEvent/Shared/Dto/CheckoutSessionDto.cs b/NetEvent/Shared/Dto/CheckoutSessionDto.cs index 9c0e4126..acfe6420 100644 --- a/NetEvent/Shared/Dto/CheckoutSessionDto.cs +++ b/NetEvent/Shared/Dto/CheckoutSessionDto.cs @@ -1,4 +1,7 @@ -using System.Text.Json.Serialization; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text.Json.Serialization; +using System.Xml.Linq; namespace NetEvent.Shared.Dto; diff --git a/NetEvent/Shared/Dto/PaymentResponseDto.cs b/NetEvent/Shared/Dto/PaymentResponseDto.cs new file mode 100644 index 00000000..dfa4eda7 --- /dev/null +++ b/NetEvent/Shared/Dto/PaymentResponseDto.cs @@ -0,0 +1,29 @@ +using System; + +using System.Text.Json.Serialization; + +namespace NetEvent.Shared.Dto; + +public class PaymentResponseDto +{ + [JsonPropertyName("paymentResponseJson")] + public string PaymentResponseJson { get; set; } +} + +public class PurchaseDto +{ + [JsonPropertyName("id")] + public string Id { get; set; } + + [JsonPropertyName("purchaseTime")] + public DateTime? PurchaseTime { get; set; } + + [JsonPropertyName("userId")] + public string? UserId { get; set; } + + //[InverseProperty(nameof(TicketPurchase.Purchase))] + //public List? TicketPurchases { get; set; } + + [JsonPropertyName("price")] + public int Price { get; set; } +} From 6ff4f16692b26bbb50dd8ced4d131e87f99dc003 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Tue, 21 Feb 2023 00:11:49 +0100 Subject: [PATCH 22/39] Update Payment --- NetEvent/Client/JavaScripts/src/checkout.js | 9 ++-- .../Pages/Checkout/CheckoutTicket.razor | 5 ++ .../Pages/Checkout/CheckoutTicket.razor.cs | 49 +++++++++++++++++-- NetEvent/Client/Services/PaymentService.cs | 2 +- NetEvent/Server/Data/PaymentManager.cs | 34 ++++++++++--- 5 files changed, 82 insertions(+), 17 deletions(-) diff --git a/NetEvent/Client/JavaScripts/src/checkout.js b/NetEvent/Client/JavaScripts/src/checkout.js index 5745c14e..a9c1b78a 100644 --- a/NetEvent/Client/JavaScripts/src/checkout.js +++ b/NetEvent/Client/JavaScripts/src/checkout.js @@ -23,9 +23,6 @@ const configuration = { export async function startPaymentAsync(clientKey, paymentMethods, checkoutTickets) { - - checkoutTickets.invokeMethodAsync('TestMethod', 123); - configuration.clientKey = clientKey; configuration.paymentMethodsResponse = JSON.parse(paymentMethods); @@ -40,7 +37,8 @@ export async function startPaymentAsync(clientKey, paymentMethods, checkoutTicke dropin.handleAction(responseData.action); } else { // Your function to show the final result to the shopper - showFinalResult(responseData); + //dropin.setStatus(responseData.ResultCode); + checkoutTickets.invokeMethodAsync('ShowResult', responseData.ResultCode, responseData.RefusalReasonCode); } }) .catch(error => { @@ -57,7 +55,8 @@ export async function startPaymentAsync(clientKey, paymentMethods, checkoutTicke dropin.handleAction(response.action); } else { // Your function to show the final result to the shopper - showFinalResult(response); + //dropin.setStatus(responseData.ResultCode); + checkoutTickets.invokeMethod('ShowResult', responseData.ResultCode, responseData.RefusalReasonCode); } }) .catch(error => { diff --git a/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor index 98fbfb9e..10bd8ac0 100644 --- a/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor +++ b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor @@ -34,4 +34,9 @@ else
+@if (_Result != null) +{ + @_Result
@_ResultRefused
+} + @*
*@ diff --git a/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs index 315e2ddc..8277e37d 100644 --- a/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs +++ b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs @@ -25,6 +25,7 @@ using System.Text.Json.Serialization; using System.Text.Json; using System.IO; +using Newtonsoft.Json; namespace NetEvent.Client.Pages.Checkout { @@ -66,6 +67,9 @@ public partial class CheckoutTicket private CheckoutSessionDto? CheckoutSession; private IReadOnlyCollection? PaymentMethods; private PurchaseDto _Purchase; + private Severity _ResultSeverity; + private LocalizedString? _Result; + private LocalizedString? _ResultRefused; protected override async Task OnInitializedAsync() { @@ -96,7 +100,7 @@ private async Task BuyTicketAsync() { PaymentMethods = paymentMethods.ResultData; var clientKey = await SettingsService.GetSystemSettingAsync(SystemSettingGroup.PaymentData, SystemSettings.PaymentData.AdyenClientKey, cts.Token).ConfigureAwait(false); - var paymentMethod = JsonSerializer.Serialize(new { paymentMethods = PaymentMethods }, new JsonSerializerOptions() { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault }); + var paymentMethod = System.Text.Json.JsonSerializer.Serialize(new { paymentMethods = PaymentMethods }, new JsonSerializerOptions() { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault }); await JsRuntime.InvokeVoidAsync("checkout.startPaymentAsync", clientKey?.Value, paymentMethod, DotNetObjectReference.Create(this)).ConfigureAwait(false); } } @@ -108,6 +112,7 @@ private async Task BuyTicketAsync() Console.WriteLine(_Purchase.Id); var dataJson = data.GetRawText(); var paymentResponse = await PaymentService.MakePaymentAsync(_Purchase.Id, dataJson, CancellationToken.None).ConfigureAwait(false); + return paymentResponse?.ResultData?.PaymentResponseJson; } @@ -118,9 +123,47 @@ public Task MakeDetailsCall(object data) } [JSInvokable] - public Task TestMethod(object data) + public void ShowResult(int resultCode, string? refusedCode) { - return Task.FromResult(null); + // https://docs.adyen.com/online-payments/payment-result-codes + switch (resultCode) + { + case 0 /* AuthenticationFinished */: + case 1 /* AuthenticationNotRequired */: + case 2 /* Authorised */: + case 9 /* Received */: + _ResultSeverity = Severity.Success; + break; + case 5 /* Error */: + _ResultSeverity = Severity.Error; + break; + case 3 /* Cancelled */: + case 4 /* ChallengeShopper */: + case 6 /* IdentifyShopper */: + case 7 /* Pending */: + case 8 /* PresentToShopper */: + case 10 /* RedirectShopper */: + _ResultSeverity = Severity.Info; + break; + case 11 /* Refused */: + _ResultSeverity = Severity.Warning; + + + + break; + default: + _ResultSeverity = Severity.Normal; + break; + } + + _Result = Localizer[$"CheckoutTicket.Result.{resultCode}"]; + if (refusedCode != null) + { + // https://docs.adyen.com/development-resources/refusal-reasons + _ResultRefused = Localizer[$"CheckoutTicket.ResultRefused.{refusedCode}"]; + } + + StateHasChanged(); } } } diff --git a/NetEvent/Client/Services/PaymentService.cs b/NetEvent/Client/Services/PaymentService.cs index 71f39be9..c87c63cd 100644 --- a/NetEvent/Client/Services/PaymentService.cs +++ b/NetEvent/Client/Services/PaymentService.cs @@ -87,7 +87,7 @@ public async Task> MakePaymentAsync(string pur var response = await client.PostAsJsonAsync($"api/payment/checkout/{purchaseId}/payments", paymentDataJson, cancellationToken); response.EnsureSuccessStatusCode(); - var paymentResponse = await response.Content.ReadFromJsonAsync().ConfigureAwait(false); + var paymentResponse = await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken).ConfigureAwait(false); return ServiceResult.Success(paymentResponse); } catch (Exception ex) diff --git a/NetEvent/Server/Data/PaymentManager.cs b/NetEvent/Server/Data/PaymentManager.cs index f3660d39..93a319f6 100644 --- a/NetEvent/Server/Data/PaymentManager.cs +++ b/NetEvent/Server/Data/PaymentManager.cs @@ -1,12 +1,15 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using Adyen.Model.Checkout; using Adyen.Model.Checkout.Details; +using Adyen.Model.Enum; using Adyen.Service; +using Adyen.Util; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -17,6 +20,7 @@ using NetEvent.Shared.Config; using NetEvent.Shared.Dto; using NetEvent.Shared.Dto.Event; +using Newtonsoft.Json; namespace NetEvent.Server.Data { @@ -137,15 +141,29 @@ public async Task PurchaseAsync(CartDto cart, ClaimsPrincipal claimsPr return null; } - var paymentRequest = new PaymentRequest + var paymentRequest = JsonConvert.DeserializeObject(paymentMethodData); + + if (paymentRequest == null) { - PaymentMethod = System.Text.Json.JsonSerializer.Deserialize(paymentMethodData), - MerchantAccount = merchantAccount.SerializedValue, - Reference = purchase.Id, - ReturnUrl = "https://your-company.com/checkout?shopperOrder=12xy..", // TODO Checkout Seite mit Polling/Events/... - Amount = new Amount(currencyGroup.First().Key.ToCurrencyDto().To3DigitIso(), purchase.Price), - //CountryCode = new RegionInfo(CultureInfo.CurrentUICulture.LCID).TwoLetterISORegionName, - }; + // TODO Error + return null; + } + + paymentRequest.MerchantAccount = merchantAccount.SerializedValue; + paymentRequest.Reference = purchase.Id; + paymentRequest.ReturnUrl = "https://your-company.com/checkout?shopperOrder=12xy.."; + paymentRequest.Amount = new Amount(currencyGroup.First().Key.ToCurrencyDto().To3DigitIso(), purchase.Price); + paymentRequest.ShopperInteraction = PaymentRequest.ShopperInteractionEnum.Ecommerce; + + //var paymentRequest = new PaymentRequest + //{ + // PaymentMethod = System.Text.Json.JsonSerializer.Deserialize(paymentMethodData), + // MerchantAccount = merchantAccount.SerializedValue, + // Reference = purchase.Id, + // ReturnUrl = "https://your-company.com/checkout?shopperOrder=12xy..", // TODO Checkout Seite mit Polling/Events/... + // Amount = new Amount(currencyGroup.First().Key.ToCurrencyDto().To3DigitIso(), purchase.Price), + // //CountryCode = new RegionInfo(CultureInfo.CurrentUICulture.LCID).TwoLetterISORegionName, + //}; var client = new Adyen.Client(apiKey.SerializedValue, Adyen.Model.Enum.Environment.Test); var checkout = new Checkout(client); var paymentResult = await checkout.PaymentsAsync(paymentRequest).ConfigureAwait(false); From db2f21b27c19cdba0de339c05ee3852c32bba992 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Tue, 21 Feb 2023 19:55:22 +0100 Subject: [PATCH 23/39] Use Linter --- NetEvent/Client/JavaScripts/package-lock.json | 2035 ++++++++++++++++- NetEvent/Client/JavaScripts/package.json | 5 + .../Client/JavaScripts/src/.eslintrc.json | 15 + NetEvent/Client/JavaScripts/src/checkout.js | 149 +- 4 files changed, 2090 insertions(+), 114 deletions(-) create mode 100644 NetEvent/Client/JavaScripts/src/.eslintrc.json diff --git a/NetEvent/Client/JavaScripts/package-lock.json b/NetEvent/Client/JavaScripts/package-lock.json index cd1bfb5f..6a604db2 100644 --- a/NetEvent/Client/JavaScripts/package-lock.json +++ b/NetEvent/Client/JavaScripts/package-lock.json @@ -13,6 +13,11 @@ }, "devDependencies": { "css-loader": "^6.7.3", + "eslint": "^8.34.0", + "eslint-config-standard": "^17.0.0", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-n": "^15.6.1", + "eslint-plugin-promise": "^6.1.1", "style-loader": "^3.3.1", "webpack": "^5.75.0", "webpack-cli": "^5.0.1" @@ -64,6 +69,62 @@ "node": ">=10.0.0" } }, + "node_modules/@eslint/eslintrc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", + "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", @@ -122,6 +183,41 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@types/applepayjs": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/applepayjs/-/applepayjs-3.0.4.tgz", @@ -164,6 +260,12 @@ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "dev": true }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, "node_modules/@types/node": { "version": "18.13.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", @@ -393,6 +495,15 @@ "acorn": "^8" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -418,6 +529,119 @@ "ajv": "^6.9.1" } }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-includes": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/browserslist": { "version": "4.21.5", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", @@ -452,6 +676,37 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "node_modules/builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dev": true, + "dependencies": { + "semver": "^7.0.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001454", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001454.tgz", @@ -468,6 +723,34 @@ } ] }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -496,6 +779,24 @@ "node": ">=6" } }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/colorette": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", @@ -508,6 +809,12 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, "node_modules/core-js-pure": { "version": "3.28.0", "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.28.0.tgz", @@ -570,6 +877,57 @@ "node": ">=4" } }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dev": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/electron-to-chromium": { "version": "1.4.301", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.301.tgz", @@ -601,71 +959,603 @@ "node": ">=4" } }, + "node_modules/es-abstract": { + "version": "1.21.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.1.tgz", + "integrity": "sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.3", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.4", + "is-array-buffer": "^3.0.1", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.2", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/es-module-lexer": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", "dev": true }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" + "has": "^1.0.3" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, "dependencies": { - "estraverse": "^5.2.0" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" }, "engines": { - "node": ">=4.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, "engines": { - "node": ">=4.0" + "node": ">=6" } }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "engines": { - "node": ">=4.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" + "node_modules/eslint": { + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.34.0.tgz", + "integrity": "sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==", + "dev": true, + "dependencies": { + "@eslint/eslintrc": "^1.4.1", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.4.0", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-standard": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz", + "integrity": "sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peerDependencies": { + "eslint": "^8.0.1", + "eslint-plugin-import": "^2.25.2", + "eslint-plugin-n": "^15.0.0", + "eslint-plugin-promise": "^6.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", + "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.11.0", + "resolve": "^1.22.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", + "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-es": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", + "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==", + "dev": true, + "dependencies": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" + } + }, + "node_modules/eslint-plugin-es/node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.27.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", + "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.1", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.7.4", + "has": "^1.0.3", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.6", + "resolve": "^1.22.1", + "semver": "^6.3.0", + "tsconfig-paths": "^3.14.1" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-n": { + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.6.1.tgz", + "integrity": "sha512-R9xw9OtCRxxaxaszTQmQAlPgM+RdGjaL1akWuY/Fv9fRAi8Wj4CUKc6iYVG8QNRjRuo8/BqVYIpfqberJUEacA==", + "dev": true, + "dependencies": { + "builtins": "^5.0.1", + "eslint-plugin-es": "^4.1.0", + "eslint-utils": "^3.0.0", + "ignore": "^5.1.1", + "is-core-module": "^2.11.0", + "minimatch": "^3.1.2", + "resolve": "^1.22.1", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-promise": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", + "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", + "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz", + "integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" } }, "node_modules/fast-deep-equal": { @@ -680,6 +1570,12 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -689,6 +1585,27 @@ "node": ">= 4.9.1" } }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -702,24 +1619,195 @@ "node": ">=8" } }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, + "node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -732,6 +1820,15 @@ "node": ">= 0.4.0" } }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -741,6 +1838,57 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/icss-utils": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", @@ -753,6 +1901,40 @@ "postcss": "^8.1.0" } }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", @@ -772,6 +1954,45 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/interpret": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", @@ -781,6 +2002,60 @@ "node": ">=10.13.0" } }, + "node_modules/is-array-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz", + "integrity": "sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-core-module": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", @@ -793,6 +2068,78 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -805,6 +2152,95 @@ "node": ">=0.10.0" } }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -834,6 +2270,28 @@ "node": ">= 10.13.0" } }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -846,6 +2304,24 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -855,6 +2331,19 @@ "node": ">=0.10.0" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", @@ -876,6 +2365,12 @@ "node": ">=8" } }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -909,12 +2404,39 @@ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "dependencies": { - "mime-db": "1.52.0" + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 0.6" + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "node_modules/nanoid": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", @@ -927,6 +2449,12 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -939,6 +2467,85 @@ "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", "dev": true }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -975,6 +2582,18 @@ "node": ">=6" } }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -984,6 +2603,15 @@ "node": ">=8" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -1128,6 +2756,15 @@ "url": "https://opencollective.com/preact" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", @@ -1137,6 +2774,26 @@ "node": ">=6" } }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -1163,6 +2820,35 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, "node_modules/resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -1201,6 +2887,54 @@ "node": ">=8" } }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1221,6 +2955,20 @@ } ] }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/schema-utils": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", @@ -1296,6 +3044,20 @@ "node": ">=8" } }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -1324,6 +3086,67 @@ "source-map": "^0.6.0" } }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/style-loader": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", @@ -1428,6 +3251,77 @@ } } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/tsconfig-paths": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", + "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/update-browserslist-db": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", @@ -1620,17 +3514,80 @@ "node": ">= 8" } }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/wildcard": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", "dev": true }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/NetEvent/Client/JavaScripts/package.json b/NetEvent/Client/JavaScripts/package.json index d14bc4d8..5d467918 100644 --- a/NetEvent/Client/JavaScripts/package.json +++ b/NetEvent/Client/JavaScripts/package.json @@ -12,6 +12,11 @@ "license": "ISC", "devDependencies": { "css-loader": "^6.7.3", + "eslint": "^8.34.0", + "eslint-config-standard": "^17.0.0", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-n": "^15.6.1", + "eslint-plugin-promise": "^6.1.1", "style-loader": "^3.3.1", "webpack": "^5.75.0", "webpack-cli": "^5.0.1" diff --git a/NetEvent/Client/JavaScripts/src/.eslintrc.json b/NetEvent/Client/JavaScripts/src/.eslintrc.json new file mode 100644 index 00000000..ce3a62db --- /dev/null +++ b/NetEvent/Client/JavaScripts/src/.eslintrc.json @@ -0,0 +1,15 @@ +{ + "env": { + "browser": true, + "es2021": true + }, + "extends": "standard", + "overrides": [ + ], + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "rules": { + } +} diff --git a/NetEvent/Client/JavaScripts/src/checkout.js b/NetEvent/Client/JavaScripts/src/checkout.js index a9c1b78a..53e22d0a 100644 --- a/NetEvent/Client/JavaScripts/src/checkout.js +++ b/NetEvent/Client/JavaScripts/src/checkout.js @@ -1,83 +1,82 @@ -import AdyenCheckout from '@adyen/adyen-web'; -import '@adyen/adyen-web/dist/adyen.css'; +import AdyenCheckout from '@adyen/adyen-web' +import '@adyen/adyen-web/dist/adyen.css' const configuration = { - //paymentMethodsResponse: paymentMethodsResponse, // The `/paymentMethods` response from the server. - //clientKey: "YOUR_CLIENT_KEY", // Web Drop-in versions before 3.10.1 use originKey instead of clientKey. - locale: "de-DE", - environment: "test", - analytics: { - enabled: false // Set to false to not send analytics data to Adyen. - }, - //paymentMethodsConfiguration: { - // card: { // Example optional configuration for Cards - // hasHolderName: true, - // holderNameRequired: true, - // enableStoreDetails: true, - // hideCVC: false, // Change this to true to hide the CVC field for stored cards - // name: 'Credit or debit card', - // onSubmit: () => { }, // onSubmit configuration for card payments. Overrides the global configuration. - // } - //} -}; - + // paymentMethodsResponse: paymentMethodsResponse, // The `/paymentMethods` response from the server. + // clientKey: "YOUR_CLIENT_KEY", // Web Drop-in versions before 3.10.1 use originKey instead of clientKey. + locale: 'de-DE', + environment: 'test', + analytics: { + enabled: false // Set to false to not send analytics data to Adyen. + } + // paymentMethodsConfiguration: { + // card: { // Example optional configuration for Cards + // hasHolderName: true, + // holderNameRequired: true, + // enableStoreDetails: true, + // hideCVC: false, // Change this to true to hide the CVC field for stored cards + // name: 'Credit or debit card', + // onSubmit: () => { }, // onSubmit configuration for card payments. Overrides the global configuration. + // } + // } +} -export async function startPaymentAsync(clientKey, paymentMethods, checkoutTickets) { - configuration.clientKey = clientKey; - configuration.paymentMethodsResponse = JSON.parse(paymentMethods); +export async function startPaymentAsync (clientKey, paymentMethods, checkoutTickets) { + configuration.clientKey = clientKey + configuration.paymentMethodsResponse = JSON.parse(paymentMethods) - configuration.onSubmit = (state, dropin) => { - // Global configuration for onSubmit - // Your function calling your server to make the `/payments` request - checkoutTickets.invokeMethodAsync('MakePayment', state.data) - .then(response => { - let responseData = JSON.parse(response); - if (responseData.action) { - // Drop-in handles the action object from the /payments response - dropin.handleAction(responseData.action); - } else { - // Your function to show the final result to the shopper - //dropin.setStatus(responseData.ResultCode); - checkoutTickets.invokeMethodAsync('ShowResult', responseData.ResultCode, responseData.RefusalReasonCode); - } - }) - .catch(error => { - throw Error(error); - }); - }; + configuration.onSubmit = (state, dropin) => { + // Global configuration for onSubmit + // Your function calling your server to make the `/payments` request + checkoutTickets.invokeMethodAsync('MakePayment', state.data) + .then(response => { + const responseData = JSON.parse(response) + if (responseData.action) { + // Drop-in handles the action object from the /payments response + dropin.handleAction(responseData.action) + } else { + // Your function to show the final result to the shopper + // dropin.setStatus(responseData.ResultCode); + checkoutTickets.invokeMethodAsync('ShowResult', responseData.ResultCode, responseData.RefusalReasonCode) + } + }) + .catch(error => { + throw Error(error) + }) + } - configuration.onAdditionalDetails = (state, dropin) => { - // Your function calling your server to make a `/payments/details` request - checkoutTickets.invokeMethodAsync('MakeDetailsCall', state.data) - .then(response => { - if (response.action) { - // Drop-in handles the action object from the /payments response - dropin.handleAction(response.action); - } else { - // Your function to show the final result to the shopper - //dropin.setStatus(responseData.ResultCode); - checkoutTickets.invokeMethod('ShowResult', responseData.ResultCode, responseData.RefusalReasonCode); - } - }) - .catch(error => { - throw Error(error); - }); - }; + configuration.onAdditionalDetails = (state, dropin) => { + // Your function calling your server to make a `/payments/details` request + checkoutTickets.invokeMethodAsync('MakeDetailsCall', state.data) + .then(response => { + if (response.action) { + // Drop-in handles the action object from the /payments response + dropin.handleAction(response.action) + } else { + // Your function to show the final result to the shopper + // dropin.setStatus(responseData.ResultCode); + // checkoutTickets.invokeMethod('ShowResult', responseData.ResultCode, responseData.RefusalReasonCode) + } + }) + .catch(error => { + throw Error(error) + }) + } - // Create an instance of AdyenCheckout using the configuration object. - const checkout = await AdyenCheckout(configuration); - // Access the available payment methods for the session. - console.log(clientKey); - console.log(checkout.paymentMethodsResponse); + // Create an instance of AdyenCheckout using the configuration object. + const checkout = await AdyenCheckout(configuration) + // Access the available payment methods for the session. + console.log(clientKey) + console.log(checkout.paymentMethodsResponse) - // Create an instance of the Component and mount it to the container you created. - const dropin = checkout - .create('dropin', { - // Starting from version 4.0.0, Drop-in configuration only accepts props related to itself and cannot contain generic configuration like the onSubmit event. - openFirstPaymentMethod: false - }) - .mount('#dropin-container'); + // Create an instance of the Component and mount it to the container you created. + checkout + .create('dropin', { + // Starting from version 4.0.0, Drop-in configuration only accepts props related to itself and cannot contain generic configuration like the onSubmit event. + openFirstPaymentMethod: false + }) + .mount('#dropin-container') - // TODO Handle RedirectResult - // https://docs.adyen.com/online-payments/web-components#handle-redirect-result -}; \ No newline at end of file + // TODO Handle RedirectResult + // https://docs.adyen.com/online-payments/web-components#handle-redirect-result +}; From d3a804cd13f4ff7a0e7a1153411ee52252a60a9f Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Tue, 21 Feb 2023 20:33:19 +0100 Subject: [PATCH 24/39] Update Nugetpackages --- .../Client.Tests/NetEvent.Client.Tests.csproj | 2 +- NetEvent/Client/NetEvent.Client.csproj | 10 +++---- .../Server.Tests/NetEvent.Server.Tests.csproj | 6 ++--- NetEvent/Server/NetEvent.Server.csproj | 26 +++++++++---------- .../Shared.Tests/NetEvent.Shared.Tests.csproj | 2 +- NetEvent/Shared/NetEvent.Shared.csproj | 6 ++--- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/NetEvent/Client.Tests/NetEvent.Client.Tests.csproj b/NetEvent/Client.Tests/NetEvent.Client.Tests.csproj index 279e1e48..0678add6 100644 --- a/NetEvent/Client.Tests/NetEvent.Client.Tests.csproj +++ b/NetEvent/Client.Tests/NetEvent.Client.Tests.csproj @@ -11,7 +11,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/NetEvent/Client/NetEvent.Client.csproj b/NetEvent/Client/NetEvent.Client.csproj index ab5dffc3..ebd62406 100644 --- a/NetEvent/Client/NetEvent.Client.csproj +++ b/NetEvent/Client/NetEvent.Client.csproj @@ -27,14 +27,14 @@ - - - + + + - - + + diff --git a/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj b/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj index b87d7f1b..9bf80da9 100644 --- a/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj +++ b/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj @@ -12,10 +12,10 @@ - - + + - + all diff --git a/NetEvent/Server/NetEvent.Server.csproj b/NetEvent/Server/NetEvent.Server.csproj index b56c4646..fe7942dc 100644 --- a/NetEvent/Server/NetEvent.Server.csproj +++ b/NetEvent/Server/NetEvent.Server.csproj @@ -18,24 +18,24 @@ - - - - - - - - - - + + + + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + diff --git a/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj b/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj index cee851f9..7d6dacb5 100644 --- a/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj +++ b/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj @@ -10,7 +10,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/NetEvent/Shared/NetEvent.Shared.csproj b/NetEvent/Shared/NetEvent.Shared.csproj index 23e938fc..93047bc5 100644 --- a/NetEvent/Shared/NetEvent.Shared.csproj +++ b/NetEvent/Shared/NetEvent.Shared.csproj @@ -9,9 +9,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive From d49a55b978d59d37aa07f39fb28c9c17216ce81b Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Wed, 8 Mar 2023 19:58:25 +0100 Subject: [PATCH 25/39] Update packages --- NetEvent/Client/JavaScripts/package-lock.json | 396 +++++++++--------- NetEvent/Client/NetEvent.Client.csproj | 4 +- NetEvent/Server/NetEvent.Server.csproj | 4 +- 3 files changed, 198 insertions(+), 206 deletions(-) diff --git a/NetEvent/Client/JavaScripts/package-lock.json b/NetEvent/Client/JavaScripts/package-lock.json index 6a604db2..2e3a1de3 100644 --- a/NetEvent/Client/JavaScripts/package-lock.json +++ b/NetEvent/Client/JavaScripts/package-lock.json @@ -24,9 +24,9 @@ } }, "node_modules/@adyen/adyen-web": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@adyen/adyen-web/-/adyen-web-5.33.0.tgz", - "integrity": "sha512-UKYjlEVasf4D4ujVxsAb9dvY+oDhNxM7KaBZMFJ7l3sU9bHE037g3Y1+3yraUxJaHfSJQnNVHGrTd3QmQZntbA==", + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@adyen/adyen-web/-/adyen-web-5.35.0.tgz", + "integrity": "sha512-2WjRTXoNq/laUIymufeyo5CgOHM2+nIdpxzSeIcAU6AH9qvLLpcfRcLkR+VDiFC32wj7PGSrrEDe6sLYSyq0sg==", "dependencies": { "@babel/runtime": "^7.15.4", "@babel/runtime-corejs3": "^7.20.1", @@ -38,9 +38,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.20.13", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz", - "integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", + "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", "dependencies": { "regenerator-runtime": "^0.13.11" }, @@ -49,9 +49,9 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.20.13", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.20.13.tgz", - "integrity": "sha512-p39/6rmY9uvlzRiLZBIB3G9/EBr66LBMcYm7fIDeSBNdRjF2AGD3rFZucUyAgGHC2N+7DdLvVi33uTjSE44FIw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.21.0.tgz", + "integrity": "sha512-TDD4UJzos3JJtM+tHX+w2Uc+KWj7GV+VKKFdMVd2Rx8sdA19hcc3P3AHFYd5LVOw+pYuSd5lICC3gm52B6Rwxw==", "dependencies": { "core-js-pure": "^3.25.1", "regenerator-runtime": "^0.13.11" @@ -70,9 +70,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", - "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz", + "integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -92,6 +92,15 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/js": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz", + "integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.8", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", @@ -267,9 +276,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.13.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", - "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==", + "version": "18.14.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.6.tgz", + "integrity": "sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==", "dev": true }, "node_modules/@webassemblyjs/ast": { @@ -708,9 +717,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001454", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001454.tgz", - "integrity": "sha512-4E63M5TBbgDoA9dQoFRdjL6iAmzTrz3rwYWoKDlvnvyvBxjCZ0rrUoX3THhEMie0/RYuTCeMbeTYLGAWgnLwEg==", + "version": "1.0.30001462", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001462.tgz", + "integrity": "sha512-PDd20WuOBPiasZ7KbFnmQRyuLE7cFXW2PVd7dmALzbkUXEP46upAuCDm9eY9vho8fgNMGmbAX92QBZHzcnWIqw==", "dev": true, "funding": [ { @@ -739,18 +748,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -816,9 +813,9 @@ "dev": true }, "node_modules/core-js-pure": { - "version": "3.28.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.28.0.tgz", - "integrity": "sha512-DSOVleA9/v3LNj/vFxAPfUHttKTzrB2RXhAPvR5TPXn4vrra3Z2ssytvRyt8eruJwAfwAiFADEbrjcRdcvPLQQ==", + "version": "3.29.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.29.0.tgz", + "integrity": "sha512-v94gUjN5UTe1n0yN/opTihJ8QBWD2O8i19RfTZR7foONPWArnjB96QA/wk5ozu1mm6ja3udQCzOzwQXTxi3xOQ==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -929,9 +926,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.301", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.301.tgz", - "integrity": "sha512-bz00ASIIDjcgszZKuEA1JEFhbDjqUNbQ/PEhNEl1wbixzYpeTp2H2QWjsQvAL2T1wJBdOwCF5hE896BoMwYKrA==", + "version": "1.4.324", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.324.tgz", + "integrity": "sha512-m+eBs/kh3TXnCuqDF6aHLLRwLK2U471JAbZ1KYigf0TM96fZglxv0/ZFBvyIxnLKsIWUoDiVnHTA2mhYz1fqdA==", "dev": true }, "node_modules/enhanced-resolve": { @@ -1074,12 +1071,13 @@ } }, "node_modules/eslint": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.34.0.tgz", - "integrity": "sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz", + "integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.4.1", + "@eslint/eslintrc": "^2.0.0", + "@eslint/js": "8.35.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -1093,7 +1091,7 @@ "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", "espree": "^9.4.0", - "esquery": "^1.4.0", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", @@ -1341,16 +1339,16 @@ } }, "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=8.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/eslint-utils": { @@ -1389,89 +1387,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/espree": { "version": "9.4.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", @@ -1490,9 +1405,9 @@ } }, "node_modules/esquery": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz", - "integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -1501,15 +1416,6 @@ "node": ">=0.10" } }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -1522,7 +1428,7 @@ "node": ">=4.0" } }, - "node_modules/esrecurse/node_modules/estraverse": { + "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", @@ -1531,15 +1437,6 @@ "node": ">=4.0" } }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -1607,16 +1504,19 @@ } }, "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "dependencies": { - "locate-path": "^5.0.0", + "locate-path": "^6.0.0", "path-exists": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat-cache": { @@ -1926,15 +1826,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", @@ -2003,13 +1894,13 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz", - "integrity": "sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "get-intrinsic": "^1.2.0", "is-typed-array": "^1.1.10" }, "funding": { @@ -2270,6 +2161,21 @@ "node": ">= 10.13.0" } }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/js-sdsl": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", @@ -2354,15 +2260,18 @@ } }, "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { - "p-locate": "^4.1.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash.merge": { @@ -2547,30 +2456,33 @@ } }, "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "p-limit": "^2.2.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-try": { @@ -2645,6 +2557,58 @@ "node": ">=8" } }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/postcss": { "version": "8.4.21", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", @@ -2878,7 +2842,7 @@ "node": ">=8" } }, - "node_modules/resolve-from": { + "node_modules/resolve-cwd/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", @@ -2887,6 +2851,15 @@ "node": ">=8" } }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -3164,18 +3137,15 @@ } }, "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { "has-flag": "^4.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=8" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -3200,9 +3170,9 @@ } }, "node_modules/terser": { - "version": "5.16.3", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz", - "integrity": "sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==", + "version": "5.16.5", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.5.tgz", + "integrity": "sha512-qcwfg4+RZa3YvlFh0qjifnzBHjKGNbtDo9yivMqMFDy9Q6FSaQWSB/j1xKhsoUFJIqDOM3TsN6D5xbrMrFcHbg==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.2", @@ -3258,13 +3228,13 @@ "dev": true }, "node_modules/tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", "dev": true, "dependencies": { "@types/json5": "^0.0.29", - "json5": "^1.0.1", + "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } @@ -3377,9 +3347,9 @@ } }, "node_modules/webpack": { - "version": "5.75.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz", - "integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==", + "version": "5.76.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", + "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", @@ -3499,6 +3469,28 @@ "node": ">=10.13.0" } }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/NetEvent/Client/NetEvent.Client.csproj b/NetEvent/Client/NetEvent.Client.csproj index ebd62406..7412ffc8 100644 --- a/NetEvent/Client/NetEvent.Client.csproj +++ b/NetEvent/Client/NetEvent.Client.csproj @@ -36,7 +36,7 @@ - + all @@ -44,7 +44,7 @@ - + diff --git a/NetEvent/Server/NetEvent.Server.csproj b/NetEvent/Server/NetEvent.Server.csproj index fe7942dc..79e05209 100644 --- a/NetEvent/Server/NetEvent.Server.csproj +++ b/NetEvent/Server/NetEvent.Server.csproj @@ -18,7 +18,7 @@ - + @@ -44,7 +44,7 @@ - + From a5dd3aeb7502cc4824c40951b38fc767cc1a6d51 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Thu, 6 Apr 2023 19:49:17 +0200 Subject: [PATCH 26/39] Fix Build --- NetEvent/Client/NetEvent.Client.csproj | 14 ++--- .../Client/Pages/Administration/Users.razor | 54 ++++++++++--------- .../Pages/Administration/Users.razor.cs | 2 +- .../Pages/Checkout/CheckoutTicket.razor.cs | 2 - .../Server.Tests/NetEvent.Server.Tests.csproj | 4 +- NetEvent/Server/Modules/ModuleBase.cs | 5 +- NetEvent/Server/NetEvent.Server.csproj | 23 ++++---- NetEvent/Shared/NetEvent.Shared.csproj | 4 +- 8 files changed, 55 insertions(+), 53 deletions(-) diff --git a/NetEvent/Client/NetEvent.Client.csproj b/NetEvent/Client/NetEvent.Client.csproj index 7412ffc8..d200973a 100644 --- a/NetEvent/Client/NetEvent.Client.csproj +++ b/NetEvent/Client/NetEvent.Client.csproj @@ -27,14 +27,14 @@ - - - + + + - - + + @@ -42,9 +42,9 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + diff --git a/NetEvent/Client/Pages/Administration/Users.razor b/NetEvent/Client/Pages/Administration/Users.razor index dd4c1567..410659df 100644 --- a/NetEvent/Client/Pages/Administration/Users.razor +++ b/NetEvent/Client/Pages/Administration/Users.razor @@ -7,6 +7,7 @@ @using NetEvent.Shared.Dto; @using NetEvent.Shared.Dto.Administration; @using NetEvent.Shared.Policy; +@using System.Net.Http.Json @@ -21,31 +22,32 @@ CommittedItemChanges="@CommittedUserChangesAsync" QuickFilter="@_usersQuickFilter" Hideable="true"> - + @* @Localizer["Administration.Users.Title"] - + *@ + - - - - - + + + + + - - + + @context.Item.Role?.Name - - + + @@ -57,11 +59,11 @@ } - + - + @* - + *@ @@ -79,25 +81,25 @@ DeletedItemChanges="@DeletedItemChanges" QuickFilter="@_roleQuickFilter" Hideable="true"> - +@* @Localizer["Administration.Users.Roles.Title"] - - - - +*@ + + + - - + + @if (@context.Item.Claims != null) { @@ -123,17 +125,17 @@ } - - + + - + - + @* - + *@ diff --git a/NetEvent/Client/Pages/Administration/Users.razor.cs b/NetEvent/Client/Pages/Administration/Users.razor.cs index 00aeb283..797a9d70 100644 --- a/NetEvent/Client/Pages/Administration/Users.razor.cs +++ b/NetEvent/Client/Pages/Administration/Users.razor.cs @@ -43,7 +43,7 @@ private async Task LoadRoles(CancellationToken cancellationToken) #region Users - public List AllUsers { get; private set; } = new List(); + public IEnumerable AllUsers { get; private set; } = new List(); private string? _UsersSearchString; diff --git a/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs index 8277e37d..404cf3aa 100644 --- a/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs +++ b/NetEvent/Client/Pages/Checkout/CheckoutTicket.razor.cs @@ -148,8 +148,6 @@ public void ShowResult(int resultCode, string? refusedCode) case 11 /* Refused */: _ResultSeverity = Severity.Warning; - - break; default: _ResultSeverity = Severity.Normal; diff --git a/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj b/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj index 9bf80da9..26bf4e09 100644 --- a/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj +++ b/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/NetEvent/Server/Modules/ModuleBase.cs b/NetEvent/Server/Modules/ModuleBase.cs index f438018f..0b215bf7 100644 --- a/NetEvent/Server/Modules/ModuleBase.cs +++ b/NetEvent/Server/Modules/ModuleBase.cs @@ -18,7 +18,10 @@ public abstract class ModuleBase : IModule public virtual IServiceCollection RegisterModule(IServiceCollection builder) { - builder.AddMediatR(typeof(ModuleBase)); + builder.AddMediatR(c => + { + c.RegisterServicesFromAssemblyContaining(); + }); return builder; } diff --git a/NetEvent/Server/NetEvent.Server.csproj b/NetEvent/Server/NetEvent.Server.csproj index 79e05209..0a471804 100644 --- a/NetEvent/Server/NetEvent.Server.csproj +++ b/NetEvent/Server/NetEvent.Server.csproj @@ -19,22 +19,21 @@ - - - - - - - - - + + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + @@ -43,7 +42,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/NetEvent/Shared/NetEvent.Shared.csproj b/NetEvent/Shared/NetEvent.Shared.csproj index 93047bc5..eda16ba7 100644 --- a/NetEvent/Shared/NetEvent.Shared.csproj +++ b/NetEvent/Shared/NetEvent.Shared.csproj @@ -10,8 +10,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive From 82c0b728ac69d40cb3f97c082edda63d89e2019d Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Tue, 16 May 2023 20:13:47 +0200 Subject: [PATCH 27/39] Fix Build --- NetEvent/Client/NetEvent.Client.csproj | 12 ++++----- .../Client/Pages/Administration/Users.razor | 4 +-- NetEvent/Directory.Build.props | 1 + .../Server.Tests/NetEvent.Server.Tests.csproj | 4 +-- NetEvent/Server/NetEvent.Server.csproj | 26 +++++++++---------- NetEvent/Shared/NetEvent.Shared.csproj | 6 ++--- 6 files changed, 27 insertions(+), 26 deletions(-) diff --git a/NetEvent/Client/NetEvent.Client.csproj b/NetEvent/Client/NetEvent.Client.csproj index d200973a..3397fca4 100644 --- a/NetEvent/Client/NetEvent.Client.csproj +++ b/NetEvent/Client/NetEvent.Client.csproj @@ -27,14 +27,14 @@ - - - + + + - - + + @@ -44,7 +44,7 @@ - + diff --git a/NetEvent/Client/Pages/Administration/Users.razor b/NetEvent/Client/Pages/Administration/Users.razor index 410659df..67bac6a1 100644 --- a/NetEvent/Client/Pages/Administration/Users.razor +++ b/NetEvent/Client/Pages/Administration/Users.razor @@ -49,7 +49,7 @@ - + @@ -128,7 +128,7 @@ - + diff --git a/NetEvent/Directory.Build.props b/NetEvent/Directory.Build.props index 005b3859..3c003391 100644 --- a/NetEvent/Directory.Build.props +++ b/NetEvent/Directory.Build.props @@ -1,6 +1,7 @@ net7.0 + enable true diff --git a/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj b/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj index 26bf4e09..7f9b8e89 100644 --- a/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj +++ b/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/NetEvent/Server/NetEvent.Server.csproj b/NetEvent/Server/NetEvent.Server.csproj index 0a471804..109dbe7e 100644 --- a/NetEvent/Server/NetEvent.Server.csproj +++ b/NetEvent/Server/NetEvent.Server.csproj @@ -17,24 +17,24 @@ - + - - - - - - - - + + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + @@ -42,7 +42,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/NetEvent/Shared/NetEvent.Shared.csproj b/NetEvent/Shared/NetEvent.Shared.csproj index eda16ba7..6ad60ac1 100644 --- a/NetEvent/Shared/NetEvent.Shared.csproj +++ b/NetEvent/Shared/NetEvent.Shared.csproj @@ -9,9 +9,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive From 97fd2c31e587d224ab5442bd627b3dd9917f5167 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Tue, 16 May 2023 20:18:50 +0200 Subject: [PATCH 28/39] Update Nuget Packages --- CodeCoverage.runsettings | 8 ++--- .../Client.Tests/NetEvent.Client.Tests.csproj | 2 +- NetEvent/Client/NetEvent.Client.csproj | 2 +- .../Server.Tests/NetEvent.Server.Tests.csproj | 2 +- NetEvent/Server/Data/PaymentManager.cs | 29 ++++++++++++------- NetEvent/Server/NetEvent.Server.csproj | 4 +-- .../Shared.Tests/NetEvent.Shared.Tests.csproj | 2 +- 7 files changed, 28 insertions(+), 21 deletions(-) diff --git a/CodeCoverage.runsettings b/CodeCoverage.runsettings index 53ebac6a..2689a749 100644 --- a/CodeCoverage.runsettings +++ b/CodeCoverage.runsettings @@ -1,5 +1,5 @@ - - .*Migrations.* - - + .*Migrations.* + + \ No newline at end of file diff --git a/NetEvent/Client.Tests/NetEvent.Client.Tests.csproj b/NetEvent/Client.Tests/NetEvent.Client.Tests.csproj index 0678add6..9d2aec55 100644 --- a/NetEvent/Client.Tests/NetEvent.Client.Tests.csproj +++ b/NetEvent/Client.Tests/NetEvent.Client.Tests.csproj @@ -11,7 +11,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/NetEvent/Client/NetEvent.Client.csproj b/NetEvent/Client/NetEvent.Client.csproj index 3397fca4..cc43b29c 100644 --- a/NetEvent/Client/NetEvent.Client.csproj +++ b/NetEvent/Client/NetEvent.Client.csproj @@ -35,7 +35,7 @@ - + diff --git a/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj b/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj index 7f9b8e89..47377b38 100644 --- a/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj +++ b/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj @@ -15,7 +15,7 @@ - + all diff --git a/NetEvent/Server/Data/PaymentManager.cs b/NetEvent/Server/Data/PaymentManager.cs index 93a319f6..4f4f8e0b 100644 --- a/NetEvent/Server/Data/PaymentManager.cs +++ b/NetEvent/Server/Data/PaymentManager.cs @@ -1,21 +1,16 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.IO; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; +using Adyen; using Adyen.Model.Checkout; -using Adyen.Model.Checkout.Details; -using Adyen.Model.Enum; -using Adyen.Service; -using Adyen.Util; -using Microsoft.AspNetCore.Identity; +using Adyen.Service.Checkout; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using NetEvent.Server.Helpers; using NetEvent.Server.Models; -using NetEvent.Server.Modules; using NetEvent.Shared; using NetEvent.Shared.Config; using NetEvent.Shared.Dto; @@ -56,8 +51,13 @@ public async Task GetPaymentMethodsAsync(long amount, Cu return null; } - var client = new Adyen.Client(apiKey.SerializedValue, Adyen.Model.Enum.Environment.Test); - var checkout = new Checkout(client); + var config = new Config + { + XApiKey = apiKey.SerializedValue, + Environment = Adyen.Model.Environment.Test + }; + var client = new Adyen.Client(config); + var checkout = new PaymentsService(client); var paymentMethodsRequest = new PaymentMethodsRequest(merchantAccount: merchantAccount.SerializedValue) { @@ -164,8 +164,15 @@ public async Task PurchaseAsync(CartDto cart, ClaimsPrincipal claimsPr // Amount = new Amount(currencyGroup.First().Key.ToCurrencyDto().To3DigitIso(), purchase.Price), // //CountryCode = new RegionInfo(CultureInfo.CurrentUICulture.LCID).TwoLetterISORegionName, //}; - var client = new Adyen.Client(apiKey.SerializedValue, Adyen.Model.Enum.Environment.Test); - var checkout = new Checkout(client); + + //Create the http client + var config = new Config + { + XApiKey = apiKey.SerializedValue, + Environment = Adyen.Model.Environment.Test + }; + var client = new Adyen.Client(config); + var checkout = new PaymentsService(client); var paymentResult = await checkout.PaymentsAsync(paymentRequest).ConfigureAwait(false); return paymentResult; } diff --git a/NetEvent/Server/NetEvent.Server.csproj b/NetEvent/Server/NetEvent.Server.csproj index 109dbe7e..edf02cd8 100644 --- a/NetEvent/Server/NetEvent.Server.csproj +++ b/NetEvent/Server/NetEvent.Server.csproj @@ -1,4 +1,4 @@ - + @@ -17,7 +17,7 @@ - + diff --git a/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj b/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj index 7d6dacb5..0a8c0280 100644 --- a/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj +++ b/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj @@ -10,7 +10,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive From 771266975b5b62449ab6f4d509fb6698e8081dd5 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Tue, 13 Jun 2023 20:26:15 +0200 Subject: [PATCH 29/39] Update Packages --- .../Client.Tests/NetEvent.Client.Tests.csproj | 4 ++-- NetEvent/Client/NetEvent.Client.csproj | 14 ++++++------- .../Server.Tests/NetEvent.Server.Tests.csproj | 10 +++++----- NetEvent/Server/NetEvent.Server.csproj | 20 +++++++++---------- .../Shared.Tests/NetEvent.Shared.Tests.csproj | 4 ++-- NetEvent/Shared/NetEvent.Shared.csproj | 4 ++-- 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/NetEvent/Client.Tests/NetEvent.Client.Tests.csproj b/NetEvent/Client.Tests/NetEvent.Client.Tests.csproj index 9d2aec55..b80a717f 100644 --- a/NetEvent/Client.Tests/NetEvent.Client.Tests.csproj +++ b/NetEvent/Client.Tests/NetEvent.Client.Tests.csproj @@ -11,13 +11,13 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/NetEvent/Client/NetEvent.Client.csproj b/NetEvent/Client/NetEvent.Client.csproj index cc43b29c..4976aaad 100644 --- a/NetEvent/Client/NetEvent.Client.csproj +++ b/NetEvent/Client/NetEvent.Client.csproj @@ -27,14 +27,14 @@ - - - + + + - - + + @@ -43,8 +43,8 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - - + + diff --git a/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj b/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj index 47377b38..c76ecdea 100644 --- a/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj +++ b/NetEvent/Server.Tests/NetEvent.Server.Tests.csproj @@ -12,10 +12,10 @@ - - - - + + + + all @@ -27,7 +27,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/NetEvent/Server/NetEvent.Server.csproj b/NetEvent/Server/NetEvent.Server.csproj index edf02cd8..71144bc6 100644 --- a/NetEvent/Server/NetEvent.Server.csproj +++ b/NetEvent/Server/NetEvent.Server.csproj @@ -17,22 +17,22 @@ - + - - - - - - - - + + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj b/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj index 0a8c0280..bff26773 100644 --- a/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj +++ b/NetEvent/Shared.Tests/NetEvent.Shared.Tests.csproj @@ -10,13 +10,13 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/NetEvent/Shared/NetEvent.Shared.csproj b/NetEvent/Shared/NetEvent.Shared.csproj index 6ad60ac1..abe337f2 100644 --- a/NetEvent/Shared/NetEvent.Shared.csproj +++ b/NetEvent/Shared/NetEvent.Shared.csproj @@ -10,8 +10,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive From ee63883ca185851cb3b2889f04bb42fd96bd890a Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Tue, 13 Jun 2023 20:26:53 +0200 Subject: [PATCH 30/39] Update sonarlint rules --- .sonarlint/NetEvent.slconfig | 14 +- .../lan2play_netevent/CSharp/SonarLint.xml | 10 +- .../lan2play_netevent_css_settings.json | 122 ++++ .sonarlint/lan2play_netevent_js_settings.json | 457 +++++++------- .../lan2play_netevent_secrets_settings.json | 32 + .sonarlint/lan2play_netevent_ts_settings.json | 564 ++++++++++-------- .sonarlint/lan2play_neteventcsharp.ruleset | 27 +- .sonarlint/sonar.settings.json | 11 +- 8 files changed, 795 insertions(+), 442 deletions(-) create mode 100644 .sonarlint/lan2play_netevent_css_settings.json create mode 100644 .sonarlint/lan2play_netevent_secrets_settings.json diff --git a/.sonarlint/NetEvent.slconfig b/.sonarlint/NetEvent.slconfig index ddd40732..8235b069 100644 --- a/.sonarlint/NetEvent.slconfig +++ b/.sonarlint/NetEvent.slconfig @@ -9,15 +9,23 @@ "Profiles": { "CSharp": { "ProfileKey": "AYCLMpKIxLjXNqYUY9ar", - "ProfileTimestamp": "2023-01-12T20:47:45Z" + "ProfileTimestamp": "2023-06-05T13:10:27Z" + }, + "Secrets": { + "ProfileKey": "AYXoTKwx9Ao2yLWbNWjU", + "ProfileTimestamp": "2023-01-25T09:40:14Z" }, "Js": { "ProfileKey": "AYBnUIIyux-I6QpYqqPJ", - "ProfileTimestamp": "2022-12-07T09:34:26Z" + "ProfileTimestamp": "2023-05-02T12:15:49Z" }, "Ts": { "ProfileKey": "AYBnUIIyux-I6QpYqqPW", - "ProfileTimestamp": "2022-12-07T09:41:27Z" + "ProfileTimestamp": "2023-05-02T12:26:51Z" + }, + "Css": { + "ProfileKey": "AYBnUIIyux-I6QpYqqPC", + "ProfileTimestamp": "2023-03-28T08:36:06Z" } } } \ No newline at end of file diff --git a/.sonarlint/lan2play_netevent/CSharp/SonarLint.xml b/.sonarlint/lan2play_netevent/CSharp/SonarLint.xml index f5365f7f..614d6e7c 100644 --- a/.sonarlint/lan2play_netevent/CSharp/SonarLint.xml +++ b/.sonarlint/lan2play_netevent/CSharp/SonarLint.xml @@ -3,7 +3,7 @@ sonar.cs.analyzeGeneratedCode - true + false sonar.cs.file.suffixes @@ -17,6 +17,14 @@ sonar.cs.roslyn.ignoreIssues false + + sonar.exclusions + **/Migrations/**/*,**/*.razor + + + sonar.global.exclusions + **/build-wrapper-dump.json + diff --git a/.sonarlint/lan2play_netevent_css_settings.json b/.sonarlint/lan2play_netevent_css_settings.json new file mode 100644 index 00000000..e554bebb --- /dev/null +++ b/.sonarlint/lan2play_netevent_css_settings.json @@ -0,0 +1,122 @@ +{ + "sonarlint.rules": { + "css:S4659": { + "level": "On", + "parameters": { + "ignorePseudoClasses": "local,global,export,import,deep" + }, + "severity": "Major" + }, + "css:S4655": { + "level": "On", + "severity": "Major" + }, + "css:S4670": { + "level": "On", + "parameters": { + "ignoreTypes": "/^(mat|md|fa)-/", + "ignore": "custom-elements" + }, + "severity": "Critical" + }, + "css:S4649": { + "level": "On", + "severity": "Major" + }, + "css:S4662": { + "level": "On", + "parameters": { + "ignoreAtRules": "value,at-root,content,debug,each,else,error,for,function,if,include,mixin,return,warn,while,extend,use,forward,tailwind,apply,layer,/^@.*/" + }, + "severity": "Major" + }, + "css:S4667": { + "level": "On", + "severity": "Major" + }, + "css:S4648": { + "level": "On", + "severity": "Major" + }, + "css:S4647": { + "level": "On", + "severity": "Blocker" + }, + "css:S1116": { + "level": "On", + "severity": "Minor" + }, + "css:S1128": { + "level": "On", + "severity": "Minor" + }, + "css:S4656": { + "level": "On", + "parameters": { + "ignoreFallbacks": "true" + }, + "severity": "Major" + }, + "css:S4666": { + "level": "On", + "severity": "Major" + }, + "css:S4668": { + "level": "On", + "severity": "Blocker" + }, + "css:S4661": { + "level": "On", + "severity": "Major" + }, + "css:S4663": { + "level": "On", + "severity": "Minor" + }, + "css:S4660": { + "level": "On", + "parameters": { + "ignorePseudoElements": "ng-deep,v-deep,deep" + }, + "severity": "Major" + }, + "css:S4654": { + "level": "On", + "parameters": { + "ignoreSelectors": "/^:export.*/, /^:import.*/", + "ignoreTypes": "composes, /^mso-/" + }, + "severity": "Blocker" + }, + "css:S4657": { + "level": "On", + "severity": "Critical" + }, + "css:S4651": { + "level": "On", + "severity": "Critical" + }, + "css:S4650": { + "level": "On", + "severity": "Blocker" + }, + "css:S4653": { + "level": "On", + "severity": "Blocker" + }, + "css:S4652": { + "level": "On", + "severity": "Major" + }, + "css:S4658": { + "level": "On", + "severity": "Major" + }, + "css:S5362": { + "level": "Off" + }, + "css:S4664": { + "level": "Off" + } + } +} \ No newline at end of file diff --git a/.sonarlint/lan2play_netevent_js_settings.json b/.sonarlint/lan2play_netevent_js_settings.json index bf00a390..8364a2b7 100644 --- a/.sonarlint/lan2play_netevent_js_settings.json +++ b/.sonarlint/lan2play_netevent_js_settings.json @@ -1,10 +1,6 @@ { "sonarlint.rules": { - "javascript:S4138": { - "level": "On", - "severity": "Minor" - }, - "jssecurity:S2631": { + "javascript:S2871": { "level": "On", "severity": "Critical" }, @@ -16,10 +12,18 @@ "level": "On", "severity": "Blocker" }, + "jssecurity:S5696": { + "level": "On", + "severity": "Blocker" + }, "jssecurity:S2076": { "level": "On", "severity": "Blocker" }, + "jssecurity:S6105": { + "level": "On", + "severity": "Blocker" + }, "jssecurity:S5147": { "level": "On", "severity": "Blocker" @@ -28,6 +32,10 @@ "level": "On", "severity": "Blocker" }, + "jssecurity:S3649": { + "level": "On", + "severity": "Blocker" + }, "jssecurity:S5131": { "level": "On", "severity": "Blocker" @@ -40,10 +48,6 @@ "level": "On", "severity": "Blocker" }, - "jssecurity:S6287": { - "level": "On", - "severity": "Blocker" - }, "jssecurity:S6350": { "level": "On", "severity": "Major" @@ -52,63 +56,158 @@ "level": "On", "severity": "Blocker" }, - "javascript:S5732": { + "javascript:S3504": { "level": "On", - "severity": "Minor" + "severity": "Critical" }, - "javascript:S5734": { + "javascript:S2703": { "level": "On", - "severity": "Minor" + "severity": "Blocker" }, - "javascript:S6268": { + "javascript:S2598": { "level": "On", - "severity": "Blocker" + "severity": "Critical" }, - "javascript:S5852": { + "javascript:S4502": { "level": "On", "severity": "Critical" }, - "javascript:S5730": { + "javascript:S5547": { + "level": "On", + "severity": "Critical" + }, + "javascript:S5542": { + "level": "On", + "severity": "Critical" + }, + "javascript:S4423": { + "level": "On", + "severity": "Critical" + }, + "javascript:S2245": { + "level": "On", + "severity": "Critical" + }, + "javascript:S4426": { + "level": "On", + "severity": "Critical" + }, + "javascript:S3330": { "level": "On", "severity": "Minor" }, - "javascript:S5736": { + "javascript:S5527": { + "level": "On", + "severity": "Critical" + }, + "javascript:S4790": { + "level": "On", + "severity": "Critical" + }, + "javascript:S5332": { + "level": "On", + "severity": "Critical" + }, + "javascript:S2068": { + "level": "On", + "parameters": { + "credentialWords": "password, pwd, passwd" + }, + "severity": "Blocker" + }, + "javascript:S6544": { + "level": "On", + "severity": "Major" + }, + "javascript:S6557": { + "level": "On", + "severity": "Major" + }, + "javascript:S2077": { + "level": "On", + "severity": "Major" + }, + "javascript:S6551": { "level": "On", "severity": "Minor" }, - "javascript:S5739": { + "javascript:S2612": { + "level": "On", + "severity": "Major" + }, + "javascript:S4721": { + "level": "On", + "severity": "Major" + }, + "javascript:S6582": { + "level": "On", + "severity": "Major" + }, + "javascript:S6594": { "level": "On", "severity": "Minor" }, - "javascript:S6265": { + "javascript:S4830": { "level": "On", - "severity": "Blocker" + "severity": "Critical" }, - "javascript:S5743": { + "javascript:S2094": { "level": "On", "severity": "Minor" }, - "javascript:S5742": { + "javascript:S5122": { "level": "On", "severity": "Minor" }, - "javascript:S6275": { + "javascript:S2092": { + "level": "On", + "severity": "Minor" + }, + "jssecurity:S2631": { + "level": "On", + "severity": "Critical" + }, + "jssecurity:S6287": { "level": "On", "severity": "Major" }, - "javascript:S6270": { + "javascript:S5732": { + "level": "On", + "severity": "Minor" + }, + "javascript:S5734": { + "level": "On", + "severity": "Minor" + }, + "javascript:S6268": { "level": "On", "severity": "Blocker" }, - "javascript:S6249": { + "javascript:S5852": { "level": "On", "severity": "Critical" }, - "javascript:S4502": { + "javascript:S5730": { "level": "On", - "severity": "Critical" + "severity": "Minor" }, - "javascript:S6245": { + "javascript:S5736": { + "level": "On", + "severity": "Minor" + }, + "javascript:S5739": { + "level": "On", + "severity": "Minor" + }, + "javascript:S5743": { + "level": "On", + "severity": "Minor" + }, + "javascript:S5742": { + "level": "On", + "severity": "Minor" + }, + "javascript:S1472": { "level": "On", "severity": "Minor" }, @@ -131,62 +230,55 @@ "level": "On", "severity": "Minor" }, - "javascript:S5042": { - "level": "On", - "severity": "Critical" - }, - "javascript:S6252": { + "javascript:S1481": { "level": "On", "severity": "Minor" }, - "javascript:S2245": { + "javascript:S5042": { "level": "On", "severity": "Critical" }, - "javascript:S5757": { + "javascript:S5659": { "level": "On", - "severity": "Minor" + "severity": "Critical" }, - "javascript:S3330": { + "javascript:S6509": { "level": "On", "severity": "Minor" }, - "javascript:S5759": { + "javascript:S2819": { "level": "On", - "severity": "Minor" + "severity": "Critical" }, - "javascript:S6281": { + "javascript:S1862": { "level": "On", - "severity": "Critical" + "severity": "Major" }, - "javascript:S4790": { + "javascript:S5876": { "level": "On", "severity": "Critical" }, - "javascript:S6299": { + "javascript:S5757": { "level": "On", - "severity": "Blocker" + "severity": "Minor" }, - "javascript:S5332": { + "javascript:S2486": { "level": "On", - "severity": "Critical" + "severity": "Minor" }, - "javascript:S2068": { + "javascript:S5759": { "level": "On", - "parameters": { - "credentialWords": "password, pwd, passwd" - }, - "severity": "Blocker" + "severity": "Minor" }, - "javascript:S6303": { + "javascript:S2137": { "level": "On", "severity": "Major" }, - "javascript:S6302": { + "javascript:S6299": { "level": "On", "severity": "Blocker" }, - "javascript:S6308": { + "javascript:S1534": { "level": "On", "severity": "Major" }, @@ -202,11 +294,15 @@ }, "severity": "Major" }, - "javascript:S2077": { + "javascript:S2639": { "level": "On", "severity": "Major" }, - "javascript:S6319": { + "javascript:S2755": { + "level": "On", + "severity": "Blocker" + }, + "javascript:S6523": { "level": "On", "severity": "Major" }, @@ -214,11 +310,15 @@ "level": "On", "severity": "Minor" }, + "javascript:S6535": { + "level": "On", + "severity": "Major" + }, "javascript:S5443": { "level": "On", "severity": "Critical" }, - "javascript:S2612": { + "javascript:S6534": { "level": "On", "severity": "Major" }, @@ -226,10 +326,6 @@ "level": "On", "severity": "Critical" }, - "javascript:S4721": { - "level": "On", - "severity": "Major" - }, "javascript:S5148": { "level": "On", "severity": "Minor" @@ -238,43 +334,31 @@ "level": "On", "severity": "Minor" }, - "javascript:S6327": { - "level": "On", - "severity": "Major" - }, - "javascript:S6329": { - "level": "On", - "severity": "Blocker" - }, "javascript:S4036": { "level": "On", "severity": "Minor" }, - "javascript:S6333": { - "level": "On", - "severity": "Blocker" - }, "javascript:S5247": { "level": "On", "severity": "Major" }, - "javascript:S6330": { + "javascript:S4275": { "level": "On", - "severity": "Major" + "severity": "Critical" }, - "javascript:S5122": { + "javascript:S125": { "level": "On", - "severity": "Minor" + "severity": "Major" }, - "javascript:S6332": { + "javascript:S1134": { "level": "On", "severity": "Major" }, - "javascript:S2092": { + "javascript:S1135": { "level": "On", - "severity": "Minor" + "severity": "Info" }, - "javascript:S6480": { + "javascript:S5860": { "level": "On", "severity": "Major" }, @@ -298,30 +382,94 @@ "level": "On", "severity": "Major" }, - "javascript:S5542": { + "javascript:S1527": { "level": "On", - "severity": "Critical" + "severity": "Blocker" }, - "javascript:S6317": { + "javascript:S6442": { "level": "On", - "severity": "Critical" + "severity": "Major" }, - "javascript:S3972": { + "javascript:S4138": { + "level": "On", + "severity": "Minor" + }, + "javascript:S6265": { + "level": "On", + "severity": "Blocker" + }, + "javascript:S6275": { + "level": "On", + "severity": "Major" + }, + "javascript:S6270": { + "level": "On", + "severity": "Blocker" + }, + "javascript:S6249": { "level": "On", "severity": "Critical" }, - "javascript:S6321": { + "javascript:S6245": { "level": "On", "severity": "Minor" }, - "jssecurity:S3649": { + "javascript:S6252": { + "level": "On", + "severity": "Minor" + }, + "javascript:S6281": { + "level": "On", + "severity": "Critical" + }, + "javascript:S6303": { + "level": "On", + "severity": "Major" + }, + "javascript:S6302": { "level": "On", "severity": "Blocker" }, - "javascript:S4423": { + "javascript:S6308": { + "level": "On", + "severity": "Major" + }, + "javascript:S6319": { + "level": "On", + "severity": "Major" + }, + "javascript:S6327": { + "level": "On", + "severity": "Major" + }, + "javascript:S6329": { + "level": "On", + "severity": "Blocker" + }, + "javascript:S6333": { + "level": "On", + "severity": "Blocker" + }, + "javascript:S6330": { + "level": "On", + "severity": "Major" + }, + "javascript:S6332": { + "level": "On", + "severity": "Major" + }, + "javascript:S6317": { "level": "On", "severity": "Critical" }, + "javascript:S3972": { + "level": "On", + "severity": "Critical" + }, + "javascript:S6321": { + "level": "On", + "severity": "Minor" + }, "javascript:S107": { "level": "On", "parameters": { @@ -333,14 +481,6 @@ "level": "On", "severity": "Minor" }, - "javascript:S5547": { - "level": "On", - "severity": "Critical" - }, - "javascript:S4426": { - "level": "On", - "severity": "Critical" - }, "javascript:S2688": { "level": "On", "severity": "Major" @@ -409,58 +549,22 @@ "level": "On", "severity": "Major" }, - "javascript:S6442": { - "level": "On", - "severity": "Major" - }, "javascript:S6441": { "level": "On", "severity": "Major" }, - "jssecurity:S5696": { - "level": "On", - "severity": "Blocker" - }, - "jssecurity:S6105": { - "level": "On", - "severity": "Blocker" - }, - "javascript:S2598": { - "level": "On", - "severity": "Critical" - }, "javascript:S3358": { "level": "On", "severity": "Major" }, - "javascript:S5659": { - "level": "On", - "severity": "Critical" - }, "javascript:S1854": { "level": "On", "severity": "Major" }, - "javascript:S2819": { - "level": "On", - "severity": "Critical" - }, "javascript:S1186": { "level": "On", "severity": "Critical" }, - "javascript:S5876": { - "level": "On", - "severity": "Critical" - }, - "javascript:S5527": { - "level": "On", - "severity": "Critical" - }, - "javascript:S2755": { - "level": "On", - "severity": "Blocker" - }, "javascript:S1874": { "level": "On", "severity": "Minor" @@ -469,18 +573,10 @@ "level": "On", "severity": "Major" }, - "javascript:S4830": { - "level": "On", - "severity": "Critical" - }, "javascript:S1143": { "level": "On", "severity": "Critical" }, - "javascript:S1534": { - "level": "On", - "severity": "Major" - }, "javascript:S1788": { "level": "On", "severity": "Major" @@ -493,14 +589,6 @@ "level": "On", "severity": "Major" }, - "javascript:S1135": { - "level": "On", - "severity": "Info" - }, - "javascript:S1134": { - "level": "On", - "severity": "Major" - }, "javascript:S2681": { "level": "On", "severity": "Major" @@ -557,10 +645,6 @@ "level": "On", "severity": "Critical" }, - "javascript:S3504": { - "level": "On", - "severity": "Critical" - }, "javascript:S3776": { "level": "On", "parameters": { @@ -619,10 +703,6 @@ "level": "On", "severity": "Major" }, - "javascript:S5860": { - "level": "On", - "severity": "Major" - }, "javascript:S5868": { "level": "On", "severity": "Major" @@ -667,10 +747,6 @@ "level": "On", "severity": "Major" }, - "javascript:S1472": { - "level": "On", - "severity": "Minor" - }, "javascript:S1119": { "level": "On", "severity": "Major" @@ -683,14 +759,6 @@ "level": "On", "severity": "Major" }, - "javascript:S2703": { - "level": "On", - "severity": "Blocker" - }, - "javascript:S1862": { - "level": "On", - "severity": "Major" - }, "javascript:S3923": { "level": "On", "severity": "Major" @@ -699,10 +767,6 @@ "level": "On", "severity": "Major" }, - "javascript:S2137": { - "level": "On", - "severity": "Major" - }, "javascript:S2814": { "level": "On", "severity": "Major" @@ -735,10 +799,6 @@ "level": "On", "severity": "Major" }, - "javascript:S2871": { - "level": "On", - "severity": "Critical" - }, "javascript:S2999": { "level": "On", "parameters": { @@ -837,10 +897,6 @@ "level": "On", "severity": "Major" }, - "javascript:S4275": { - "level": "On", - "severity": "Critical" - }, "javascript:S3812": { "level": "On", "severity": "Critical" @@ -860,10 +916,6 @@ "level": "On", "severity": "Minor" }, - "javascript:S1481": { - "level": "On", - "severity": "Minor" - }, "javascript:S2392": { "level": "On", "severity": "Major" @@ -880,10 +932,6 @@ "level": "On", "severity": "Major" }, - "javascript:S1527": { - "level": "On", - "severity": "Blocker" - }, "javascript:S4143": { "level": "On", "severity": "Major" @@ -896,10 +944,6 @@ "level": "On", "severity": "Major" }, - "javascript:S125": { - "level": "On", - "severity": "Major" - }, "javascript:S3626": { "level": "On", "severity": "Minor" @@ -968,6 +1012,22 @@ "level": "On", "severity": "Major" }, + "javascript:S131": { + "level": "Off" + }, + "javascript:S3402": { + "level": "Off" + }, + "javascript:S106": { + "level": "Off" + }, + "javascript:S6522": { + "level": "On", + "severity": "Major" + }, + "javascript:S6480": { + "level": "Off" + }, "javascript:S100": { "level": "Off" }, @@ -1067,15 +1127,9 @@ "javascript:S2817": { "level": "Off" }, - "javascript:S106": { - "level": "Off" - }, "javascript:S1525": { "level": "Off" }, - "javascript:S131": { - "level": "Off" - }, "javascript:S138": { "level": "Off" }, @@ -1193,9 +1247,6 @@ "javascript:S2428": { "level": "Off" }, - "javascript:S3402": { - "level": "Off" - }, "javascript:S3523": { "level": "Off" }, diff --git a/.sonarlint/lan2play_netevent_secrets_settings.json b/.sonarlint/lan2play_netevent_secrets_settings.json new file mode 100644 index 00000000..1a0a4ae7 --- /dev/null +++ b/.sonarlint/lan2play_netevent_secrets_settings.json @@ -0,0 +1,32 @@ +{ + "sonarlint.rules": { + "secrets:S6338": { + "level": "On", + "severity": "Blocker" + }, + "secrets:S6337": { + "level": "On", + "severity": "Blocker" + }, + "secrets:S6290": { + "level": "On", + "severity": "Blocker" + }, + "secrets:S6334": { + "level": "On", + "severity": "Blocker" + }, + "secrets:S6336": { + "level": "On", + "severity": "Blocker" + }, + "secrets:S6335": { + "level": "On", + "severity": "Blocker" + }, + "secrets:S6292": { + "level": "On", + "severity": "Blocker" + } + } +} \ No newline at end of file diff --git a/.sonarlint/lan2play_netevent_ts_settings.json b/.sonarlint/lan2play_netevent_ts_settings.json index 3f927345..0a363ca1 100644 --- a/.sonarlint/lan2play_netevent_ts_settings.json +++ b/.sonarlint/lan2play_netevent_ts_settings.json @@ -1,78 +1,253 @@ { "sonarlint.rules": { - "typescript:S6480": { + "typescript:S6544": { "level": "On", "severity": "Major" }, - "typescript:S4123": { + "tssecurity:S5883": { + "level": "On", + "severity": "Minor" + }, + "tssecurity:S5146": { + "level": "On", + "severity": "Blocker" + }, + "tssecurity:S5696": { + "level": "On", + "severity": "Blocker" + }, + "tssecurity:S2076": { + "level": "On", + "severity": "Blocker" + }, + "tssecurity:S6105": { + "level": "On", + "severity": "Blocker" + }, + "tssecurity:S5147": { + "level": "On", + "severity": "Blocker" + }, + "tssecurity:S5334": { + "level": "On", + "severity": "Blocker" + }, + "tssecurity:S3649": { + "level": "On", + "severity": "Blocker" + }, + "tssecurity:S5131": { + "level": "On", + "severity": "Blocker" + }, + "tssecurity:S5144": { + "level": "On", + "severity": "Major" + }, + "tssecurity:S2083": { + "level": "On", + "severity": "Blocker" + }, + "tssecurity:S6350": { + "level": "On", + "severity": "Major" + }, + "tssecurity:S6096": { + "level": "On", + "severity": "Blocker" + }, + "typescript:S3735": { "level": "On", "severity": "Critical" }, - "typescript:S3863": { + "typescript:S2598": { "level": "On", - "severity": "Minor" + "severity": "Critical" }, - "typescript:S1128": { + "typescript:S4502": { "level": "On", - "severity": "Minor" + "severity": "Critical" }, - "typescript:S5732": { + "typescript:S5547": { + "level": "On", + "severity": "Critical" + }, + "typescript:S5542": { + "level": "On", + "severity": "Critical" + }, + "typescript:S4423": { + "level": "On", + "severity": "Critical" + }, + "typescript:S2245": { + "level": "On", + "severity": "Critical" + }, + "typescript:S4426": { + "level": "On", + "severity": "Critical" + }, + "typescript:S3330": { "level": "On", "severity": "Minor" }, - "typescript:S5734": { + "typescript:S6606": { "level": "On", "severity": "Minor" }, - "typescript:S6268": { + "typescript:S5527": { + "level": "On", + "severity": "Critical" + }, + "typescript:S4790": { + "level": "On", + "severity": "Critical" + }, + "typescript:S5332": { + "level": "On", + "severity": "Critical" + }, + "typescript:S2068": { "level": "On", + "parameters": { + "credentialWords": "password, pwd, passwd" + }, "severity": "Blocker" }, - "typescript:S5852": { + "typescript:S6557": { + "level": "On", + "severity": "Major" + }, + "typescript:S2871": { "level": "On", "severity": "Critical" }, - "typescript:S5730": { + "typescript:S2077": { + "level": "On", + "severity": "Major" + }, + "typescript:S6550": { + "level": "On", + "severity": "Major" + }, + "typescript:S2612": { + "level": "On", + "severity": "Major" + }, + "typescript:S4721": { + "level": "On", + "severity": "Major" + }, + "typescript:S6583": { + "level": "On", + "severity": "Major" + }, + "typescript:S6582": { + "level": "On", + "severity": "Major" + }, + "typescript:S6598": { "level": "On", "severity": "Minor" }, - "typescript:S5736": { + "typescript:S6594": { "level": "On", "severity": "Minor" }, - "typescript:S5739": { + "typescript:S6590": { + "level": "On", + "severity": "Major" + }, + "typescript:S6569": { + "level": "On", + "severity": "Major" + }, + "typescript:S6568": { "level": "On", "severity": "Minor" }, - "typescript:S6265": { + "typescript:S6565": { "level": "On", - "severity": "Blocker" + "severity": "Minor" }, - "typescript:S5743": { + "typescript:S6564": { + "level": "On", + "severity": "Major" + }, + "typescript:S4830": { + "level": "On", + "severity": "Critical" + }, + "typescript:S6578": { + "level": "On", + "severity": "Major" + }, + "typescript:S6572": { + "level": "On", + "severity": "Major" + }, + "typescript:S6571": { "level": "On", "severity": "Minor" }, - "typescript:S5742": { + "typescript:S2094": { "level": "On", "severity": "Minor" }, - "typescript:S6275": { + "typescript:S5122": { + "level": "On", + "severity": "Minor" + }, + "typescript:S2092": { + "level": "On", + "severity": "Minor" + }, + "tssecurity:S2631": { + "level": "On", + "severity": "Critical" + }, + "tssecurity:S6287": { "level": "On", "severity": "Major" }, - "typescript:S6270": { + "typescript:S5732": { + "level": "On", + "severity": "Minor" + }, + "typescript:S5734": { + "level": "On", + "severity": "Minor" + }, + "typescript:S6268": { "level": "On", "severity": "Blocker" }, - "typescript:S6249": { + "typescript:S5852": { "level": "On", "severity": "Critical" }, - "typescript:S4502": { + "typescript:S5730": { "level": "On", - "severity": "Critical" + "severity": "Minor" }, - "typescript:S6245": { + "typescript:S5736": { + "level": "On", + "severity": "Minor" + }, + "typescript:S5739": { + "level": "On", + "severity": "Minor" + }, + "typescript:S5743": { + "level": "On", + "severity": "Minor" + }, + "typescript:S5742": { + "level": "On", + "severity": "Minor" + }, + "typescript:S1472": { "level": "On", "severity": "Minor" }, @@ -99,58 +274,47 @@ "level": "On", "severity": "Critical" }, - "typescript:S6252": { - "level": "On", - "severity": "Minor" - }, - "typescript:S2245": { + "typescript:S5659": { "level": "On", "severity": "Critical" }, - "typescript:S5757": { + "typescript:S6509": { "level": "On", "severity": "Minor" }, - "typescript:S3330": { - "level": "On", - "severity": "Minor" - }, - "typescript:S5759": { + "typescript:S2819": { "level": "On", - "severity": "Minor" + "severity": "Critical" }, - "typescript:S6281": { + "typescript:S1862": { "level": "On", - "severity": "Critical" + "severity": "Major" }, - "typescript:S4790": { + "typescript:S5876": { "level": "On", "severity": "Critical" }, - "typescript:S6299": { + "typescript:S5757": { "level": "On", - "severity": "Blocker" + "severity": "Minor" }, - "typescript:S5332": { + "typescript:S2486": { "level": "On", - "severity": "Critical" + "severity": "Minor" }, - "typescript:S2068": { + "typescript:S5759": { "level": "On", - "parameters": { - "credentialWords": "password, pwd, passwd" - }, - "severity": "Blocker" + "severity": "Minor" }, - "typescript:S6303": { + "typescript:S2137": { "level": "On", "severity": "Major" }, - "typescript:S6302": { + "typescript:S6299": { "level": "On", "severity": "Blocker" }, - "typescript:S6308": { + "typescript:S1534": { "level": "On", "severity": "Major" }, @@ -166,33 +330,37 @@ }, "severity": "Major" }, - "typescript:S2077": { + "typescript:S2639": { "level": "On", "severity": "Major" }, - "typescript:S6319": { + "typescript:S2755": { + "level": "On", + "severity": "Blocker" + }, + "typescript:S6523": { "level": "On", "severity": "Major" }, - "typescript:S5689": { + "typescript:S6522": { "level": "On", - "severity": "Minor" + "severity": "Major" }, - "typescript:S5443": { + "typescript:S5689": { "level": "On", - "severity": "Critical" + "severity": "Minor" }, - "typescript:S2612": { + "typescript:S6535": { "level": "On", "severity": "Major" }, - "typescript:S1523": { + "typescript:S5443": { "level": "On", "severity": "Critical" }, - "typescript:S4721": { + "typescript:S1523": { "level": "On", - "severity": "Major" + "severity": "Critical" }, "typescript:S5148": { "level": "On", @@ -202,121 +370,133 @@ "level": "On", "severity": "Minor" }, + "typescript:S4036": { + "level": "On", + "severity": "Minor" + }, + "typescript:S5247": { + "level": "On", + "severity": "Major" + }, + "typescript:S4275": { + "level": "On", + "severity": "Critical" + }, + "typescript:S6330": { + "level": "On", + "severity": "Major" + }, "typescript:S6327": { "level": "On", "severity": "Major" }, - "typescript:S6329": { + "typescript:S6319": { "level": "On", - "severity": "Blocker" + "severity": "Major" }, - "typescript:S4036": { + "typescript:S6303": { "level": "On", - "severity": "Minor" + "severity": "Major" }, - "typescript:S6333": { + "typescript:S6308": { "level": "On", - "severity": "Blocker" + "severity": "Major" }, - "typescript:S5247": { + "typescript:S6332": { "level": "On", "severity": "Major" }, - "typescript:S6330": { + "typescript:S6275": { "level": "On", "severity": "Major" }, - "typescript:S5122": { + "typescript:S6481": { "level": "On", - "severity": "Minor" + "severity": "Major" }, - "typescript:S6332": { + "typescript:S6478": { "level": "On", "severity": "Major" }, - "typescript:S2092": { + "typescript:S6486": { "level": "On", - "severity": "Minor" + "severity": "Major" }, - "tssecurity:S2631": { + "typescript:S6479": { "level": "On", - "severity": "Critical" + "severity": "Major" }, - "tssecurity:S5883": { + "typescript:S6477": { "level": "On", - "severity": "Minor" + "severity": "Major" }, - "tssecurity:S5146": { + "typescript:S6317": { "level": "On", - "severity": "Blocker" + "severity": "Critical" }, - "tssecurity:S2076": { + "typescript:S6302": { "level": "On", "severity": "Blocker" }, - "tssecurity:S5147": { + "typescript:S6270": { "level": "On", "severity": "Blocker" }, - "tssecurity:S5334": { + "typescript:S6333": { "level": "On", "severity": "Blocker" }, - "tssecurity:S5131": { + "typescript:S6329": { "level": "On", "severity": "Blocker" }, - "tssecurity:S5144": { + "typescript:S5860": { "level": "On", "severity": "Major" }, - "tssecurity:S2083": { - "level": "On", - "severity": "Blocker" - }, - "tssecurity:S6287": { + "typescript:S1848": { "level": "On", - "severity": "Blocker" + "severity": "Major" }, - "tssecurity:S6350": { + "typescript:S6442": { "level": "On", "severity": "Major" }, - "tssecurity:S6096": { + "typescript:S4123": { "level": "On", - "severity": "Blocker" + "severity": "Critical" }, - "typescript:S6486": { + "typescript:S3863": { "level": "On", - "severity": "Major" + "severity": "Minor" }, - "typescript:S6481": { + "typescript:S1128": { "level": "On", - "severity": "Major" + "severity": "Minor" }, - "typescript:S6477": { + "typescript:S6265": { "level": "On", - "severity": "Major" + "severity": "Blocker" }, - "typescript:S6479": { + "typescript:S6249": { "level": "On", - "severity": "Major" + "severity": "Critical" }, - "typescript:S6478": { + "typescript:S6245": { "level": "On", - "severity": "Major" + "severity": "Minor" }, - "typescript:S4325": { + "typescript:S6252": { "level": "On", "severity": "Minor" }, - "typescript:S5542": { + "typescript:S6281": { "level": "On", "severity": "Critical" }, - "typescript:S6317": { + "typescript:S4325": { "level": "On", - "severity": "Critical" + "severity": "Minor" }, "typescript:S3972": { "level": "On", @@ -326,10 +506,6 @@ "level": "On", "severity": "Minor" }, - "typescript:S4423": { - "level": "On", - "severity": "Critical" - }, "typescript:S107": { "level": "On", "parameters": { @@ -345,18 +521,6 @@ "level": "On", "severity": "Minor" }, - "tssecurity:S3649": { - "level": "On", - "severity": "Blocker" - }, - "typescript:S5547": { - "level": "On", - "severity": "Critical" - }, - "typescript:S4426": { - "level": "On", - "severity": "Critical" - }, "typescript:S3776": { "level": "On", "parameters": { @@ -380,10 +544,6 @@ "level": "On", "severity": "Minor" }, - "typescript:S6442": { - "level": "On", - "severity": "Major" - }, "typescript:S6443": { "level": "On", "severity": "Major" @@ -448,42 +608,18 @@ "level": "On", "severity": "Major" }, - "typescript:S2598": { - "level": "On", - "severity": "Critical" - }, "typescript:S3358": { "level": "On", "severity": "Major" }, - "typescript:S5659": { - "level": "On", - "severity": "Critical" - }, "typescript:S1854": { "level": "On", "severity": "Major" }, - "typescript:S2819": { - "level": "On", - "severity": "Critical" - }, "typescript:S1186": { "level": "On", "severity": "Critical" }, - "typescript:S5876": { - "level": "On", - "severity": "Critical" - }, - "typescript:S5527": { - "level": "On", - "severity": "Critical" - }, - "typescript:S2755": { - "level": "On", - "severity": "Blocker" - }, "typescript:S1874": { "level": "On", "severity": "Minor" @@ -492,22 +628,6 @@ "level": "On", "severity": "Major" }, - "typescript:S4830": { - "level": "On", - "severity": "Critical" - }, - "tssecurity:S5696": { - "level": "On", - "severity": "Blocker" - }, - "tssecurity:S6105": { - "level": "On", - "severity": "Blocker" - }, - "typescript:S1534": { - "level": "On", - "severity": "Major" - }, "typescript:S1143": { "level": "On", "severity": "Critical" @@ -560,10 +680,6 @@ "level": "On", "severity": "Major" }, - "typescript:S3735": { - "level": "On", - "severity": "Critical" - }, "typescript:S5843": { "level": "On", "parameters": { @@ -603,10 +719,6 @@ "level": "On", "severity": "Major" }, - "typescript:S5860": { - "level": "On", - "severity": "Major" - }, "typescript:S5868": { "level": "On", "severity": "Major" @@ -659,10 +771,6 @@ "level": "On", "severity": "Major" }, - "typescript:S1472": { - "level": "On", - "severity": "Minor" - }, "typescript:S1119": { "level": "On", "severity": "Major" @@ -679,10 +787,6 @@ "level": "On", "severity": "Critical" }, - "typescript:S1862": { - "level": "On", - "severity": "Major" - }, "typescript:S3923": { "level": "On", "severity": "Major" @@ -691,14 +795,6 @@ "level": "On", "severity": "Major" }, - "typescript:S2137": { - "level": "On", - "severity": "Major" - }, - "typescript:S2814": { - "level": "On", - "severity": "Major" - }, "typescript:S1533": { "level": "On", "severity": "Minor" @@ -715,10 +811,6 @@ "level": "On", "severity": "Major" }, - "typescript:S2871": { - "level": "On", - "severity": "Critical" - }, "typescript:S2999": { "level": "On", "parameters": { @@ -798,10 +890,6 @@ "level": "On", "severity": "Minor" }, - "typescript:S1848": { - "level": "On", - "severity": "Major" - }, "typescript:S3854": { "level": "On", "severity": "Critical" @@ -853,10 +941,6 @@ }, "severity": "Minor" }, - "typescript:S4275": { - "level": "On", - "severity": "Critical" - }, "typescript:S1301": { "level": "On", "severity": "Minor" @@ -928,6 +1012,50 @@ "level": "On", "severity": "Minor" }, + "typescript:S1451": { + "level": "Off" + }, + "typescript:S131": { + "level": "Off" + }, + "typescript:S6551": { + "level": "On", + "severity": "Minor" + }, + "typescript:S3402": { + "level": "Off" + }, + "typescript:S100": { + "level": "Off" + }, + "typescript:S2933": { + "level": "Off" + }, + "typescript:S106": { + "level": "Off" + }, + "typescript:S6534": { + "level": "On", + "severity": "Major" + }, + "typescript:S4023": { + "level": "Off" + }, + "typescript:S4328": { + "level": "Off" + }, + "typescript:S3514": { + "level": "Off" + }, + "typescript:S6480": { + "level": "Off" + }, + "typescript:S6304": { + "level": "Off" + }, + "typescript:S2814": { + "level": "Off" + }, "typescript:S1440": { "level": "Off" }, @@ -940,9 +1068,6 @@ "typescript:S2255": { "level": "Off" }, - "typescript:S6304": { - "level": "Off" - }, "typescript:S4817": { "level": "Off" }, @@ -976,9 +1101,6 @@ "typescript:S138": { "level": "Off" }, - "typescript:S106": { - "level": "Off" - }, "typescript:S1131": { "level": "Off" }, @@ -1042,9 +1164,6 @@ "typescript:S1525": { "level": "Off" }, - "typescript:S1451": { - "level": "Off" - }, "typescript:S2208": { "level": "Off" }, @@ -1054,12 +1173,6 @@ "typescript:S1528": { "level": "Off" }, - "typescript:S131": { - "level": "Off" - }, - "typescript:S100": { - "level": "Off" - }, "typescript:S909": { "level": "Off" }, @@ -1072,9 +1185,6 @@ "typescript:S4204": { "level": "Off" }, - "typescript:S4328": { - "level": "Off" - }, "typescript:S1488": { "level": "Off" }, @@ -1111,9 +1221,6 @@ "typescript:S126": { "level": "Off" }, - "typescript:S2933": { - "level": "Off" - }, "typescript:S109": { "level": "Off" }, @@ -1135,12 +1242,6 @@ "typescript:S2427": { "level": "Off" }, - "typescript:S3514": { - "level": "Off" - }, - "typescript:S3402": { - "level": "Off" - }, "typescript:S3525": { "level": "Off" }, @@ -1212,9 +1313,6 @@ }, "typescript:S3786": { "level": "Off" - }, - "typescript:S4023": { - "level": "Off" } } } \ No newline at end of file diff --git a/.sonarlint/lan2play_neteventcsharp.ruleset b/.sonarlint/lan2play_neteventcsharp.ruleset index cb095d68..5fc77af0 100644 --- a/.sonarlint/lan2play_neteventcsharp.ruleset +++ b/.sonarlint/lan2play_neteventcsharp.ruleset @@ -28,6 +28,7 @@ + @@ -87,17 +88,20 @@ + + + @@ -136,6 +140,7 @@ + @@ -162,6 +167,7 @@ + @@ -172,6 +178,7 @@ + @@ -211,6 +218,7 @@ + @@ -251,6 +259,7 @@ + @@ -345,15 +354,17 @@ - + + + @@ -361,6 +372,7 @@ + @@ -368,6 +380,19 @@ + + + + + + + + + + + + + diff --git a/.sonarlint/sonar.settings.json b/.sonarlint/sonar.settings.json index f2909265..cfbad380 100644 --- a/.sonarlint/sonar.settings.json +++ b/.sonarlint/sonar.settings.json @@ -1 +1,10 @@ -{"sonar.exclusions":["**/Migrations/**/*"],"sonar.global.exclusions":["**/build-wrapper-dump.json"],"sonar.inclusions":[]} \ No newline at end of file +{ + "sonar.exclusions": [ + "**/Migrations/**/*", + "**/*.razor" + ], + "sonar.global.exclusions": [ + "**/build-wrapper-dump.json" + ], + "sonar.inclusions": [] +} \ No newline at end of file From 9e2f61544fdd7eb1fb53c0db74b5eb01f0d52e51 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Tue, 13 Jun 2023 20:29:14 +0200 Subject: [PATCH 31/39] Remove deprecated dependency --- NetEvent/Client/NetEvent.Client.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/NetEvent/Client/NetEvent.Client.csproj b/NetEvent/Client/NetEvent.Client.csproj index 4976aaad..7f142271 100644 --- a/NetEvent/Client/NetEvent.Client.csproj +++ b/NetEvent/Client/NetEvent.Client.csproj @@ -30,7 +30,6 @@ - From 5c2e35ecff16b82a39960f2158004a4583503814 Mon Sep 17 00:00:00 2001 From: TheR00st3r Date: Tue, 13 Jun 2023 21:36:51 +0200 Subject: [PATCH 32/39] Compression and async script --- NetEvent/Client/wwwroot/index.html | 4 ++-- NetEvent/Server/Program.cs | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/NetEvent/Client/wwwroot/index.html b/NetEvent/Client/wwwroot/index.html index bc040a91..26b56a3f 100644 --- a/NetEvent/Client/wwwroot/index.html +++ b/NetEvent/Client/wwwroot/index.html @@ -29,8 +29,8 @@ - - + +